diff options
Diffstat (limited to 'src/game/g_buildable.c')
-rw-r--r-- | src/game/g_buildable.c | 141 |
1 files changed, 43 insertions, 98 deletions
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index dad88840..11d7ea2a 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -143,17 +143,9 @@ qboolean G_FindPower( gentity_t *self ) // Handle repeaters if( self->s.modelindex == BA_H_REPEATER ) { - if( level.reactorPresent ) - { - G_FindReactor( self ); - self->parentNode = self->reactorNode; - - return qtrue; - } - - self->parentNode = NULL; + self->parentNode = G_Reactor( ); - return qfalse; + return self->parentNode != NULL; } // Reset parent @@ -559,80 +551,46 @@ qboolean G_IsDCCBuilt( void ) /* ================ -G_FindOvermind +G_Reactor +G_Overmind + +Since there's only one of these and we quite often want to find them, cache the +results, but check them for validity each time -Attempt to find an overmind for self +The code here will break if more than one reactor or overmind is allowed, even +if one of them is dead/unspawned ================ */ -qboolean G_FindOvermind( gentity_t *self ) -{ - int i; - gentity_t *ent; +static gentity_t *G_FindBuildable( buildable_t buildable ); - if( self->buildableTeam != TEAM_ALIENS ) - return qfalse; +gentity_t *G_Reactor( void ) +{ + static gentity_t *rc; - //if this already has overmind then stop now - if( self->overmindNode && self->overmindNode->health > 0 ) - return qtrue; + // If cache becomes invalid renew it + if( !rc || rc->s.eType != ET_BUILDABLE || rc->s.modelindex == BA_H_REACTOR ) + rc = G_FindBuildable( BA_H_REACTOR ); - //reset parent - self->overmindNode = NULL; + // If we found it and it's alive, return it + if( rc && rc->spawned && rc->health > 0 ) + return rc; - //iterate through entities - for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ ) - { - if( ent->s.eType != ET_BUILDABLE ) - continue; - - //if entity is an overmind calculate the distance to it - if( ent->s.modelindex == BA_A_OVERMIND && ent->spawned && ent->health > 0 ) - { - self->overmindNode = ent; - return qtrue; - } - } - - return qfalse; + return NULL; } -/* -================ -G_FindReactor - -Attempt to find a reactor for self -================ -*/ -qboolean G_FindReactor( gentity_t *self ) +gentity_t *G_Overmind( void ) { - int i; - gentity_t *ent; + static gentity_t *om; - if( self->buildableTeam != TEAM_HUMANS ) - return qfalse; + // If cache becomes invalid renew it + if( !om || om->s.eType != ET_BUILDABLE || om->s.modelindex == BA_A_OVERMIND ) + om = G_FindBuildable( BA_A_OVERMIND ); - // If this already has reactor then stop now - if( self->reactorNode && self->reactorNode->health > 0 ) - return qtrue; - - // Reset parent - self->reactorNode = NULL; - - // Iterate through entities - for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ ) - { - if( ent->s.eType != ET_BUILDABLE ) - continue; + // If we found it and it's alive, return it + if( om && om->spawned && om->health > 0 ) + return om; - // If entity is an overmind calculate the distance to it - if( ent->s.modelindex == BA_H_REACTOR && ent->spawned && ent->health > 0 ) - { - self->reactorNode = ent; - return qtrue; - } - } - - return qfalse; + return NULL; } /* @@ -888,7 +846,7 @@ A generic think function for Alien buildables */ void AGeneric_Think( gentity_t *self ) { - self->powered = level.overmindPresent; + self->powered = G_Overmind( ) != NULL; self->nextthink = level.time + BG_Buildable( self->s.modelindex )->nextthink; AGeneric_CreepCheck( self ); } @@ -1210,7 +1168,9 @@ Think function for Alien Barricade void ABarricade_Think( gentity_t *self ) { AGeneric_Think( self ); - ABarricade_Shrink( self, !G_FindOvermind( self ) ); + + // Shrink if unpowered + ABarricade_Shrink( self, !self->powered ); } /* @@ -1260,16 +1220,13 @@ void AAcidTube_Think( gentity_t *self ) int i, num; gentity_t *enemy; - self->powered = level.overmindPresent; - self->nextthink = level.time + BG_Buildable( self->s.modelindex )->nextthink; + AGeneric_Think( self ); VectorAdd( self->s.origin, range, maxs ); VectorSubtract( self->s.origin, range, mins ); - AGeneric_CreepCheck( self ); - // attack nearby humans - if( self->spawned && self->health > 0 && G_FindOvermind( self ) ) + if( self->spawned && self->health > 0 && self->powered ) { num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); for( i = 0; i < num; i++ ) @@ -1351,17 +1308,14 @@ Think function for Alien Hive */ void AHive_Think( gentity_t *self ) { - self->powered = level.overmindPresent; - self->nextthink = level.time + BG_Buildable( self->s.modelindex )->nextthink; - - AGeneric_CreepCheck( self ); + AGeneric_Think( self ); // Hive missile hasn't returned in HIVE_REPEAT seconds, forget about it if( self->timestamp < level.time ) self->active = qfalse; // Find a target to attack - if( self->spawned && !self->active && G_FindOvermind( self ) ) + if( self->spawned && !self->active && self->powered ) { int i, num, entityList[ MAX_GENTITIES ]; vec3_t mins, maxs, @@ -1499,7 +1453,7 @@ void AHovel_Use( gentity_t *self, gentity_t *other, gentity_t *activator ) { vec3_t hovelOrigin, hovelAngles, inverseNormal; - if( self->spawned && G_FindOvermind( self ) ) + if( self->spawned && self->powered ) { if( self->active ) { @@ -1558,10 +1512,7 @@ Think for alien hovel */ void AHovel_Think( gentity_t *self ) { - self->powered = level.overmindPresent; - self->nextthink = level.time + 200; - - AGeneric_CreepCheck( self ); + AGeneric_Think( self ); if( self->spawned ) { @@ -1631,10 +1582,7 @@ void ABooster_Touch( gentity_t *self, gentity_t *other, trace_t *trace ) { gclient_t *client = other->client; - if( !self->spawned || self->health <= 0 ) - return; - - if( !G_FindOvermind( self ) ) + if( !self->spawned || !self->powered || self->health <= 0 ) return; if( !client ) @@ -1791,12 +1739,9 @@ void ATrapper_Think( gentity_t *self ) int range = BG_Buildable( self->s.modelindex )->turretRange; int firespeed = BG_Buildable( self->s.modelindex )->turretFireSpeed; - self->powered = level.overmindPresent; - self->nextthink = level.time + BG_Buildable( self->s.modelindex )->nextthink; - - AGeneric_CreepCheck( self ); + AGeneric_Think( self ); - if( self->spawned && G_FindOvermind( self ) ) + if( self->spawned && self->powered ) { //if the current target is not valid find a new one if( !ATrapper_CheckTarget( self, self->enemy, range ) ) @@ -3386,7 +3331,7 @@ itemBuildError_t G_CanBuild( gentity_t *ent, buildable_t buildable, int distance // Check there is an Overmind if( buildable != BA_A_OVERMIND ) { - if( !level.overmindPresent ) + if( !G_Overmind( ) ) reason = IBE_NOOVERMIND; } |