Setting owner_handle of projectiles

Please post any questions about developing your plugin here. Please use the search function before posting!
arawra
Senior Member
Posts: 190
Joined: Fri Jun 21, 2013 6:51 am

Setting owner_handle of projectiles

Postby arawra » Sat Sep 26, 2020 8:29 am

How would I go about setting the owner of a spawned in entity so that damage can be attributed to the player that spawns in the entity?

Syntax: Select all

from players.entity import Player
from entities.entity import Entity
from events import Event
from players.helpers import index_from_userid
from engines.precache import Model
from listeners.tick import Delay

flashbangModel = 'models/weapons/v_eq_flashbang.mdl'

@Event('player_say')
def player_say(e):
player = Player(index_from_userid(e['userid']))
if e['text'] == 'test':
loc = player.get_view_coordinates()
flashbang = Entity.create('molotov_projectile')
flashbang.model = Model(flashbangModel)
flashbang.spawn()
flashbang.origin = loc
flashbang.owner_handle = player.inthandle
Delay(.2, flashbang.detonate)
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: Setting owner_handle of projectiles

Postby L'In20Cible » Sat Sep 26, 2020 8:37 am

arawra wrote:How would I go about setting the owner of a spawned in entity so that damage can be attributed to the player that spawns in the entity?

Syntax: Select all

from players.entity import Player
from entities.entity import Entity
from events import Event
from players.helpers import index_from_userid
from engines.precache import Model
from listeners.tick import Delay

flashbangModel = 'models/weapons/v_eq_flashbang.mdl'

@Event('player_say')
def player_say(e):
player = Player(index_from_userid(e['userid']))
if e['text'] == 'test':
loc = player.get_view_coordinates()
flashbang = Entity.create('molotov_projectile')
flashbang.model = Model(flashbangModel)
flashbang.spawn()
flashbang.origin = loc
flashbang.owner_handle = player.inthandle
Delay(.2, flashbang.detonate)

According to sp dump server_classes classes they have a m_hThrower which I guess is what you want to set.

Syntax: Select all

flashbang.set_network_property_int('m_hThrower', player.inthandle)


EDIT: Actually, we have it aliased as thrower so the following should do it:

Syntax: Select all

flashbang.thrower = player.inthandle
arawra
Senior Member
Posts: 190
Joined: Fri Jun 21, 2013 6:51 am

Re: Setting owner_handle of projectiles

Postby arawra » Sat Sep 26, 2020 9:43 am

Neither of those are working for me :\

Syntax: Select all

@Event('player_say')
def player_say(e):
player = Player(index_from_userid(e['userid']))
if e['text'] == 'test':
degree = (2*pi)/4

x,y,z = player.get_eye_location()
x2,y2,z2 = Vector(x+20,y-20,z)
x3 = (x2-x) * math.cos(degree) - (y2-y) * math.sin(degree)
y3 = (y2-y) * math.cos(degree) + (x2-x) * math.sin(degree)
z3 = z2
flashbang = Entity.create('molotov_projectile')
#flashbang.model = Model(flashbangModel)
flashbang.spawn()
flashbang.origin = Vector(x3+x,y3+y,z3)
flashbang.set_network_property_int('m_hThrower', player.inthandle)
#Delay(.2, flashbang.detonate)
flashbang.teleport(None, flashbang.angles, player.view_vector * 650)
Delay(1.6, flashbang.detonate)
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: Setting owner_handle of projectiles

Postby L'In20Cible » Sun Sep 27, 2020 2:15 am

arawra wrote:Neither of those are working for me :\

Syntax: Select all

@Event('player_say')
def player_say(e):
player = Player(index_from_userid(e['userid']))
if e['text'] == 'test':
degree = (2*pi)/4

x,y,z = player.get_eye_location()
x2,y2,z2 = Vector(x+20,y-20,z)
x3 = (x2-x) * math.cos(degree) - (y2-y) * math.sin(degree)
y3 = (y2-y) * math.cos(degree) + (x2-x) * math.sin(degree)
z3 = z2
flashbang = Entity.create('molotov_projectile')
#flashbang.model = Model(flashbangModel)
flashbang.spawn()
flashbang.origin = Vector(x3+x,y3+y,z3)
flashbang.set_network_property_int('m_hThrower', player.inthandle)
#Delay(.2, flashbang.detonate)
flashbang.teleport(None, flashbang.angles, player.view_vector * 650)
Delay(1.6, flashbang.detonate)

