Page 1 of 1

Collision detection

Posted: Sun Oct 09, 2016 1:28 pm
by velocity
How can I check if an entity, such as flashbang collide with a player?

Re: Collision detection

Posted: Sun Oct 09, 2016 1:33 pm
by iPlayer
I use box-like trace if there's no other option.

I can't say that there's no other option in your case. Flashbangs hurt players on direct hit. Even if it's a teammate, as far as I remember, OnTakeDamage function is called.

Re: Collision detection

Posted: Sun Oct 09, 2016 1:38 pm
by velocity
There should be, I have been working with something called

SDKHook(entity, SDKHook_StartTouch, FunctionName); in SourceMod


Code: Select all

public OnEntityCreated(entity, const String:classname[])
{
    // Checks if the entity is a flashbang
    if (StrContains(classname, "flashbang_projectile") != -1)
    {
      SDKHook(entity, SDKHook_StartTouch, StartTouchFlash);   
    }
}


And since I switched to SourcePython I would like to know how to do the same :smile:

Re: Collision detection

Posted: Sun Oct 09, 2016 2:08 pm
by iPlayer
Here's the hook registration & hook body itself.

Syntax: Select all

from entities.entity import Entity
from entities.hooks import EntityCondition, EntityPreHook
from memory import make_object
from messages import SayText2
from players.entity import Player


TARGET_CLASSNAME = 'flashbang_projectile'


@EntityPreHook(
EntityCondition.equals_entity_classname(TARGET_CLASSNAME),
"start_touch")
def pre_start_touch(args):
entity = make_object(Entity, args[0])

# Hook was likely set on CBaseEntity::StartTouch, so we need to filter out other entities
if entity.classname != TARGET_CLASSNAME:
return

# Firstly create an entity out of args[1] and check if it's a player
other = make_object(Entity, args[1])
if not other.is_player():
return

# Secondly, create a player out of args[1]
player = make_object(Player, args[1])

# Do whatever you want
SayText2(
"Flashbang projectile (index={index}) touched player (userid="
"{userid})".format(index=entity.index, userid=player.userid)
).send()

Re: Collision detection

Posted: Sun Oct 09, 2016 2:26 pm
by velocity
Alright I'll test out soon!

Re: Collision detection

Posted: Mon Oct 10, 2016 8:38 pm
by velocity
iPlayer wrote:Here's the hook registration & hook body itself.

Syntax: Select all

from entities.entity import Entity
from entities.hooks import EntityCondition, EntityPreHook
from memory import make_object
from messages import SayText2
from players.entity import Player


TARGET_CLASSNAME = 'flashbang_projectile'


@EntityPreHook(
EntityCondition.equals_entity_classname(TARGET_CLASSNAME),
"start_touch")
def pre_start_touch(args):
entity = make_object(Entity, args[0])

# Hook was likely set on CBaseEntity::StartTouch, so we need to filter out other entities
if entity.classname != TARGET_CLASSNAME:
return

# Firstly create an entity out of args[1] and check if it's a player
other = make_object(Entity, args[1])
if not other.is_player():
return

# Secondly, create a player out of args[1]
player = make_object(Player, args[1])

# Do whatever you want
SayText2(
"Flashbang projectile (index={index}) touched player (userid="
"{userid})".format(index=entity.index, userid=player.userid)
).send()


Yes, it works, but I've noticed something, if I decide to teleport the player inside of pre_start_touch the server crashes?

Syntax: Select all

...

player_prop = Player(player.index)
player_prop.teleport(velocity=Vector(1000,0,1000))

Re: Collision detection

Posted: Tue Oct 11, 2016 10:55 am
by iPlayer
That's related to the issue described in the first post of this thread: http://forums.sourcepython.com/viewtopic.php?f=10&t=1158
That issue has yet to be resolved by the SP team.

You can try going with the post-hook:

Syntax: Select all

from entities.entity import Entity
from entities.hooks import EntityCondition, EntityPostHook
from memory import make_object
from messages import SayText2
from players.entity import Player


TARGET_CLASSNAME = 'flashbang_projectile'


@EntityPostHook(
EntityCondition.equals_entity_classname(TARGET_CLASSNAME),
"start_touch")
def post_start_touch(args, ret_val):
entity = make_object(Entity, args[0])

# Hook was likely set on CBaseEntity::StartTouch, so we need to filter out other entities
if entity.classname != TARGET_CLASSNAME:
return

# Firstly create an entity out of args[1] and check if it's a player
other = make_object(Entity, args[1])
if not other.is_player():
return

# Secondly, create a player out of args[1]
player = make_object(Player, args[1])

# Do whatever you want
SayText2(
"Flashbang projectile (index={index}) touched player (userid="
"{userid})".format(index=entity.index, userid=player.userid)
).send()


I also think that using player.base_velocity instead of player.teleport won't crash the server.

Re: Collision detection

Posted: Tue Oct 11, 2016 3:39 pm
by decompile
Just a short question when I was looking at your code @iPlayer

Why do you use

Syntax: Select all

if entity.classname != TARGET_CLASSNAME:
return


when you already defined the classname in the EntityPostHook?

Syntax: Select all

@EntityPostHook(EntityCondition.equals_entity_classname(TARGET_CLASSNAME), "start_touch")


I have no clue, thats why im asking.

Re: Collision detection

Posted: Tue Oct 11, 2016 3:47 pm
by satoon101
If you look at the comment prior to that line, it is correct. Even though you use that specific entity to hook start_touch, it hooks CBaseEntity::StartTouch. This is because most ServerClasses don't define their own StartTouch implementation. For flashbang_projectile, the first (and only) ServerClass in its hierarchy to define StartTouch is CBaseEntity. Therefore, CBaseEntity::StartTouch is what gets hooked. So, you have to figure out yourself whether or not the hook was called for the specified entity.

This is something we can update in the future, to use the conditions to know when to call specific hooks, but it does not currently do so.

Re: Collision detection

Posted: Tue Oct 11, 2016 3:59 pm
by iPlayer
Yeah, Satoon basically explained it. EntityCondition behavior is a trap if you don't look into it. It only determines what entity will be used to set the hook, not what kind of entity will be called with that hook.
I personally don't think it's something that needs to be changed on SP behalf though, only maybe just in a form of some addition, e.g. yet another EntityCondition filter.