diff options
Diffstat (limited to 'src/game')
-rw-r--r-- | src/game/g_local.h | 2 | ||||
-rw-r--r-- | src/game/g_missile.c | 80 |
2 files changed, 65 insertions, 17 deletions
diff --git a/src/game/g_local.h b/src/game/g_local.h index 49a5ceac..caa7ff5f 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -249,6 +249,8 @@ struct gentity_s float zapDmg; // keep track of damage qboolean ownerClear; // used for missle tracking + + qboolean pointAgainstWorld; // don't use the bbox for map collisions }; typedef enum diff --git a/src/game/g_missile.c b/src/game/g_missile.c index ebfd4d9d..2eeada6a 100644 --- a/src/game/g_missile.c +++ b/src/game/g_missile.c @@ -246,7 +246,8 @@ void G_RunMissile( gentity_t *ent ) { vec3_t origin; trace_t tr; - int passent; + int passent; + qboolean impact = qfalse; // get current position BG_EvaluateTrajectory( &ent->s.pos, level.time, origin ); @@ -254,40 +255,75 @@ void G_RunMissile( gentity_t *ent ) // ignore interactions with the missile owner passent = ent->r.ownerNum; - // trace a line from the previous position to the current position - trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask ); + // general trace to see if we hit anything at all + trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, + origin, passent, ent->clipmask ); if( tr.startsolid || tr.allsolid ) { - // make sure the tr.entityNum is set to the entity we're stuck in - trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, passent, ent->clipmask ); - tr.fraction = 0; + tr.fraction = 0.0f; + VectorCopy( ent->r.currentOrigin, tr.endpos ); } - else - VectorCopy( tr.endpos, ent->r.currentOrigin ); - ent->r.contents = CONTENTS_SOLID; //trick trap_LinkEntity into... - trap_LinkEntity( ent ); - ent->r.contents = 0; //...encoding bbox information + if( tr.fraction < 1.0f ) + { + if( !ent->pointAgainstWorld || tr.contents & CONTENTS_BODY || + ( tr.entityNum >= 0 && tr.entityNum != ENTITYNUM_WORLD ) ) + { + // We hit an entity or we don't care + impact = qtrue; + } + else + { + trap_Trace( &tr, ent->r.currentOrigin, NULL, NULL, origin, + passent, ent->clipmask ); + + if( tr.fraction < 1.0f ) + { + // Hit the world with point trace + impact = qtrue; + } + else + { + if( tr.contents & CONTENTS_BODY || + ( tr.entityNum >= 0 && tr.entityNum != ENTITYNUM_WORLD ) ) + { + // Hit an entity + impact = qtrue; + } + else + { + trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, + origin, passent, CONTENTS_BODY ); + + if( tr.fraction < 1.0f ) + impact = qtrue; + } + } + } + } - if( tr.fraction != 1 ) + VectorCopy( tr.endpos, ent->r.currentOrigin ); + + if( impact ) { - // never explode or bounce on sky if( tr.surfaceFlags & SURF_NOIMPACT ) { - // If grapple, reset owner - if( ent->parent && ent->parent->client && ent->parent->client->hook == ent ) - ent->parent->client->hook = NULL; - + // Never explode or bounce on sky G_FreeEntity( ent ); return; } G_MissileImpact( ent, &tr ); + if( ent->s.eType != ET_MISSILE ) return; // exploded } + ent->r.contents = CONTENTS_SOLID; //trick trap_LinkEntity into... + trap_LinkEntity( ent ); + ent->r.contents = 0; //...encoding bbox information + // check think function after bouncing G_RunThink( ent ); } @@ -310,6 +346,7 @@ gentity_t *fire_flamer( gentity_t *self, vec3_t start, vec3_t dir ) bolt = G_Spawn(); bolt->classname = "flame"; + bolt->pointAgainstWorld = qfalse; bolt->nextthink = level.time + FLAMER_LIFETIME; bolt->think = G_ExplodeMissile; bolt->s.eType = ET_MISSILE; @@ -356,6 +393,7 @@ gentity_t *fire_blaster( gentity_t *self, vec3_t start, vec3_t dir ) bolt = G_Spawn(); bolt->classname = "blaster"; + bolt->pointAgainstWorld = qtrue; bolt->nextthink = level.time + 10000; bolt->think = G_ExplodeMissile; bolt->s.eType = ET_MISSILE; @@ -401,6 +439,7 @@ gentity_t *fire_pulseRifle( gentity_t *self, vec3_t start, vec3_t dir ) bolt = G_Spawn(); bolt->classname = "pulse"; + bolt->pointAgainstWorld = qtrue; bolt->nextthink = level.time + 10000; bolt->think = G_ExplodeMissile; bolt->s.eType = ET_MISSILE; @@ -448,6 +487,7 @@ gentity_t *fire_luciferCannon( gentity_t *self, vec3_t start, vec3_t dir, bolt = G_Spawn( ); bolt->classname = "lcannon"; + bolt->pointAgainstWorld = qtrue; if( damage == LCANNON_DAMAGE ) bolt->nextthink = level.time; @@ -506,6 +546,7 @@ gentity_t *launch_grenade( gentity_t *self, vec3_t start, vec3_t dir ) bolt = G_Spawn( ); bolt->classname = "grenade"; + bolt->pointAgainstWorld = qfalse; bolt->nextthink = level.time + 5000; bolt->think = G_ExplodeMissile; bolt->s.eType = ET_MISSILE; @@ -641,6 +682,7 @@ gentity_t *fire_hive( gentity_t *self, vec3_t start, vec3_t dir ) bolt = G_Spawn( ); bolt->classname = "hive"; + bolt->pointAgainstWorld = qfalse; bolt->nextthink = level.time + HIVE_DIR_CHANGE_PERIOD; bolt->think = AHive_SearchAndDestroy; bolt->s.eType = ET_MISSILE; @@ -682,6 +724,7 @@ gentity_t *fire_lockblob( gentity_t *self, vec3_t start, vec3_t dir ) bolt = G_Spawn( ); bolt->classname = "lockblob"; + bolt->pointAgainstWorld = qtrue; bolt->nextthink = level.time + 15000; bolt->think = G_ExplodeMissile; bolt->s.eType = ET_MISSILE; @@ -720,6 +763,7 @@ gentity_t *fire_slowBlob( gentity_t *self, vec3_t start, vec3_t dir ) bolt = G_Spawn( ); bolt->classname = "slowblob"; + bolt->pointAgainstWorld = qtrue; bolt->nextthink = level.time + 15000; bolt->think = G_ExplodeMissile; bolt->s.eType = ET_MISSILE; @@ -759,6 +803,7 @@ gentity_t *fire_paraLockBlob( gentity_t *self, vec3_t start, vec3_t dir ) bolt = G_Spawn( ); bolt->classname = "lockblob"; + bolt->pointAgainstWorld = qtrue; bolt->nextthink = level.time + 15000; bolt->think = G_ExplodeMissile; bolt->s.eType = ET_MISSILE; @@ -796,6 +841,7 @@ gentity_t *fire_bounceBall( gentity_t *self, vec3_t start, vec3_t dir ) bolt = G_Spawn( ); bolt->classname = "bounceball"; + bolt->pointAgainstWorld = qtrue; bolt->nextthink = level.time + 3000; bolt->think = G_ExplodeMissile; bolt->s.eType = ET_MISSILE; |