summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/g_local.h2
-rw-r--r--src/game/g_missile.c80
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;