View Full Version : Entity Collision

05-04-2016, 09:45 PM
So, I create an entity:

CClientCommand Skill_One( "skill1", "DUMMY", @Skill_One_CB );
void Skill_One_CB( const CCommand@ pArgs )
CBasePlayer@ pPlayer = g_ConCommandSystem.GetCurrentPlayer();

// Get the player's origin and view angles
Vector pOrigin = pPlayer.pev.origin;
Vector pAngles = pPlayer.pev.v_angle;
g_EngineFuncs.MakeVectors( pAngles );
Vector pForward = g_Engine.v_forward;
VectorMA( pOrigin, 16.0, pForward, pOrigin );

// Create the entity
CBaseEntity@ test = g_EntityFuncs.Create( "info_target", pOrigin, pAngles, false, pPlayer.edict() );
g_EntityFuncs.SetModel( test, "models/rpgrocket.mdl" );
g_EntityFuncs.SetSize( test.pev, Vector( -8.0, -8.0, -8.0 ), Vector( 8.0, 8.0, 8.0 ) );
test.pev.solid = SOLID_BBOX;
test.pev.movetype = MOVETYPE_FLY;
test.pev.targetname = string_t( "blahblah" );

// Give it some speed
Vector vVelocity = g_vecZero;
vVelocity = pForward * 1792.0;
test.pev.velocity = vVelocity;

Next, I try to check if the entity has "collided" with something through a very hacky way:

g_Scheduler.SetInterval( "Skill_Think", 0.01, g_Scheduler.REPEAT_INFINITE_TIMES );
void Skill_Think()
CBaseEntity@ ent = null;
while( ( @ent = g_EntityFuncs.FindEntityInSphere( ent, g_vecZero, 8192.0, "*", "classname" ) ) !is null ) // WTF am I doing?
string cname = ent.pev.classname;
string tname = ent.pev.targetname;

if ( cname == 'info_target' && tname == 'blahblah' )
// Get entity speed
Vector vSpeed = ent.pev.velocity;
if ( vSpeed.Length() < 8.0 ) // If it's moving this slow, then it had to collide with a wall or another entity
SomeCustomExplosion( ent )


Sometimes the entity just keeps going until something brings it into a full stop, rather than "exploding" as soon as it touches a wall or another entity.
I cannot see any function in the API that allows checking if an entity touches another entity (or similar). And checking the entity's speed via the following method:

Vector vSpeed = ent.pev.velocity;
if ( vSpeed.Length() < 8.0 )
// Stuff

Doesn't seem to work on all cases. Also my code above is awfully bad.
So, the point: How to check if an entity collided/touched something, like a wall or another entity?

05-04-2016, 11:02 PM
Create a custom entity that implements the "Touch" method. I don't think you can override Touch for existing entities.

class YourCustomEntity : ScriptBaseEntity
void Spawn()
self.pev.movetype = MOVETYPE_FLY;
self.pev.solid = SOLID_BBOX;

g_EntityFuncs.SetModel( self, pev.model );

void Touch( CBaseEntity@ pOther )
g_Game.AlertMessage( at_console, "LOL TOUCHED " + pOther.pev.classname);

06-04-2016, 10:16 AM
Ain't the creation of custom entities reserved to map scripts only? I need this to work on a plugin.

06-04-2016, 11:26 AM
Right, didn't know this was a plugin. In that case, you'll need to do the collision detection yourself.

Your current method doesn't seem to be checking for collision, but rather setting off the bomb if it starts moving slowly. With most movetypes, that won't work well since hitting walls at narrow angles doesn't reduce speed much.

What I think you should try is a TraceHull every single frame. TraceHull simulates a box moving from point A to point B, so it's a bit more accurate than TraceLine. The drawback is that you only have a few hull sizes to choose from. head_hull should be good enough for most missiles:

g_Utility.TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, owner.edict(), tr );
if ( tr.flFraction < 1.0 )
g_Game.AlertMessage( at_console, "ROFL COLLIDED WITH " + (tr.pHit !is null) ? tr.pHit.pev.classname : "nothing?");

Also, store Ehandles to the entities you create rather than searching for them. If you do more than a few of these searches at once you're gonna have some serious framerate issues.

06-04-2016, 06:39 PM
Golly, you are awesome. Worked like a charm! Thanks!