From d15d03572381c449024f385f4774f1c4bc95e227 Mon Sep 17 00:00:00 2001 From: Petr Pudlak Date: Sat, 20 Sep 2014 16:04:45 +0200 Subject: Add a helper function for suiciding buildables Removes duplicate code when suiciding alien and human structures. --- src/game/g_buildable.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'src/game') diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index 61a3460..856db29 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -514,6 +514,24 @@ gentity_t *G_InPowerZone( gentity_t *self ) return NULL; } +/* +================ +G_Suicide + +let the given buildable suicide +================ +*/ +void G_Suicide( gentity_t *self ) +{ + const gentity_t *parent = self->parentNode; + + if( parent ) + G_Damage( self, NULL, g_entities + parent->killedBy, NULL, NULL, + self->health, 0, MOD_NOCREEP ); + else + G_Damage( self, NULL, NULL, NULL, NULL, self->health, 0, MOD_NOCREEP ); +} + /* ================ G_FindDCC @@ -952,16 +970,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 ); return; } G_CreepSlow( self ); @@ -2314,11 +2325,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 ); return qtrue; } } -- cgit From 43ea36ac9bea52cd058c81a8697878c508a0eb4b Mon Sep 17 00:00:00 2001 From: Petr Pudlak Date: Sat, 20 Sep 2014 16:14:54 +0200 Subject: Show negative build points even after sudden death While it's not possible to build after SD, it's possible that buildings die due to too little BPs. --- src/game/g_buildable.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'src/game') diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index 856db29..90df479 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -387,22 +387,23 @@ 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. ================== */ 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 +411,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; } /* -- cgit From 0238f457f4200a92e99e3be0a61a9870ea8ae560 Mon Sep 17 00:00:00 2001 From: Petr Pudlak Date: Sat, 20 Sep 2014 18:54:42 +0200 Subject: Add a separate mode of death for no-BP building suicides --- src/game/bg_public.h | 1 + src/game/g_buildable.c | 10 +++++----- src/game/g_combat.c | 11 ++++++++--- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src/game') 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 90df479..72d4d3c 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -527,15 +527,15 @@ G_Suicide let the given buildable suicide ================ */ -void G_Suicide( gentity_t *self ) +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, MOD_NOCREEP ); + self->health, 0, death ); else - G_Damage( self, NULL, NULL, NULL, NULL, self->health, 0, MOD_NOCREEP ); + G_Damage( self, NULL, NULL, NULL, NULL, self->health, 0, death ); } /* @@ -978,7 +978,7 @@ void AGeneric_CreepCheck( gentity_t *self ) { if( !G_FindCreep( self ) ) { - G_Suicide( self ); + G_Suicide( self, MOD_NOCREEP ); return; } G_CreepSlow( self ); @@ -2331,7 +2331,7 @@ static qboolean G_SuicideIfNoPower( gentity_t *self ) self->count = level.time; else if( ( level.time - self->count ) >= HUMAN_BUILDABLE_INACTIVE_TIME ) { - G_Suicide( self ); + 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; -- cgit From dc215ae76045cc7ee80db427a1da1eede472d376 Mon Sep 17 00:00:00 2001 From: Petr Pudlak Date: Sat, 20 Sep 2014 19:45:18 +0200 Subject: Scan if a team has a negative number of build points The scan occurs periodically in the main loop. There is a given probability that a building dies within 1 minute if BP < 0. --- src/game/g_buildable.c | 2 ++ src/game/g_local.h | 1 + src/game/g_main.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) (limited to 'src/game') diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index 72d4d3c..37e3e66 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -391,6 +391,8 @@ 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 ) 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..2a8fb13 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 ); + h_bps = G_GetBuildPoints( NULL, TEAM_HUMANS ); + + 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 ); -- cgit From 25ea3508f41b1ae7764c10516a7148149a0bc50a Mon Sep 17 00:00:00 2001 From: Petr Pudlak Date: Sat, 20 Sep 2014 20:14:17 +0200 Subject: Account for build points in the queues So that buildings don't die when there is enough BPs, but still stuck in the queue. --- src/game/g_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/game') diff --git a/src/game/g_main.c b/src/game/g_main.c index 2a8fb13..f5d8d8a 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -1377,8 +1377,8 @@ void G_CheckForNegativeBuildPoints( void ) return; level.nextNegativeBPCheck += thinkduration; - a_bps = G_GetBuildPoints( NULL, TEAM_ALIENS ); - h_bps = G_GetBuildPoints( NULL, TEAM_HUMANS ); + 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; -- cgit