Page 1 of 1

Preventing death event take_damage

Posted: Tue May 22, 2018 2:29 am
by arawra
When using take_damage it will cause two death notifications and fire player_death twice, once for each weapon. How do I prevent that?

Image

I wouldn't mind preHooking on_take_damage and modifying damage, but I do not know how to access the attacker's information. The only information that seemed to be returned was the victim and damage information pointers.


Edit: The issue also seems to only occur on headshots.

Re: Preventing death event take_damage

Posted: Tue May 22, 2018 2:45 am
by satoon101
You can get the attacker's information from the TakeDamageInfo.
http://wiki.sourcepython.com/developing ... o.attacker


You can also get the weapon used in the attack.
http://wiki.sourcepython.com/developing ... nfo.weapon

Re: Preventing death event take_damage

Posted: Tue May 22, 2018 3:23 am
by arawra
How would I get that information from an event prehook?

Re: Preventing death event take_damage

Posted: Tue May 22, 2018 4:13 am
by satoon101
It's not an "event" pre-hook, it's pre-hooking a function in memory. Events just notify you that some is happening (or primarily 'has' happened). You can hook events, but the effect of doing that is very limited. Here is how you could hook the OnTakeDamage function and get the attacker's info, as well as adjust the damage done:

Syntax: Select all

from entities import TakeDamageInfo
from entities.constants import DamageTypes
from entities.entity import Entity
from entities.hooks import EntityCondition, EntityPreHook
from memory import make_object
from players.entity import Player
from weapons.entity import Weapon

@EntityPreHook(EntityCondition.is_bot_player, 'on_take_damage')
@EntityPreHook(EntityCondition.is_human_player, 'on_take_damage')
def _pre_take_damage(stack_data):
take_damage_info = make_object(TakeDamageInfo, stack_data[1])
attacker = Entity(take_damage_info.attacker)
if attacker.classname != 'player':
return

attacker = Player(attacker.index)
weapon = Weapon(take_damage_info.weapon)

# Only allow knife damage
if weapon.classname != 'weapon_knife':
return

# Increase the damage
take_damage_info.damage += 100

# Change the type of damage
take_damage_info.type = DamageTypes.BURN

# Add a damage type
take_damage_info |= DamageTypes.POISON

Re: Preventing death event take_damage

Posted: Wed May 23, 2018 4:14 am
by arawra
I couldn't help but notice there wasn't a way to access the victim in this case...?

E: OK so on this post you can
viewtopic.php?f=20&t=1468&p=11709&hilit=on_take_damage#p11709

How can you find out what is returned in stack_data?

Re: Preventing death event take_damage

Posted: Sun Jun 03, 2018 7:08 am
by arawra
I'm not finding it possible to modify players' health who are not contained in the pointer argument.

Attempts to use player.take_damage even with skip_hooks=True also always results in a crash.

Syntax: Select all

@SayCommand('test')
def test(command, index, teamOnly):
message(Player(index).get_view_player().health)
# Using this to test the intended target's HP


@EntityPreHook(EntityCondition.is_human_player, 'on_take_damage')
def _pre_take_damage(stack_data):
take_damage_info = make_object(TakeDamageInfo, stack_data[1])
attacker = Entity(take_damage_info.attacker)

if attacker.classname == 'player':
weapon = Weapon(take_damage_info.weapon)
if weapon.classname != 'worldspawn':


victimObject = make_object(Player, stack_data[0])
victim = playerList[victimObject.index]
attacker = playerList[attacker.index]


damage = take_damage_info.damage
p1 = attacker.origin
p2 = victim.origin
distance = math.sqrt(abs(p2[0]**2 - p1[0]**2) + abs(p2[1]**2 - p1[1]**2) + abs(p2[2]**2 - p1[2]**2))
if attacker.getClass() == 'Ranger':
message('ranger')
attacker.speedChange(.05 * attacker.getLevel(), 3)
if True: #attacker.pierce:

message('pierce on')
for cleavedTarget in PlayerIter():
if not cleavedTarget.playerinfo.is_dead() and cleavedTarget.playerinfo.team != attacker.playerinfo.team and cleavedTarget.index != victim.index:

p3 = cleavedTarget.origin
# p1 = attacker, p2 = victim, p3 = cleave target
top = (p2[0] - p1[0]) * (p3[0]-p1[0]) + (p2[1]-p1[1]) * (p3[1]-p1[1])
bottom1 = math.sqrt( (p2[0]-p1[0])**2 + (p2[1]-p1[1])**2)
bottom2 = math.sqrt((p3[0]-p1[0])**2 + (p3[1]-p1[1])**2)
try:
if math.acos( top/(bottom1*bottom2) ) * 180/math.pi < 15:
message("Damaging " + cleavedTarget.name)
cleavedTarget.health - damage # This line does not do anything

except:
pass

if victim.getClass() == 'Paladin':
while victim.armor:
if damage <= 0: break
victim.armor -= 1
damage -= 1


take_damage_info.damage = damage
return

Re: Preventing death event take_damage

Posted: Tue Jun 05, 2018 4:52 pm
by satoon101

Syntax: Select all

cleavedTarget.health - damage # This line does not do anything

That's because you aren't actually setting anything there. You need to use -= not just -