summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authorBen Millwood <thebenmachine@gmail.com>2009-10-03 12:52:08 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:16:17 +0000
commiteb9f1d7a0e02993772facc4314a0ba9f62592879 (patch)
tree5ad820d9415d6b7181962453249044d3516f772d /src/game
parentfd69c6cdcccfee850fb769ce34883ee7813ab569 (diff)
Zone BP
Diffstat (limited to 'src/game')
-rw-r--r--src/game/bg_public.h6
-rw-r--r--src/game/g_active.c6
-rw-r--r--src/game/g_buildable.c261
-rw-r--r--src/game/g_local.h25
-rw-r--r--src/game/g_main.c140
-rw-r--r--src/game/tremulous.h7
6 files changed, 348 insertions, 97 deletions
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index 6a4bc1c8..079d55e4 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -69,7 +69,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define CS_BOTINFO 25
#define CS_CLIENTS_READY 26
-#define CS_BUILDPOINTS 28
#define CS_STAGES 29
#define CS_MODELS 33
@@ -269,8 +268,9 @@ typedef enum
PERS_STATE,
PERS_CREDIT, // human credit
PERS_QUEUEPOS, // position in the spawn queue
- PERS_NEWWEAPON // weapon to switch to
- // netcode has space for 5 more
+ PERS_NEWWEAPON, // weapon to switch to
+ PERS_BP
+ // netcode has space for 4 more
} persEnum_t;
#define PS_WALLCLIMBINGFOLLOW 0x00000001
diff --git a/src/game/g_active.c b/src/game/g_active.c
index e004346a..80c3df65 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -1742,6 +1742,12 @@ void ClientThink_real( gentity_t *ent )
}
}
+ client->ps.persistant[ PERS_BP ] = G_GetBuildPoints( client->ps.origin,
+ client->ps.stats[ STAT_TEAM ], BG_Class( client->ps.stats[ STAT_CLASS ] )->buildDist );
+
+ if( client->ps.persistant[ PERS_BP ] < 0 )
+ client->ps.persistant[ PERS_BP ] = 0;
+
// Give clients some credit periodically
if( ent->client->lastKillTime + FREEKILL_PERIOD < level.time )
{
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index 8d77267a..11ed8db4 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "g_local.h"
+zone_t zones[ MAX_ZONES ];
+
/*
================
G_SetBuildableAnim
@@ -212,7 +214,7 @@ Simple wrapper to G_FindPower to find the entity providing
power for the specified point
================
*/
-static gentity_t *G_PowerEntityForPoint( vec3_t origin )
+gentity_t *G_PowerEntityForPoint( vec3_t origin )
{
gentity_t dummy;
@@ -229,90 +231,112 @@ static gentity_t *G_PowerEntityForPoint( vec3_t origin )
/*
================
-G_FindRepeater
+G_IsPowered
+
+Check if a location has power, returning the entity type
+that is providing it
+================
+*/
+buildable_t G_IsPowered( vec3_t origin )
+{
+ gentity_t *ent = G_PowerEntityForPoint( origin );
+
+ if( ent )
+ return ent->s.modelindex;
+ else
+ return BA_NONE;
+}
+
+/*
+================
+G_RepeaterWouldOverlap
-attempt to find a repeater in range of self, return qtrue if successful
+Check if a repeater would create an overlapping power zone
================
*/
-static qboolean G_FindRepeater( gentity_t *self )
+static qboolean G_RepeaterWouldOverlap( vec3_t origin )
{
int i;
gentity_t *ent;
- gentity_t *closestPower = NULL;
- int distance = 0;
- int minDistance = REPEATER_BASESIZE + 1;
+ int distance;
vec3_t temp_v;
- if( self->buildableTeam != TEAM_HUMANS )
- return qfalse;
-
- //iterate through entities
+ // 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 a power item calculate the distance to it
- if( ent->s.modelindex == BA_H_REPEATER &&
+ // If entity is a power item calculate the distance to it
+ if( ( ent->s.modelindex == BA_H_REACTOR || ent->s.modelindex == BA_H_REPEATER ) &&
ent->spawned && ent->powered )
{
- VectorSubtract( self->s.origin, ent->s.origin, temp_v );
+ VectorSubtract( origin, ent->s.origin, temp_v );
distance = VectorLength( temp_v );
- if( distance < minDistance )
+ if( ent->s.modelindex == BA_H_REACTOR )
{
- closestPower = ent;
- minDistance = distance;
+ if( distance <= REACTOR_BASESIZE + REPEATER_BASESIZE )
+ return qtrue;
+ }
+ else if( ent->s.modelindex == BA_H_REPEATER )
+ {
+ if( distance <= REPEATER_BASESIZE + REPEATER_BASESIZE )
+ return qtrue;
}
}
}
- //if there were no power items nearby give up
- if( closestPower )
- {
- self->parentNode = closestPower;
- return qtrue;
- }
return qfalse;
}
+
/*
-================
-G_RepeaterEntityForPoint
+==================
+G_GetBuildPoints
-Simple wrapper to G_FindRepeater to find a repeater providing
-power for the specified point
-================
+Get the number of build points from a position
+==================
*/
-static gentity_t *G_RepeaterEntityForPoint( vec3_t origin )
+int G_GetBuildPoints( const vec3_t pos, team_t team, int dist )
{
- gentity_t dummy;
+ int i;
+ gentity_t *ent;
+ int distance = 0;
+ vec3_t temp_v;
+ int buildPoints = 0;
- dummy.parentNode = NULL;
- dummy.buildableTeam = TEAM_HUMANS;
- dummy.s.modelindex = BA_NONE;
- VectorCopy( origin, dummy.s.origin );
+ if( team == TEAM_HUMANS )
+ {
+ // Iterate through entities
+ for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ )
+ {
+ ent = &g_entities[ i ];
- if( G_FindRepeater( &dummy ) )
- return dummy.parentNode;
- else
- return NULL;
-}
-/*
-================
-G_IsPowered
+ VectorSubtract( pos, ent->s.origin, temp_v );
+ distance = VectorLength( temp_v );
-Check if a location has power, returning the entity type
-that is providing it
-================
-*/
-buildable_t G_IsPowered( vec3_t origin )
-{
- gentity_t *ent = G_PowerEntityForPoint( origin );
+ if( ent->s.modelindex == BA_H_REACTOR && distance <= REACTOR_BASESIZE + dist )
+ {
+ // Reactor is in range
+ buildPoints += level.humanBuildPoints;
+ }
+ else if( ent->s.modelindex == BA_H_REPEATER && distance <= REPEATER_BASESIZE + dist )
+ {
+ if( ent->usesZone && zones[ent->zone].active )
+ {
+ zone_t *zone = &zones[ent->zone];
- if( ent )
- return ent->s.modelindex;
- else
- return BA_NONE;
+ buildPoints += zone->totalBuildPoints - zone->queuedBuildPoints;
+ }
+ }
+ }
+ }
+ else if( team == TEAM_ALIENS )
+ {
+ buildPoints = level.alienBuildPoints;
+ }
+
+ return buildPoints;
}
/*
@@ -1625,6 +1649,48 @@ void ATrapper_Think( gentity_t *self )
+void HSpawn_Blast( gentity_t *ent );
+void HSpawn_Disappear( gentity_t *ent );
+
+/*
+================
+HRepeater_Die
+
+Called when a repeater dies
+================
+*/
+static void HRepeater_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod )
+{
+ G_RewardAttackers( self );
+ G_SetBuildableAnim( self, BANIM_DESTROY1, qtrue );
+ G_SetIdleBuildableAnim( self, BANIM_DESTROYED );
+
+ self->die = nullDieFunction;
+ self->powered = qfalse; //free up power
+ self->s.eFlags &= ~EF_FIRING; //prevent any firing effects
+
+ if( self->spawned )
+ {
+ self->think = HSpawn_Blast;
+ self->nextthink = level.time + HUMAN_DETONATION_DELAY;
+ }
+ else
+ {
+ self->think = HSpawn_Disappear;
+ self->nextthink = level.time; //blast immediately
+ }
+
+ G_LogDestruction( self, attacker, mod );
+
+ if( self->usesZone )
+ {
+ zone_t *zone = &zones[self->zone];
+
+ zone->active = qfalse;
+ self->usesZone = qfalse;
+ }
+}
+
/*
================
HRepeater_Think
@@ -1637,10 +1703,11 @@ void HRepeater_Think( gentity_t *self )
int i;
qboolean reactor = qfalse;
gentity_t *ent;
+ zone_t *zone;
if( self->spawned )
{
- //iterate through entities
+ // Iterate through entities
for ( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )
{
if( ent->s.eType != ET_BUILDABLE )
@@ -1653,7 +1720,7 @@ void HRepeater_Think( gentity_t *self )
if( G_NumberOfDependants( self ) == 0 )
{
- //if no dependants for x seconds then disappear
+ // If no dependants for x seconds then disappear
if( self->count < 0 )
self->count = level.time;
else if( self->count > 0 && ( ( level.time - self->count ) > REPEATER_INACTIVE_TIME ) )
@@ -1664,6 +1731,29 @@ void HRepeater_Think( gentity_t *self )
self->powered = reactor;
+ // Initialise the zone once the repeater has spawned
+ if( self->spawned && ( !self->usesZone || !zones[ self->zone ].active ) )
+ {
+ // See if a free zone exists
+ for( i = 0; i < MIN( g_humanRepeaterMaxZones.integer, MAX_ZONES ); i++ )
+ {
+ zone = &zones[ i ];
+
+ if( !zone->active )
+ {
+ // Initialise the BP queue with all BP queued
+ zone->queuedBuildPoints = zone->totalBuildPoints = g_humanRepeaterBuildPoints.integer;
+ zone->nextQueueTime = level.time;
+ zone->active = qtrue;
+
+ self->zone = zone - zones;
+ self->usesZone = qtrue;
+
+ break;
+ }
+ }
+ }
+
self->nextthink = level.time + POWER_REFRESH_TIME;
}
@@ -2398,6 +2488,7 @@ G_QueueBuildPoints
void G_QueueBuildPoints( gentity_t *self )
{
gentity_t *killer = NULL;
+ gentity_t *powerEntity;
if( self->killedBy != ENTITYNUM_NONE )
killer = &g_entities[ self->killedBy ];
@@ -2425,11 +2516,34 @@ void G_QueueBuildPoints( gentity_t *self )
break;
case TEAM_HUMANS:
- if( !level.humanBuildPointQueue )
- level.humanNextQueueTime = level.time + g_humanBuildQueueTime.integer;
+ powerEntity = G_PowerEntityForPoint( self->s.origin );
+
+ if( powerEntity )
+ {
+ switch( powerEntity->s.modelindex )
+ {
+ default:
+ case BA_H_REACTOR:
+ if( !level.humanBuildPointQueue )
+ level.humanNextQueueTime = level.time + g_humanBuildQueueTime.integer;
+
+ level.humanBuildPointQueue +=
+ BG_Buildable( self->s.modelindex )->buildPoints;
+ break;
+
+ case BA_H_REPEATER:
+ if( powerEntity->usesZone && zones[powerEntity->zone].active )
+ {
+ zone_t *zone = &zones[powerEntity->zone];
- level.humanBuildPointQueue +=
- BG_Buildable( self->s.modelindex )->buildPoints;
+ if( !zone->queuedBuildPoints )
+ zone->nextQueueTime = level.time + g_humanRepeaterBuildQueueTime.integer;
+ zone->queuedBuildPoints +=
+ BG_Buildable( self->s.modelindex )->buildPoints;
+ }
+ break;
+ }
+ }
break;
}
}
@@ -2813,7 +2927,7 @@ static itemBuildError_t G_SufficientBPAvailable( buildable_t buildable,
if( team == TEAM_ALIENS )
{
- remainingBP = level.alienBuildPoints;
+ remainingBP = G_GetBuildPoints( origin, team, 0 );
remainingSpawns = level.numAlienSpawns;
bpError = IBE_NOALIENBP;
spawn = BA_A_SPAWN;
@@ -2821,7 +2935,7 @@ static itemBuildError_t G_SufficientBPAvailable( buildable_t buildable,
}
else if( team == TEAM_HUMANS )
{
- remainingBP = level.humanBuildPoints;
+ remainingBP = G_GetBuildPoints( origin, team, 0 );
remainingSpawns = level.numHumanSpawns;
bpError = IBE_NOHUMANBP;
spawn = BA_H_SPAWN;
@@ -2889,6 +3003,13 @@ static itemBuildError_t G_SufficientBPAvailable( buildable_t buildable,
else
repeaterInRange = qfalse;
+ // Don't allow marked buildables to be replaced in another zone,
+ // unless the marked buildable is unpowered
+ if( buildable != BA_H_REACTOR && buildable != BA_H_REPEATER &&
+ G_PowerEntityForPoint( ent->s.origin ) != G_PowerEntityForPoint( origin ) &&
+ G_PowerEntityForPoint( ent->s.origin ) )
+ continue;
+
if( !ent->inuse )
continue;
@@ -2907,6 +3028,11 @@ static itemBuildError_t G_SufficientBPAvailable( buildable_t buildable,
if( ent->s.modelindex == core && buildable != core )
continue;
+ // Don't allow a power source to be replaced by a non-power source
+ if( buildable != BA_H_REACTOR && buildable != BA_H_REPEATER &&
+ ( ent->s.modelindex == BA_H_REACTOR || ent->s.modelindex == BA_H_REPEATER ) )
+ continue;
+
if( ent->deconstruct )
{
level.markedBuildables[ numBuildables++ ] = ent;
@@ -3066,6 +3192,9 @@ itemBuildError_t G_CanBuild( gentity_t *ent, buildable_t buildable, int distance
contents = trap_PointContents( entity_origin, -1 );
buildPoints = BG_Buildable( buildable )->buildPoints;
+ if( ( tempReason = G_SufficientBPAvailable( buildable, origin ) ) != IBE_NONE )
+ reason = tempReason;
+
if( ent->client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
{
//alien criteria
@@ -3122,8 +3251,11 @@ itemBuildError_t G_CanBuild( gentity_t *ent, buildable_t buildable, int distance
if( tempent == NULL ) // No reactor
reason = IBE_RPTNOREAC;
- else if( !g_markDeconstruct.integer && G_RepeaterEntityForPoint( entity_origin ) )
+ else if( G_RepeaterWouldOverlap( entity_origin ) )
+ {
+ // The repeater would cause power zones to overlap
reason = IBE_RPTPOWERHERE;
+ }
}
// Check permission to build here
@@ -3162,9 +3294,6 @@ itemBuildError_t G_CanBuild( gentity_t *ent, buildable_t buildable, int distance
}
}
- if( ( tempReason = G_SufficientBPAvailable( buildable, origin ) ) != IBE_NONE )
- reason = tempReason;
-
// Relink buildables
G_SetBuildableLinkState( qtrue );
@@ -3355,7 +3484,7 @@ static gentity_t *G_Build( gentity_t *builder, buildable_t buildable, vec3_t ori
case BA_H_REPEATER:
built->think = HRepeater_Think;
- built->die = HSpawn_Die;
+ built->die = HRepeater_Die;
built->use = HRepeater_Use;
built->count = -1;
break;
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 933028cd..e757653d 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -252,6 +252,9 @@ struct gentity_s
qboolean ownerClear; // used for missle tracking
qboolean pointAgainstWorld; // don't use the bbox for map collisions
+
+ int zone; // index for zone
+ int usesZone; // does it use a zone?
};
typedef enum
@@ -698,6 +701,8 @@ void G_Physics( gentity_t *ent, int msec );
#define MAX_ALIEN_BBOX 25
+#define MAX_ZONES 1024
+
typedef enum
{
IBE_NONE,
@@ -726,6 +731,17 @@ typedef enum
IBE_MAXERRORS
} itemBuildError_t;
+typedef struct
+{
+ int active;
+
+ int totalBuildPoints;
+ int queuedBuildPoints;
+ int nextQueueTime;
+} zone_t;
+
+extern zone_t zones[MAX_ZONES];
+
qboolean AHovel_Blocked( gentity_t *hovel, gentity_t *player, qboolean provideExit );
gentity_t *G_CheckSpawnPoint( int spawnNum, vec3_t origin, vec3_t normal,
buildable_t spawn, vec3_t spawnOrigin );
@@ -750,6 +766,8 @@ void G_LayoutSelect( void );
void G_LayoutLoad( void );
void G_BaseSelfDestruct( team_t team );
void G_QueueBuildPoints( gentity_t *self );
+int G_GetBuildPoints( const vec3_t pos, team_t team, int dist );
+gentity_t *G_PowerEntityForPoint( vec3_t origin );
//
// g_utils.c
@@ -1059,10 +1077,13 @@ extern vmCvar_t g_enableDust;
extern vmCvar_t g_enableBreath;
extern vmCvar_t g_singlePlayer;
-extern vmCvar_t g_humanBuildPoints;
extern vmCvar_t g_alienBuildPoints;
-extern vmCvar_t g_humanBuildQueueTime;
extern vmCvar_t g_alienBuildQueueTime;
+extern vmCvar_t g_humanBuildPoints;
+extern vmCvar_t g_humanBuildQueueTime;
+extern vmCvar_t g_humanRepeaterBuildPoints;
+extern vmCvar_t g_humanRepeaterBuildQueueTime;
+extern vmCvar_t g_humanRepeaterMaxZones;
extern vmCvar_t g_humanStage;
extern vmCvar_t g_humanCredits;
extern vmCvar_t g_humanMaxStage;
diff --git a/src/game/g_main.c b/src/game/g_main.c
index cca612bc..02448be4 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -87,10 +87,13 @@ vmCvar_t g_minCommandPeriod;
vmCvar_t g_minNameChangePeriod;
vmCvar_t g_maxNameChanges;
-vmCvar_t g_humanBuildPoints;
vmCvar_t g_alienBuildPoints;
-vmCvar_t g_humanBuildQueueTime;
vmCvar_t g_alienBuildQueueTime;
+vmCvar_t g_humanBuildPoints;
+vmCvar_t g_humanBuildQueueTime;
+vmCvar_t g_humanRepeaterBuildPoints;
+vmCvar_t g_humanRepeaterBuildQueueTime;
+vmCvar_t g_humanRepeaterMaxZones;
vmCvar_t g_humanStage;
vmCvar_t g_humanCredits;
vmCvar_t g_humanMaxStage;
@@ -222,10 +225,13 @@ static cvarTable_t gameCvarTable[ ] =
{ &pmove_fixed, "pmove_fixed", "0", CVAR_SYSTEMINFO, 0, qfalse},
{ &pmove_msec, "pmove_msec", "8", CVAR_SYSTEMINFO, 0, qfalse},
- { &g_humanBuildPoints, "g_humanBuildPoints", DEFAULT_HUMAN_BUILDPOINTS, 0, 0, qfalse },
{ &g_alienBuildPoints, "g_alienBuildPoints", DEFAULT_ALIEN_BUILDPOINTS, 0, 0, qfalse },
- { &g_humanBuildQueueTime, "g_humanBuildQueueTime", DEFAULT_HUMAN_QUEUE_TIME, 0, 0, qfalse },
{ &g_alienBuildQueueTime, "g_alienBuildQueueTime", DEFAULT_ALIEN_QUEUE_TIME, 0, 0, qfalse },
+ { &g_humanBuildPoints, "g_humanBuildPoints", DEFAULT_HUMAN_BUILDPOINTS, 0, 0, qfalse },
+ { &g_humanBuildQueueTime, "g_humanBuildQueueTime", DEFAULT_HUMAN_QUEUE_TIME, 0, 0, qfalse },
+ { &g_humanRepeaterBuildPoints, "g_humanRepeaterBuildPoints", DEFAULT_HUMAN_REPEATER_BUILDPOINTS, 0, 0, qfalse },
+ { &g_humanRepeaterMaxZones, "g_humanRepeaterMaxZones", DEFAULT_HUMAN_REPEATER_MAX_ZONES, 0, 0, qfalse },
+ { &g_humanRepeaterBuildQueueTime, "g_humanRepeaterBuildQueueTime", DEFAULT_HUMAN_REPEATER_QUEUE_TIME, 0, 0, qfalse },
{ &g_humanStage, "g_humanStage", "0", 0, 0, qfalse },
{ &g_humanCredits, "g_humanCredits", "0", 0, 0, qfalse },
{ &g_humanMaxStage, "g_humanMaxStage", DEFAULT_HUMAN_MAX_STAGE, 0, 0, qfalse },
@@ -1063,11 +1069,10 @@ Recalculate the quantity of building points available to the teams
*/
void G_CalculateBuildPoints( void )
{
- int i;
+ int i, j;
buildable_t buildable;
gentity_t *ent;
- int localHTP = level.humanBuildPoints = g_humanBuildPoints.integer,
- localATP = level.alienBuildPoints = g_alienBuildPoints.integer;
+ zone_t *zone;
// BP queue updates
while( level.alienBuildPointQueue > 0 &&
@@ -1112,9 +1117,6 @@ void G_CalculateBuildPoints( void )
( g_suddenDeath.integer || G_TimeTilSuddenDeath( ) <= 0 ) )
{
// begin sudden death
- localHTP = 0;
- localATP = 0;
-
if( level.suddenDeathWarning < TW_PASSED )
{
G_LogPrintf( "Beginning Sudden Death\n" );
@@ -1140,8 +1142,8 @@ void G_CalculateBuildPoints( void )
}
}
- level.humanBuildPoints = localHTP - level.humanBuildPointQueue;
- level.alienBuildPoints = localATP - level.alienBuildPointQueue;
+ level.humanBuildPoints = g_humanBuildPoints.integer;
+ level.alienBuildPoints = g_alienBuildPoints.integer;
level.reactorPresent = qfalse;
level.overmindPresent = qfalse;
@@ -1149,7 +1151,56 @@ void G_CalculateBuildPoints( void )
level.numAlienSpawns = 0;
level.numHumanSpawns = 0;
- for( i = MAX_CLIENTS, ent = g_entities + i ; i < level.num_entities ; i++, ent++ )
+ // Deactivate any unowned zones
+ for( i = 0; i < MIN( g_humanRepeaterMaxZones.integer, MAX_ZONES ); i++ )
+ {
+ qboolean inUse = qfalse;
+ zone_t *zone = &zones[ i ];
+
+ if( zone->active )
+ {
+ for( j = MAX_CLIENTS, ent = g_entities + j ; j < level.num_entities ; j++, ent++ )
+ {
+ if( ent->s.eType != ET_BUILDABLE )
+ continue;
+
+ if( ent->s.eType != ET_BUILDABLE )
+ continue;
+
+ if( ent->s.eFlags & EF_DEAD )
+ continue;
+
+ if( ent->usesZone && ent->zone == i )
+ inUse = qtrue;
+ }
+
+ if( !inUse )
+ zone->active = qfalse;
+ }
+ }
+
+ // First reset repeater zone BP
+ for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ )
+ {
+ if( ent->s.eType != ET_BUILDABLE )
+ continue;
+
+ if( ent->s.eFlags & EF_DEAD )
+ continue;
+
+ if( ent->s.modelindex != BA_H_REPEATER )
+ continue;
+
+ if( ent->usesZone && zones[ ent->zone ].active )
+ {
+ zone_t *zone = &zones[ ent->zone ];
+
+ zone->totalBuildPoints = g_humanRepeaterBuildPoints.integer;
+ }
+ }
+
+ // Iterate through entities
+ for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ )
{
if( !ent->inuse )
continue;
@@ -1178,7 +1229,58 @@ void G_CalculateBuildPoints( void )
if( BG_Buildable( buildable )->team == TEAM_HUMANS )
{
- level.humanBuildPoints -= BG_Buildable( buildable )->buildPoints;
+ gentity_t *powerEntity = G_PowerEntityForPoint( ent->s.origin );
+
+ if( powerEntity )
+ {
+ switch( powerEntity->s.modelindex )
+ {
+ case BA_H_REACTOR:
+ level.humanBuildPoints -= BG_Buildable( buildable )->buildPoints;
+ break;
+
+ case BA_H_REPEATER:
+ if( powerEntity->usesZone && zones[powerEntity->zone].active )
+ {
+ zone_t *zone = &zones[powerEntity->zone];
+
+ zone->totalBuildPoints -= BG_Buildable( buildable )->buildPoints;
+ powerEntity->s.misc = zone->totalBuildPoints - zone->queuedBuildPoints;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // Unpowered buildables count as BP for the main reactor zone
+ level.humanBuildPoints -= BG_Buildable( buildable )->buildPoints;
+ }
+
+ if( buildable == BA_H_REPEATER )
+ {
+ if( ent->usesZone && zones[ ent->zone ].active )
+ {
+ zone = &zones[ ent->zone ];
+
+ if( !level.suddenDeath )
+ {
+ // BP queue updates
+ while( zone->queuedBuildPoints > 0 &&
+ zone->nextQueueTime < level.time )
+ {
+ zone->queuedBuildPoints--;
+ zone->nextQueueTime += (int)g_humanRepeaterBuildQueueTime.integer * (float)( 1 - ( (float)zone->queuedBuildPoints ) / zone->totalBuildPoints );
+ }
+ }
+ else
+ {
+ zone->totalBuildPoints = zone->queuedBuildPoints = 0;
+ }
+ }
+ }
}
else if( BG_Buildable( buildable )->team == TEAM_ALIENS )
{
@@ -1188,20 +1290,10 @@ void G_CalculateBuildPoints( void )
}
if( level.humanBuildPoints < 0 )
- {
- localHTP -= level.humanBuildPoints;
level.humanBuildPoints = 0;
- }
if( level.alienBuildPoints < 0 )
- {
- localATP -= level.alienBuildPoints;
level.alienBuildPoints = 0;
- }
-
- trap_SetConfigstring( CS_BUILDPOINTS, va( "%d %d %d %d",
- level.alienBuildPoints, localATP,
- level.humanBuildPoints, localHTP ) );
}
/*
diff --git a/src/game/tremulous.h b/src/game/tremulous.h
index 7859173e..b71db8ae 100644
--- a/src/game/tremulous.h
+++ b/src/game/tremulous.h
@@ -660,12 +660,15 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define FREEKILL_HUMAN LEVEL0_VALUE
#define DEFAULT_ALIEN_BUILDPOINTS "100"
-#define DEFAULT_ALIEN_QUEUE_TIME "1250"
+#define DEFAULT_ALIEN_QUEUE_TIME "7000"
#define DEFAULT_ALIEN_STAGE2_THRESH "8000"
#define DEFAULT_ALIEN_STAGE3_THRESH "16000"
#define DEFAULT_ALIEN_MAX_STAGE "2"
#define DEFAULT_HUMAN_BUILDPOINTS "100"
-#define DEFAULT_HUMAN_QUEUE_TIME "1250"
+#define DEFAULT_HUMAN_QUEUE_TIME "7000"
+#define DEFAULT_HUMAN_REPEATER_BUILDPOINTS "20"
+#define DEFAULT_HUMAN_REPEATER_QUEUE_TIME "7000"
+#define DEFAULT_HUMAN_REPEATER_MAX_ZONES "3"
#define DEFAULT_HUMAN_STAGE2_THRESH "4000"
#define DEFAULT_HUMAN_STAGE3_THRESH "8000"
#define DEFAULT_HUMAN_MAX_STAGE "2"