Page 1 of 1
Nesting damage
Posted: Sat May 17, 2014 6:54 am
by arawra
If I would like a player to have bonus damage on attacks, it is possible to modify the victim's health without using PlayerEntity().damage. However, if the damage were to kill a victim, I am not exactly sure where to go with this as that function leads to infinite regression. Adding a check to see if the player is dead did not stop the regression.
Syntax: Select all
@Event
def player_hurt(game_event):
attacker_userid = game_event.get_int('attacker')
victim_userid = game_event.get_int('userid')
attacker = PlayerEntity(attacker_userid)
victim = PlayerEntity(victim_userid)
if attacker.steamid == 'Some steam id':
if not victim.isdead: # Check, however still gets an infinite regression
attacker.damage(index_from_userid(victim_userid), 20, DamageTypes.BULLET, hitgroup=2)
Posted: Sat May 17, 2014 8:59 am
by Ayuto
I think I would use a hook here.
Syntax: Select all
# =============================================================================
# >> IMPORTS
# =============================================================================
import memory
from memory import Convention, Argument, Return
from memory.hooks import PreHook
from basetypes import TakeDamageInfo
from core import PLATFORM
# =============================================================================
# >> CONSTANTS
# =============================================================================
# Signature and symbol for CCSPlayer::OnTakeDamage
if PLATFORM == 'windows':
ON_TAKE_DAMAGE_IDENTIFIER = b'\x55\x8B\xEC\x81\xEC\x44\x01\x2A\x2A\x56' \
b'\x89\x4D\xFC'
else:
ON_TAKE_DAMAGE_IDENTIFIER = '_ZN9CCSPlayer12OnTakeDamageERK15CTakeDamag' \
'eInfo'
# =============================================================================
# >> GLOBAL VARIABLES
# =============================================================================
# Get the server file
server = memory.find_binary('cstrike/bin/server')
# Search for the function pointer and convert it into a Function object
OnTakeDamage = server[ON_TAKE_DAMAGE_IDENTIFIER].make_function(
Convention.THISCALL,
(Argument.POINTER, Argument.POINTER),
Return.VOID
)
# =============================================================================
# >> CALLBACKS
# =============================================================================
@PreHook(OnTakeDamage)
def pre_on_take_damage(args):
'''
Called before damage is applied to a player.
'''
# Convert the second pointer to a TakeDamageInfo object
info = memory.make_object(TakeDamageInfo, args[1])
# Do 20% more damage
info.damage *= 1.2
Posted: Sat May 17, 2014 12:03 pm
by L'In20Cible
Thats because PlayerEntity.isdead is broken use PlayerEntity.pl.deadflag instead.
Posted: Wed Jul 09, 2014 8:28 pm
by qazuar
Any chance for a working example on cs:go?
Posted: Thu Jul 10, 2014 8:29 am
by Predz
Ayuto's hooking of "OnTakeDamage" should work on CSGO., due to the signatures are already supplied in the SourcePython data. I am not to sure how the point_hurt entity has been changed in CSGO, or whether it has changed at all.
I will have a play with this quickly on CSGO, will post back if I find a method of doing this.
EDIT - Found a way to hook all entity damage, so this will add 100 damage to any entity you damage. Tested on Windows CSGO.
Code: Select all
# =============================================================================
# >> IMPORTS
# =============================================================================
from memory import find_binary
from memory import make_object
from memory import Convention
from memory import Argument
from memory import Return
from memory.hooks import PreHook
from basetypes import TakeDamageInfo
from core import PLATFORM
# =============================================================================
# >> CONSTANTS
# =============================================================================
# Signature and symbol for CBaseEntity::TakeDamage
if PLATFORM == 'windows':
IDENTIFIER = b'\x55\x8B\xEC\x83\xE4\xF8\x83\xEC\x70\x56\x57\x8B\xF9\x8B\x0D\x2A\x2A\x2A\x2A\x85\xC9'
else:
IDENTIFIER = '_ZN11CBaseEntity10TakeDamageERK15CTakeDamageInfo'
POINTER = Argument.POINTER
# =============================================================================
# >> GLOBAL VARIABLES
# =============================================================================
server = find_binary('csgo/bin/server')
OnTakeDamage = server[IDENTIFIER].make_function(Convention.THISCALL, (POINTER, POINTER), Return.VOID)
# =============================================================================
# >> CALLBACK
# =============================================================================
@PreHook(OnTakeDamage)
def pre_on_take_damage(args):
info = make_object(TakeDamageInfo, args[1])
info.damage += 100
Posted: Wed Aug 20, 2014 1:01 pm
by Hedgehog
Is it possible to get attacker weapon from TakeDamageInfo object or I should do it through PlayerEntity.active_weapon?
I was trying to do something like this, but both
inflictor and
attacker properties return attacker player index and
weapon always equal -1.
Syntax: Select all
def pre_on_take_damage(args):
'''
Called before damage is applied to a player.
'''
# Convert the second pointer to a TakeDamageInfo object
info = memory.make_object(TakeDamageInfo, args[1])
# Do 20% more damage
info.damage *= 1.2
print(info.inflictor)
print(info.attacker)
print(info.weapon)
CS:S, Windows, July 17 build
Posted: Wed Aug 20, 2014 1:52 pm
by satoon101
Inflictor will return the weapon pointer for grenades (and projectiles I believe, too), so you should first verify that the inflictor and attacker are the same. If they are, then yes, you need to use active_weapon. I am not sure exactly why weapon always returns -1, it does. That is not the fault of the plugin, it is just not set within the engine for some reason.