diff options
-rw-r--r-- | src/game/bg_public.h | 1 | ||||
-rw-r--r-- | src/game/g_buildable.c | 59 | ||||
-rw-r--r-- | src/game/g_combat.c | 11 | ||||
-rw-r--r-- | src/game/g_local.h | 1 | ||||
-rw-r--r-- | src/game/g_main.c | 71 |
5 files changed, 118 insertions, 25 deletions
diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 886d29b..f8a2f9d 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -894,6 +894,7 @@ typedef enum MOD_DECONSTRUCT, MOD_REPLACE, MOD_NOCREEP, + MOD_NOBP, MOD_ABOMB } meansOfDeath_t; diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index 61a3460..37e3e66 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -387,22 +387,25 @@ gentity_t *G_IsGathered( team_t team, vec3_t origin, qboolean omRcOnly, gentity_ ================== G_GetBuildPoints -Get the number of build points from a position +Get the number of build points from a position. + +If sudden death has started, the returned value might be negative, +but is never positive. + +Note: 'pos' can be NULL, in this case return the overall BP of the team. ================== */ int G_GetBuildPoints( const vec3_t pos, team_t team ) { - if( G_TimeTilSuddenDeath( ) <= 0 ) - { - return 0; - } - else if( !G_Overmind( ) && team == TEAM_ALIENS ) + int value = 0; + + if( !G_Overmind( ) && team == TEAM_ALIENS ) { return 0; } else if( team == TEAM_ALIENS ) { - return level.alienBuildPoints; + value = level.alienBuildPoints; } else if( !G_Reactor( ) && team == TEAM_HUMANS ) { @@ -410,10 +413,15 @@ int G_GetBuildPoints( const vec3_t pos, team_t team ) } else if( team == TEAM_HUMANS ) { - return level.humanBuildPoints; + value = level.humanBuildPoints; } + else + return 0; - return 0; + if( ( value > 0 ) && ( G_TimeTilSuddenDeath( ) <= 0 ) ) + return 0; + else + return value; } /* @@ -516,6 +524,24 @@ gentity_t *G_InPowerZone( gentity_t *self ) /* ================ +G_Suicide + +let the given buildable suicide +================ +*/ +void G_Suicide( gentity_t *self, meansOfDeath_t death ) +{ + const gentity_t *parent = self->parentNode; + + if( parent ) + G_Damage( self, NULL, g_entities + parent->killedBy, NULL, NULL, + self->health, 0, death ); + else + G_Damage( self, NULL, NULL, NULL, NULL, self->health, 0, death ); +} + +/* +================ G_FindDCC attempt to find a controlling DCC for self, return number found @@ -952,16 +978,9 @@ Tests for creep and kills the buildable if there is none */ void AGeneric_CreepCheck( gentity_t *self ) { - gentity_t *spawn; - - spawn = self->parentNode; if( !G_FindCreep( self ) ) { - if( spawn ) - G_Damage( self, NULL, g_entities + spawn->killedBy, NULL, NULL, - self->health, 0, MOD_NOCREEP ); - else - G_Damage( self, NULL, NULL, NULL, NULL, self->health, 0, MOD_NOCREEP ); + G_Suicide( self, MOD_NOCREEP ); return; } G_CreepSlow( self ); @@ -2314,11 +2333,7 @@ static qboolean G_SuicideIfNoPower( gentity_t *self ) self->count = level.time; else if( ( level.time - self->count ) >= HUMAN_BUILDABLE_INACTIVE_TIME ) { - if( self->parentNode ) - G_Damage( self, NULL, g_entities + self->parentNode->killedBy, - NULL, NULL, self->health, 0, MOD_NOCREEP ); - else - G_Damage( self, NULL, NULL, NULL, NULL, self->health, 0, MOD_NOCREEP ); + G_Suicide( self, MOD_NOCREEP ); return qtrue; } } diff --git a/src/game/g_combat.c b/src/game/g_combat.c index 073c00c..ada2f9c 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -143,7 +143,8 @@ char *modNames[ ] = "MOD_SLAP", "MOD_DECONSTRUCT", "MOD_REPLACE", - "MOD_NOCREEP", + "MOD_NOCREEP", + "MOD_NOBP", "MOD_ABOMB" }; @@ -1353,7 +1354,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, if( targ->s.eType == ET_BUILDABLE && attacker->client && mod != MOD_DECONSTRUCT && mod != MOD_SUICIDE && - mod != MOD_REPLACE && mod != MOD_NOCREEP ) + mod != MOD_REPLACE && mod != MOD_NOCREEP && mod != MOD_NOBP ) { if( targ->buildableTeam == attacker->client->pers.teamSelection && !g_friendlyBuildableFire.integer ) @@ -1781,6 +1782,9 @@ void G_LogDestruction( gentity_t *self, gentity_t *actor, int mod ) case MOD_NOCREEP: fate = ( actor->client ) ? BF_UNPOWER : BF_AUTO; break; + case MOD_NOBP: + fate = BF_UNPOWER; + break; default: if( actor->client ) { @@ -1813,7 +1817,8 @@ void G_LogDestruction( gentity_t *self, gentity_t *actor, int mod ) // No-power deaths for humans come after some minutes and it's confusing // when the messages appear attributed to the deconner. Just don't print them. - if( mod == MOD_NOCREEP && actor->client && + if( ( mod == MOD_NOCREEP && mod == MOD_NOBP ) && + actor->client && actor->client->pers.teamSelection == TEAM_HUMANS ) return; diff --git a/src/game/g_local.h b/src/game/g_local.h index 4f03aad..44c6996 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -670,6 +670,7 @@ typedef struct timeWarning_t timelimitWarning; int nextArmageddonKillTime; + int nextNegativeBPCheck; spawnQueue_t alienSpawnQueue; spawnQueue_t humanSpawnQueue; diff --git a/src/game/g_main.c b/src/game/g_main.c index 3d9c52b..f5d8d8a 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -366,6 +366,7 @@ void G_ShutdownGame( int restart ); void CheckExitRules( void ); void G_CountSpawns( void ); void G_CalculateBuildPoints( void ); +void G_CheckForNegativeBuildPoints( void ); /* ================ @@ -1353,6 +1354,75 @@ void G_CalculateBuildPoints( void ) // if( level.alienBuildPoints < 0 ) // level.alienBuildPoints = 0; } + +/* +============ +G_CheckForNegativeBuildPoints + +Recalculate the quantity of building points available to the teams +============ +*/ +void G_CheckForNegativeBuildPoints( void ) +{ + static const int thinkduration = 1037; + int e; + gentity_t *ent; + const buildableAttributes_t *ba; + float dieprob1min; + float surviveprob1min; + float surviveprobcur; + int a_bps, h_bps; + + if( level.nextNegativeBPCheck > level.time ) + return; + level.nextNegativeBPCheck += thinkduration; + + a_bps = G_GetBuildPoints( NULL, TEAM_ALIENS ) + level.alienBuildPointQueue; + h_bps = G_GetBuildPoints( NULL, TEAM_HUMANS ) + level.humanBuildPointQueue; + + if( ( a_bps >= 0 ) && ( h_bps >= 0 ) ) + return; + + for( e = 0; e < level.num_entities; ++e ) { + ent = g_entities + e; + + if (!ent->inuse) + continue; + ba = BG_Buildable( ent->s.modelindex ); + + // no gain from a building without BPs + if( ba->buildPoints <= 0 ) + continue; + + // TODO: Add a separate probability for each buildable. + // If it's 0, then they won't die at all, and the checks for building types + // won't be needed. + dieprob1min = 0.42f; /* hard-wired */ + if( dieprob1min <= 0.0f ) + continue; + surviveprob1min = 1.0f - dieprob1min; + surviveprob1min = MAX( 0.0f, surviveprob1min ); + + // check for buildings that must not die + switch( ent->s.modelindex ) { + case BA_H_REACTOR: + case BA_H_REFINERY: + case BA_A_OVERMIND: + case BA_A_CREEPCOLONY: + continue; + } + // TODO end + + if( ( ( ent->buildableTeam == TEAM_ALIENS ) && ( a_bps < 0 ) ) || + ( ( ent->buildableTeam == TEAM_HUMANS ) && ( h_bps < 0 ) ) ) + { + surviveprobcur = pow( surviveprob1min, thinkduration / 60000.0f ); + if( surviveprobcur * RAND_MAX < rand( ) ) + G_Suicide( ent, MOD_NOBP ); + } + } +} + /* ============ G_HumanBuildPoints @@ -2747,6 +2817,7 @@ void G_RunFrame( int levelTime ) G_CountSpawns( ); G_CalculateBuildPoints( ); + G_CheckForNegativeBuildPoints( ); G_CalculateStages( ); G_SpawnClients( TEAM_ALIENS ); G_SpawnClients( TEAM_HUMANS ); |