diff options
-rw-r--r-- | src/cgame/cg_draw.c | 3 | ||||
-rw-r--r-- | src/game/g_active.c | 15 | ||||
-rw-r--r-- | src/game/g_buildable.c | 40 | ||||
-rw-r--r-- | src/game/g_client.c | 11 | ||||
-rw-r--r-- | src/game/g_cmds.c | 43 | ||||
-rw-r--r-- | src/game/g_combat.c | 2 | ||||
-rw-r--r-- | src/game/g_local.h | 23 | ||||
-rw-r--r-- | src/game/g_main.c | 196 | ||||
-rw-r--r-- | src/game/tremulous.h | 10 |
9 files changed, 289 insertions, 54 deletions
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c index 68f3d3b0..e4c0402a 100644 --- a/src/cgame/cg_draw.c +++ b/src/cgame/cg_draw.c @@ -929,6 +929,9 @@ static void CG_DrawPlayerAmmoValue( rectDef_t *rect, vec4_t color ) BG_unpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, &value, NULL, NULL ); break; } + + if( value > 999 ) + value = 999; if( value > -1 ) { diff --git a/src/game/g_active.c b/src/game/g_active.c index f9e14243..cad4a2cf 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -349,12 +349,15 @@ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd ) if( ( client->buttons & BUTTON_ATTACK ) && !( client->oldbuttons & BUTTON_ATTACK ) ) { - if( client->pers.teamSelection == PTE_NONE ) - G_TriggerMenu( client->ps.clientNum, MN_TEAM ); - else if( client->pers.teamSelection == PTE_ALIENS ) - G_TriggerMenu( client->ps.clientNum, MN_A_CLASS ); - else if( client->pers.teamSelection == PTE_HUMANS ) - G_TriggerMenu( client->ps.clientNum, MN_H_SPAWN ); + if( client->pers.classSelection == PCL_NONE ) + { + if( client->pers.teamSelection == PTE_NONE ) + G_TriggerMenu( client->ps.clientNum, MN_TEAM ); + else if( client->pers.teamSelection == PTE_ALIENS ) + G_TriggerMenu( client->ps.clientNum, MN_A_CLASS ); + else if( client->pers.teamSelection == PTE_HUMANS ) + G_TriggerMenu( client->ps.clientNum, MN_H_SPAWN ); + } } } diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index fec593f2..5d487e4e 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -1968,6 +1968,33 @@ void HTeslaGen_Think( gentity_t *self ) /* ================ +HSpawn_Disappear + +Called when a human spawn is destroyed before it is spawned +think function +================ +*/ +void HSpawn_Disappear( gentity_t *self ) +{ + vec3_t dir; + + // we don't have a valid direction, so just point straight up + dir[ 0 ] = dir[ 1 ] = 0; + dir[ 2 ] = 1; + + self->s.eFlags |= EF_NODRAW; //don't draw the model once its destroyed + self->timestamp = level.time; + + self->think = freeBuildable; + self->nextthink = level.time + 100; + + self->r.contents = 0; //stop collisions... + trap_LinkEntity( self ); //...requires a relink +} + + +/* +================ HSpawn_blast Called when a human spawn explodes @@ -2012,14 +2039,19 @@ void HSpawn_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int G_setIdleBuildableAnim( self, BANIM_DESTROYED ); self->die = nullDieFunction; - self->think = HSpawn_Blast; 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 + } if( attacker && attacker->client && attacker->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) { @@ -2124,6 +2156,12 @@ void G_BuildableThink( gentity_t *ent, int msec ) ent->health = bHealth; } + if( ent->clientSpawnTime > 0 ) + ent->clientSpawnTime -= msec; + + if( ent->clientSpawnTime < 0 ) + ent->clientSpawnTime = 0; + //fall back on normal physics routines G_Physics( ent, msec ); } diff --git a/src/game/g_client.c b/src/game/g_client.c index dc1d37bf..4645780c 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -294,6 +294,9 @@ gentity_t *SelectAlienSpawnPoint( void ) if( !spot->s.groundEntityNum ) continue; + + if( spot->clientSpawnTime > 0 ) + continue; if( G_CheckSpawnPoint( spot->s.origin, spot->s.origin2, BA_A_SPAWN, NULL ) != NULL ) continue; @@ -342,6 +345,9 @@ gentity_t *SelectHumanSpawnPoint( void ) if( !spot->s.groundEntityNum ) continue; + if( spot->clientSpawnTime > 0 ) + continue; + if( G_CheckSpawnPoint( spot->s.origin, spot->s.origin2, BA_H_SPAWN, NULL ) != NULL ) continue; @@ -1250,6 +1256,11 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles { //start spawn animation on spawnPoint G_setBuildableAnim( spawnPoint, BANIM_SPAWN1, qtrue ); + + if( spawnPoint->biteam == PTE_ALIENS ) + spawnPoint->clientSpawnTime = ALIEN_SPAWN_REPEAT_TIME; + else if( spawnPoint->biteam == PTE_HUMANS ) + spawnPoint->clientSpawnTime = HUMAN_SPAWN_REPEAT_TIME; } } client->pers.teamState.state = TEAM_ACTIVE; diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 00ba30d2..bdc0a994 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -311,6 +311,9 @@ Cmd_Kill_f */ void Cmd_Kill_f( gentity_t *ent ) { + if( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) + return; + if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_NONE ) return; @@ -364,7 +367,7 @@ void Cmd_Team_f( gentity_t *ent ) { level.bankCredits[ ent->client->ps.clientNum ] = 0; ent->client->ps.persistant[ PERS_CREDIT ] = 0; - ent->client->pers.classSelection = 0; + ent->client->pers.classSelection = PCL_NONE; ClientSpawn( ent, NULL, NULL, NULL ); } @@ -1039,7 +1042,8 @@ void Cmd_Class_f( gentity_t *ent ) else { //spawning from an egg - ent->client->pers.classSelection = BG_FindClassNumForName( s ); + ent->client->pers.classSelection = + ent->client->ps.stats[ STAT_PCLASS ] = BG_FindClassNumForName( s ); if( ent->client->pers.classSelection != PCL_NONE ) { @@ -1048,20 +1052,8 @@ void Cmd_Class_f( gentity_t *ent ) if( allowedClasses[ i ] == ent->client->pers.classSelection && BG_FindStagesForClass( ent->client->pers.classSelection, g_alienStage.integer ) ) { - if( ( spawn = SelectTremulousSpawnPoint( ent->client->pers.teamSelection, - spawn_origin, spawn_angles ) ) && - level.numAlienSpawns > 0 ) //sanity check - { - ent->client->sess.sessionTeam = TEAM_FREE; - ClientUserinfoChanged( clientNum ); - ClientSpawn( ent, spawn, spawn_origin, spawn_angles ); - return; - } - else - { - trap_SendServerCommand( ent-g_entities, va( "print \"No suitable spawns available\n\"" ) ); - return; - } + G_PushSpawnQueue( &level.alienSpawnQueue, clientNum ); + return; } } @@ -1084,7 +1076,8 @@ void Cmd_Class_f( gentity_t *ent ) return; } - ent->client->pers.classSelection = PCL_H_BASE; + ent->client->pers.classSelection = + ent->client->ps.stats[ STAT_PCLASS ] = PCL_H_BASE; //set the item to spawn with if( !Q_stricmp( s, BG_FindNameForWeapon( WP_MACHINEGUN ) ) ) @@ -1098,19 +1091,7 @@ void Cmd_Class_f( gentity_t *ent ) return; } - if( ( spawn = SelectTremulousSpawnPoint( ent->client->pers.teamSelection, - spawn_origin, spawn_angles ) ) && - level.numHumanSpawns > 0 ) //sanity check - { - ent->client->sess.sessionTeam = TEAM_FREE; - ClientUserinfoChanged( clientNum ); - ClientSpawn( ent, spawn, spawn_origin, spawn_angles ); - } - else - { - trap_SendServerCommand( ent-g_entities, va( "print \"No suitable spawns available\n\"" ) ); - return; - } + G_PushSpawnQueue( &level.humanSpawnQueue, clientNum ); } else if( ent->client->pers.teamSelection == PTE_NONE ) { @@ -1145,7 +1126,7 @@ void Cmd_Destroy_f( gentity_t *ent, qboolean deconstruct ) trap_Trace( &tr, ent->client->ps.origin, NULL, NULL, end, ent->s.number, MASK_PLAYERSOLID ); traceEnt = &g_entities[ tr.entityNum ]; - if( tr.fraction < 1.0 && + if( tr.fraction < 1.0f && ( traceEnt->s.eType == ET_BUILDABLE ) && ( traceEnt->biteam == ent->client->pers.teamSelection ) && ( ( ent->client->ps.weapon >= WP_ABUILD ) && diff --git a/src/game/g_combat.c b/src/game/g_combat.c index d5e6f2f7..675b917d 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -297,7 +297,7 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int Cmd_Score_f( g_entities + i ); } - self->client->pers.classSelection = 0; //TA: reset the classtype + self->client->pers.classSelection = PCL_NONE; //TA: reset the classtype self->takedamage = qtrue; // can still be gibbed diff --git a/src/game/g_local.h b/src/game/g_local.h index 2026470d..ff8b7595 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -199,6 +199,7 @@ struct gentity_s int overmindSpawnsTimer; int nextPhysicsTime; //TA: buildables don't need to check what they're sitting on // every single frame.. so only do it periodically + int clientSpawnTime; //TA: the time until this spawn can spawn a client int credits[ MAX_CLIENTS ]; //TA: human credits for each client qboolean creditsHash[ MAX_CLIENTS ]; //TA: track who has claimed credit @@ -389,6 +390,25 @@ struct gclient_s int retriggerArmouryMenu; //TA: frame number to retrigger the armoury menu }; + +typedef struct spawnQueue_s +{ + int clients[ MAX_CLIENTS ]; + + int front, back; +} spawnQueue_t; + +#define QUEUE_PLUS1(x) (((x)+1)%MAX_CLIENTS) +#define QUEUE_MINUS1(x) (((x)-1)%MAX_CLIENTS) + +int G_InitSpawnQueue( spawnQueue_t *sq ); +int G_GetSpawnQueueLength( spawnQueue_t *sq ); +int G_PopSpawnQueue( spawnQueue_t *sq ); +void G_PushSpawnQueue( spawnQueue_t *sq, int clientNum ); +qboolean G_RemoveFromSpawnQueue( spawnQueue_t *sq, int clientNum ); +int G_GetPosInSpawnQueue( spawnQueue_t *sq, int clientNum ); + + #define MAX_LOCDAMAGE_TEXT 8192 #define MAX_LOCDAMAGE_REGIONS 16 @@ -524,6 +544,9 @@ typedef struct qboolean overmindPresent; pTeam_t lastWin; + + spawnQueue_t alienSpawnQueue; + spawnQueue_t humanSpawnQueue; } level_locals_t; // diff --git a/src/game/g_main.c b/src/game/g_main.c index f57b385f..53b61108 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -186,8 +186,8 @@ void G_RunFrame( int levelTime ); void G_ShutdownGame( int restart ); void CheckExitRules( void ); -void countSpawns( void ); -void calculateBuildPoints( void ); +void G_CountSpawns( void ); +void G_CalculateBuildPoints( void ); /* ================ @@ -527,6 +527,8 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) G_InitDamageLocations( ); G_GenerateParticleFileList( ); G_InitMapRotations( ); + G_InitSpawnQueue( &level.alienSpawnQueue ); + G_InitSpawnQueue( &level.humanSpawnQueue ); if( g_debugMapRotation.integer ) G_PrintRotations( ); @@ -542,7 +544,7 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) G_RemapTeamShaders( ); //TA: so the server counts the spawns without a client attached - countSpawns( ); + G_CountSpawns( ); } @@ -667,12 +669,180 @@ int QDECL SortRanks( const void *a, const void *b ) /* ============ -countSpawns +G_InitSpawnQueue + +Initialise a spawn queue +============ +*/ +int G_InitSpawnQueue( spawnQueue_t *sq ) +{ + sq->back = sq->front = 0; + sq->back = QUEUE_MINUS1( sq->back ); +} + +/* +============ +G_GetSpawnQueueLength + +Return tha length of a spawn queue +============ +*/ +int G_GetSpawnQueueLength( spawnQueue_t *sq ) +{ +/* if( sq->back < sq->front ) + return ( sq->back + MAX_CLIENTS - sq->front + 1 ) % MAX_CLIENTS; + else*/ + return ( sq->back - sq->front + 1 ) % MAX_CLIENTS; +} + +/* +============ +G_PopSpawnQueue + +Remove from front element from a spawn queue +============ +*/ +int G_PopSpawnQueue( spawnQueue_t *sq ) +{ + int popee = sq->front; + + if( G_GetSpawnQueueLength( sq ) > 0 ) + { + sq->front = QUEUE_PLUS1( sq->front ); + return sq->clients[ popee ]; + } + else + return -1; +} + +/* +============ +G_PushSpawnQueue + +Add an element to the back of the spawn queue +============ +*/ +void G_PushSpawnQueue( spawnQueue_t *sq, int clientNum ) +{ + sq->back = QUEUE_PLUS1( sq->back ); + sq->clients[ sq->back ] = clientNum; +} + +/* +============ +G_RemoveFromSpawnQueue + +remove a specific client from a spawn queue +============ +*/ +qboolean G_RemoveFromSpawnQueue( spawnQueue_t *sq, int clientNum ) +{ + int i = sq->front; + + do + { + if( sq->clients[ i ] == clientNum ) + { + //and this kids, is why it would have + //been better to use an LL for internal + //representation + do + { + sq->clients[ i ] = sq->clients[ QUEUE_PLUS1( i ) ]; + + i = QUEUE_PLUS1( 1 ); + } while( i != sq->back ); + + sq->back = QUEUE_MINUS1( sq->back ); + + return qtrue; + } + + i = QUEUE_PLUS1( 1 ); + } while( i != QUEUE_PLUS1( sq->back ) ); + + return qfalse; +} + +/* +============ +G_GetPosInSpawnQueue + +Get the position of a client in a spawn queue +============ +*/ +int G_GetPosInSpawnQueue( spawnQueue_t *sq, int clientNum ) +{ + int i = sq->front; + + do + { + if( sq->clients[ i ] == clientNum ) + { + if( i < sq->front ) + return i + MAX_CLIENTS - sq->front + 1; + else + return i - sq->front + 1; + } + + i = QUEUE_PLUS1( 1 ); + } while( i != QUEUE_PLUS1( sq->back ) ); + + return -1; +} + +/* +============ +G_SpawnClients + +Spawn queued clients +============ +*/ +void G_SpawnClients( pTeam_t team ) +{ + int clientNum; + gentity_t *ent, *spawn; + vec3_t spawn_origin, spawn_angles; + spawnQueue_t *sq; + int numSpawns; + + if( team == PTE_ALIENS ) + { + sq = &level.alienSpawnQueue; + numSpawns = level.numAlienSpawns; + } + else if( team == PTE_HUMANS ) + { + sq = &level.humanSpawnQueue; + numSpawns = level.numHumanSpawns; + } + + if( G_GetSpawnQueueLength( sq ) > 0 && numSpawns > 0 ) + { + if( ( spawn = SelectTremulousSpawnPoint( team, spawn_origin, spawn_angles ) ) ) + { + clientNum = G_PopSpawnQueue( sq ); + + if( clientNum < 0 ) + return; + + ent = &g_entities[ clientNum ]; + + ent->client->sess.sessionTeam = TEAM_FREE; + ClientUserinfoChanged( clientNum ); + ClientSpawn( ent, spawn, spawn_origin, spawn_angles ); + } + } +} + +/* +============ +G_CountSpawns Counts the number of spawns for each team ============ */ -void countSpawns( void ) +void G_CountSpawns( void ) { int i; gentity_t *ent; @@ -696,12 +866,12 @@ void countSpawns( void ) /* ============ -calculateBuildPoints +G_CalculateBuildPoints Recalculate the quantity of building points available to the teams ============ */ -void calculateBuildPoints( void ) +void G_CalculateBuildPoints( void ) { int i; int bclass; @@ -777,10 +947,10 @@ void calculateBuildPoints( void ) /* ============ -CalculateStages +G_CalculateStages ============ */ -void CalculateStages( void ) +void G_CalculateStages( void ) { float alienPlayerCountMod = (float)level.numAlienClients / PLAYER_COUNT_MOD; float humanPlayerCountMod = (float)level.numAlienClients / PLAYER_COUNT_MOD; @@ -1665,9 +1835,11 @@ void G_RunFrame( int levelTime ) end = trap_Milliseconds(); //TA: - countSpawns( ); - calculateBuildPoints( ); - CalculateStages( ); + G_CountSpawns( ); + G_CalculateBuildPoints( ); + G_CalculateStages( ); + G_SpawnClients( PTE_ALIENS ); + G_SpawnClients( PTE_HUMANS ); // see if it is time to end the level CheckExitRules( ); diff --git a/src/game/tremulous.h b/src/game/tremulous.h index 1c001c7a..707a0929 100644 --- a/src/game/tremulous.h +++ b/src/game/tremulous.h @@ -207,9 +207,9 @@ #define ASPAWN_CREEPSIZE 120 #define ASPAWN_VALUE 150 -#define BARRICADE_BP 8 +#define BARRICADE_BP 10 #define BARRICADE_BT 20000 -#define BARRICADE_HEALTH ABHM(350) +#define BARRICADE_HEALTH ABHM(400) #define BARRICADE_REGEN 12 #define BARRICADE_SPLASHDAMAGE 50 #define BARRICADE_SPLASHRADIUS 50 @@ -224,7 +224,7 @@ #define BOOSTER_CREEPSIZE 120 #define BOOSTER_INTERVAL 30000 //time in msec between uses (per player) -#define ACIDTUBE_BP 5 +#define ACIDTUBE_BP 8 #define ACIDTUBE_BT 15000 #define ACIDTUBE_HEALTH ABHM(200) #define ACIDTUBE_REGEN 8 @@ -293,6 +293,8 @@ #define ALIEN_POISON_DMG 30 #define ALIEN_POISON_DIVIDER (1.0f/1.32f) //about 1.0/(time`th root of damage) +#define ALIEN_SPAWN_REPEAT_TIME 10000 + /* * HUMAN weapons @@ -527,6 +529,8 @@ #define STAMINA_SPRINT_TAKE 8 #define STAMINA_LARMOUR_TAKE 4 +#define HUMAN_SPAWN_REPEAT_TIME 10000 + /* * Misc */ |