PDA

View Full Version : Entity Collision



Julcoool
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 )
}
}
}
}


However...

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?

w00tguy123
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);
}
}

Julcoool
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.

w00tguy123
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.

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