summaryrefslogtreecommitdiff
path: root/src/game/g_active.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/g_active.c')
-rw-r--r--src/game/g_active.c158
1 files changed, 85 insertions, 73 deletions
diff --git a/src/game/g_active.c b/src/game/g_active.c
index 47fd446c..9fe75f92 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -393,43 +393,85 @@ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd )
{
pmove_t pm;
gclient_t *client;
- qboolean attack1, attack3;
+ int clientNum;
+ qboolean attack1, attack3, following, queued;
client = ent->client;
client->oldbuttons = client->buttons;
client->buttons = ucmd->buttons;
- attack1 = ( ( client->buttons & BUTTON_ATTACK ) &&
- !( client->oldbuttons & BUTTON_ATTACK ) );
- attack3 = ( ( client->buttons & BUTTON_USE_HOLDABLE ) &&
- !( client->oldbuttons & BUTTON_USE_HOLDABLE ) );
+ attack1 = ( client->buttons & BUTTON_ATTACK ) &&
+ !( client->oldbuttons & BUTTON_ATTACK );
+ attack3 = ( client->buttons & BUTTON_USE_HOLDABLE ) &&
+ !( client->oldbuttons & BUTTON_USE_HOLDABLE );
+
+ // We are in following mode only if we are following a non-spectating client
+ following = client->sess.spectatorState != SPECTATOR_FOLLOW;
+ if( following )
+ {
+ clientNum = client->sess.spectatorClient;
+ if( clientNum < 0 || clientNum > level.maxclients ||
+ !g_entities[ clientNum ].client ||
+ !g_entities[ clientNum ].client->sess.sessionTeam == TEAM_SPECTATOR )
+ following = qfalse;
+ }
+
+ // Check to see if we are in the spawn queue
+ queued = qfalse;
+ if( client->pers.teamSelection == PTE_ALIENS )
+ queued = G_SearchSpawnQueue( &level.alienSpawnQueue, ent - g_entities );
+ else if( client->pers.teamSelection == PTE_HUMANS )
+ queued = G_SearchSpawnQueue( &level.humanSpawnQueue, ent - g_entities );
+
+ // Wants to get out of spawn queue
+ if( attack1 && queued )
+ {
+ if( client->sess.spectatorState == SPECTATOR_FOLLOW )
+ G_StopFollowing( ent );
+ if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
+ G_RemoveFromSpawnQueue( &level.alienSpawnQueue, client->ps.clientNum );
+ else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ G_RemoveFromSpawnQueue( &level.humanSpawnQueue, client->ps.clientNum );
+ client->pers.classSelection = PCL_NONE;
+ client->ps.stats[ STAT_PCLASS ] = PCL_NONE;
+ client->ps.pm_flags &= ~PMF_QUEUED;
+ queued = qfalse;
+ }
+ else if( attack1 && client->pers.teamSelection != PTE_NONE &&
+ client->pers.classSelection == PCL_NONE )
+ {
+ // Wants to get into spawn queue
+ if( client->sess.spectatorState == SPECTATOR_FOLLOW )
+ G_StopFollowing( ent );
+ 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->sess.spectatorState != SPECTATOR_FOLLOW )
+ // We are either not following anyone or following a spectator
+ if( !following )
{
- if( client->sess.spectatorState == SPECTATOR_LOCKED )
+ if( client->sess.spectatorState == SPECTATOR_LOCKED ||
+ client->sess.spectatorState == SPECTATOR_FOLLOW )
client->ps.pm_type = PM_FREEZE;
else
client->ps.pm_type = PM_SPECTATOR;
- // in case the client entered the queue while following a teammate
- if( ( client->pers.teamSelection == PTE_ALIENS &&
- G_SearchSpawnQueue( &level.alienSpawnQueue, ent-g_entities ) ) ||
- ( client->pers.teamSelection == PTE_HUMANS &&
- G_SearchSpawnQueue( &level.alienSpawnQueue, ent-g_entities ) ) )
- {
+ if( queued )
client->ps.pm_flags |= PMF_QUEUED;
- }
client->ps.speed = BG_FindSpeedForClass( client->ps.stats[ STAT_PCLASS ] );
-
client->ps.stats[ STAT_STAMINA ] = 0;
client->ps.stats[ STAT_MISC ] = 0;
client->ps.stats[ STAT_BUILDABLE ] = 0;
client->ps.stats[ STAT_PCLASS ] = PCL_NONE;
client->ps.weapon = WP_NONE;
- // set up for pmove
+ // Set up for pmove
memset( &pm, 0, sizeof( pm ) );
pm.ps = &client->ps;
pm.cmd = *ucmd;
@@ -437,67 +479,36 @@ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd )
pm.trace = trap_Trace;
pm.pointcontents = trap_PointContents;
- // perform a pmove
+ // Perform a pmove
Pmove( &pm );
- // save results of pmove
+ // Save results of pmove
VectorCopy( client->ps.origin, ent->s.origin );
G_TouchTriggers( ent );
trap_UnlinkEntity( ent );
- if( ( attack1 || attack3 ) && ( client->ps.pm_flags & PMF_QUEUED ) )
- {
- if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
- G_RemoveFromSpawnQueue( &level.alienSpawnQueue, client->ps.clientNum );
- else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
- G_RemoveFromSpawnQueue( &level.humanSpawnQueue, client->ps.clientNum );
-
- client->pers.classSelection = PCL_NONE;
- client->ps.stats[ STAT_PCLASS ] = PCL_NONE;
- }
-
- if( attack1 && 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 );
- }
-
- //set the queue position for the client side
+ // Set the queue position and spawn count for the client side
if( client->ps.pm_flags & PMF_QUEUED )
{
if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
{
client->ps.persistant[ PERS_QUEUEPOS ] =
G_GetPosInSpawnQueue( &level.alienSpawnQueue, client->ps.clientNum );
+ client->ps.persistant[ PERS_SPAWNS ] = level.numAlienSpawns;
}
else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
{
client->ps.persistant[ PERS_QUEUEPOS ] =
G_GetPosInSpawnQueue( &level.humanSpawnQueue, client->ps.clientNum );
+ client->ps.persistant[ PERS_SPAWNS ] = level.numHumanSpawns;
}
}
}
- else if( attack1 && ent->client->sess.spectatorState == SPECTATOR_FOLLOW )
- {
- G_StopFollowing( ent );
- client->pers.classSelection = PCL_NONE;
- if( client->pers.teamSelection == PTE_NONE )
- G_TriggerMenu( ent-g_entities, MN_TEAM );
- else if( client->pers.teamSelection == PTE_ALIENS )
- G_TriggerMenu( ent-g_entities, MN_A_CLASS );
- else if( client->pers.teamSelection == PTE_HUMANS )
- G_TriggerMenu( ent-g_entities, MN_H_SPAWN );
- }
-
+
+ // Tertiary fire or use button toggles following mode
if( attack3 )
- {
G_ToggleFollow( ent );
- }
}
@@ -592,11 +603,10 @@ void ClientTimerActions( gentity_t *ent, int msec )
if( stopped || client->ps.pm_type == PM_JETPACK )
client->ps.stats[ STAT_STAMINA ] += STAMINA_STOP_RESTORE;
else if( client->ps.stats[ STAT_STATE ] & SS_SPEEDBOOST )
- client->ps.stats[ STAT_STAMINA ] -= STAMINA_SPRINT_TAKE;
+ client->ps.stats[ STAT_STAMINA ] -= STAMINA_SPRINT_TAKE;
else if( walking || crouched )
client->ps.stats[ STAT_STAMINA ] += STAMINA_WALK_RESTORE;
-
-
+
// Check stamina limits
if( client->ps.stats[ STAT_STAMINA ] > MAX_STAMINA )
client->ps.stats[ STAT_STAMINA ] = MAX_STAMINA;
@@ -623,6 +633,7 @@ void ClientTimerActions( gentity_t *ent, int msec )
}
else
client->ps.stats[ STAT_MISC ] = 0;
+
}
if( !( ucmd->buttons & BUTTON_ATTACK2 ) || client->charging ||
@@ -645,7 +656,6 @@ void ClientTimerActions( gentity_t *ent, int msec )
//can't charge backwards
if( ucmd->forwardmove < 0 )
client->ps.stats[ STAT_MISC ] = 0;
-
if( client->ps.stats[ STAT_MISC ] > LEVEL4_TRAMPLE_CHARGE_MAX )
client->ps.stats[ STAT_MISC ] = LEVEL4_TRAMPLE_CHARGE_MAX;
}
@@ -838,11 +848,10 @@ void ClientTimerActions( gentity_t *ent, int msec )
if( modifier >= 3.0f )
client->ps.stats[ STAT_STATE ] |= SS_HEALING_3X;
else if( modifier >= 2.0f )
-
client->ps.stats[ STAT_STATE ] |= SS_HEALING_2X;
if( creep || modifier != 1.0f )
client->ps.stats[ STAT_STATE ] |= SS_HEALING_ACTIVE;
- else
+ else
client->ps.stats[ STAT_STATE ] &= ~SS_HEALING_ACTIVE;
if( ent->health > 0 &&
@@ -1493,15 +1502,13 @@ void ClientThink_real( gentity_t *ent )
if( BG_InventoryContainsUpgrade( UP_BATTLESUIT, client->ps.stats ) )
timeLeft -= BSUIT_PCLOUD_PROTECTION;
-
if( BG_InventoryContainsUpgrade( UP_HELMET, client->ps.stats ) )
timeLeft -= HELMET_PCLOUD_PROTECTION;
-
if( BG_InventoryContainsUpgrade( UP_LIGHTARMOUR, client->ps.stats ) )
timeLeft -= LIGHTARMOUR_PCLOUD_PROTECTION;
if( timeLeft <= 0 )
- client->ps.stats[ STAT_STATE ] &= ~SS_POISONCLOUDED;
+ client->ps.stats[ STAT_STATE ] &= ~SS_POISONCLOUDED;
}
if( client->ps.stats[ STAT_STATE ] & SS_POISONED &&
@@ -1872,18 +1879,23 @@ void SpectatorClientEndFrame( gentity_t *ent )
if( ent->client->sess.spectatorState == SPECTATOR_FOLLOW )
{
clientNum = ent->client->sess.spectatorClient;
-
- if( clientNum >= 0 )
+ if( clientNum >= 0 && clientNum < level.maxclients )
{
cl = &level.clients[ clientNum ];
-
- if( cl->pers.connected == CON_CONNECTED && cl->sess.sessionTeam != TEAM_SPECTATOR )
+ if( cl->pers.connected == CON_CONNECTED )
{
- flags = ( cl->ps.eFlags & ~( EF_VOTED | EF_TEAMVOTED ) ) |
- ( ent->client->ps.eFlags & ( EF_VOTED | EF_TEAMVOTED ) );
- ent->client->ps = cl->ps;
- ent->client->ps.pm_flags |= PMF_FOLLOW;
- ent->client->ps.eFlags = flags;
+ if( cl->sess.sessionTeam != TEAM_SPECTATOR )
+ {
+ flags = ( cl->ps.eFlags & ~( EF_VOTED | EF_TEAMVOTED ) ) |
+ ( ent->client->ps.eFlags & ( EF_VOTED | EF_TEAMVOTED ) );
+ ent->client->ps = cl->ps;
+ ent->client->ps.eFlags = flags;
+ ent->client->ps.pm_flags |= PMF_FOLLOW;
+ }
+ else
+ ent->client->ps.pm_flags &= ~PMF_FOLLOW;
+ ent->client->ps.clientNum = clientNum;
+ ent->client->ps.pm_flags &= ~PMF_QUEUED;
}
}
}
@@ -1910,7 +1922,7 @@ void ClientEndFrame( gentity_t *ent )
pers = &ent->client->pers;
- // save a copy of things from playerState in case of SPECTATOR_FOLLOW
+ // save a copy of certain playerState values in case of SPECTATOR_FOLLOW
pers->score = ent->client->ps.persistant[ PERS_SCORE ];
pers->credit = ent->client->ps.persistant[ PERS_CREDIT ];