summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/bg_public.h1
-rw-r--r--src/game/g_buildable.c59
-rw-r--r--src/game/g_combat.c11
-rw-r--r--src/game/g_local.h1
-rw-r--r--src/game/g_main.c71
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 );