Tried to set both; the owner AND the thrower? Other than that I have no idea. Try to grab an existing one and dig its properties/values and perhaps you may find other stuff that need to be set as well. The team maybe?
User avatar
Kami
Global Moderator
Posts: 263
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Re: Setting owner_handle of projectiles

Postby Kami » Sun Sep 27, 2020 3:52 pm

Have you tried the code with another type of projectile? I'm not sure but I think molotov_projectile creates a new entity called inferno when it explodes. Which would mean that the damage does not come from the projectile but the new entity. I couldn't test that theory though.
Jezza
Junior Member
Posts: 16
Joined: Tue Aug 28, 2012 5:52 pm

Re: Setting owner_handle of projectiles

Postby Jezza » Wed Dec 02, 2020 9:25 pm

After the update of CTakeDamageInfo struct, CTakeDamageInfo::CTakeDamageInfo has also changed.
The second argument of CTakeDamageInfo has been changed from CBaseEntity* to CSGOAttackerInfo*.

Right now CBaseCSGrenadeProjectile(the base class of CMolotovProjectile) contains CSGOAttackerInfo, which will be copied to the inferno on Detonate.
The offset of CSGOAttackerInfo in CBaseCSGrenadeProjectile is 1300 on Linux and 1276 on Windows.
Offset for inferno is 2936 on Linux and 2912 on Windows.

If you want to set the attacker to Projectile, you can create a CustomType like this.

Syntax: Select all

# Source.Python Imports
# Core
import core
# Entities
from entities.entity import Entity
# Memory
from memory import get_object_pointer
from memory import make_object
from memory.manager import CustomType
from memory.manager import Type
from memory.manager import manager

class CSGOAttackerInfo(CustomType, metaclass=manager):

need_init = manager.instance_attribute(Type.BOOL, 0, "bool m_bNeedInit")
handle = manager.instance_attribute(Type.INT, 4, "EHANDLE m_hHndl")
is_player = manager.instance_attribute(Type.BOOL, 8, "bool m_bIsPlayer")
is_world = manager.instance_attribute(Type.BOOL, 9, "bool m_bIsWorld")
client_index = manager.instance_attribute(Type.INT, 12, "int m_iClientIndex")
survival_team = manager.instance_attribute(Type.INT, 16, "int m_nSurvivalTeam")
team_checked = manager.instance_attribute(Type.INT, 20, "int m_iTeamChecked")
team_num = manager.instance_attribute(Type.INT, 24, "int m_iTeamNum")
userid = manager.instance_attribute(Type.INT, 28, "int m_iUserId")

def set_attacker_info(attacker, entity, offset):
attacker_info = make_object(CSGOAttackerInfo, get_object_pointer(entity)+offset)
attacker_info.need_init = False
attacker_info.handle = attacker.inthandle
attacker_info.is_player = True
attacker_info.is_world = False
attacker_info.client_index = attacker.index
attacker_info.survival_team = -1
attacker_info.team_checked = attacker.team_index
attacker_info.team_num = attacker.team_index
attacker_info.userid = attacker.userid

if core.PLATFORM == "linux":
offset = 1300
else:
offset = 1276

def spawn_molotov(attacker, origin):
molotov = Entity.create("molotov_projectile")
molotov.origin = origin

set_attacker_info(attacker, molotov, offset)

molotov.spawn()

molotov.call_input("InitializeSpawnFromWorld")

Or you can use the function that CBaseCSGrenadeProjectile uses to set the attacker.

Syntax: Select all

#   Core
import core
# Entities
from entities.entity import Entity
# Memory
from memory import Convention
from memory import DataType
from memory import find_binary
# Players
from players.entity import Player

if core.PLATFORM == "linux":
signature = b"\x55\x89\xE5\x57\x56\x53\x83\xEC\x2C\xC7\x45\xDC\x00\x00\x00\x00\x8B\x5D\x08"
else:
signature = b"\x55\x8B\xEC\x53\x8B\x5D\x08\x56\x57\x8B\xF9\x53"

# void CBaseCSGrenadeProjectile::SetAttacker( CBaseCSGrenadeProjectile * this , CBaseCombatCharacter * attacker )
set_attacker = find_binary("server", srv_check=False)[signature].make_function(
Convention.THISCALL, (
DataType.POINTER,
DataType.POINTER,
),
DataType.VOID,
)

attacker = Player(1)

molotov = Entity.create("molotov_projectile")
molotov.origin = attacker.origin

set_attacker(molotov, attacker)

molotov.spawn()

molotov.call_input("InitializeSpawnFromWorld")

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 18 guests