Nesting damage

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

Nesting damage

Postby arawra » Sat May 17, 2014 6:54 am

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)
User avatar
Ayuto
Project Leader
Posts: 2195
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Sat May 17, 2014 8:59 am

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
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Sat May 17, 2014 12:03 pm

Thats because PlayerEntity.isdead is broken use PlayerEntity.pl.deadflag instead.
qazuar
Junior Member
Posts: 16
Joined: Fri Jun 20, 2014 9:05 am

Postby qazuar » Wed Jul 09, 2014 8:28 pm

Any chance for a working example on cs:go?
Predz
Senior Member
Posts: 158
Joined: Wed Aug 08, 2012 9:05 pm
Location: Bristol, United Kingdom

Postby Predz » Thu Jul 10, 2014 8:29 am

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
Hedgehog
Member
Posts: 62
Joined: Sun Nov 03, 2013 8:54 pm

Postby Hedgehog » Wed Aug 20, 2014 1:01 pm

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
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Wed Aug 20, 2014 1:52 pm

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.

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 132 guests