/* * G_EndServerFrames_UpdateChaseCam */ void G_EndServerFrames_UpdateChaseCam( void ) { int i, team; edict_t *ent; // do it by teams, so spectators can copy the chasecam information from players for( team = TEAM_PLAYERS; team < GS_MAX_TEAMS; team++ ) { for( i = 0; i < teamlist[team].numplayers; i++ ) { ent = game.edicts + teamlist[team].playerIndices[i]; if( trap_GetClientState( PLAYERNUM(ent) ) < CS_SPAWNED ) { G_Chase_SetChaseActive( ent, false ); continue; } G_EndFrame_UpdateChaseCam( ent ); } } // Do spectators last team = TEAM_SPECTATOR; for( i = 0; i < teamlist[team].numplayers; i++ ) { ent = game.edicts + teamlist[team].playerIndices[i]; if( trap_GetClientState( PLAYERNUM(ent) ) < CS_SPAWNED ) { G_Chase_SetChaseActive( ent, false ); continue; } G_EndFrame_UpdateChaseCam( ent ); } }
/* * Cmd_SwitchChaseCamMode_f */ void Cmd_SwitchChaseCamMode_f( edict_t *ent ) { if( ent->s.team == TEAM_SPECTATOR ) { if( ent->r.client->resp.chase.active ) { G_SpectatorMode( ent ); } else { G_Chase_SetChaseActive( ent, true ); G_ChaseStep( ent, 0 ); } } }
/* * G_SpectatorMode */ void G_SpectatorMode( edict_t *ent ) { // join spectator team if( ent->s.team != TEAM_SPECTATOR ) { G_Teams_JoinTeam( ent, TEAM_SPECTATOR ); G_PrintMsg( NULL, "%s%s joined the %s%s team.\n", ent->r.client->netname, S_COLOR_WHITE, GS_TeamName( ent->s.team ), S_COLOR_WHITE ); } // was in chasecam if( ent->r.client->resp.chase.active ) { ent->r.client->level.showscores = false; G_Chase_SetChaseActive( ent, false ); // reset movement speeds ent->r.client->ps.pmove.stats[PM_STAT_MAXSPEED] = DEFAULT_PLAYERSPEED; ent->r.client->ps.pmove.stats[PM_STAT_JUMPSPEED] = DEFAULT_JUMPSPEED; ent->r.client->ps.pmove.stats[PM_STAT_DASHSPEED] = DEFAULT_DASHSPEED; } ent->movetype = MOVETYPE_NOCLIP; }
/* * G_ChasePlayer */ void G_ChasePlayer( edict_t *ent, const char *name, bool teamonly, int followmode ) { int i; edict_t *e; gclient_t *client; int targetNum = -1; int oldTarget; bool can_follow = true; char colorlessname[MAX_NAME_BYTES]; client = ent->r.client; oldTarget = client->resp.chase.target; if( teamonly && !client->teamstate.is_coach ) can_follow = false; if( !can_follow && followmode ) { G_PrintMsg( ent, "Chasecam follow mode unavailable\n" ); followmode = false; } if( ent->r.client->resp.chase.followmode && !followmode ) G_PrintMsg( ent, "Disabling chasecam follow mode\n" ); // always disable chasing as a start memset( &client->resp.chase, 0, sizeof( chasecam_t ) ); // locate the requested target if( name && name[0] ) { // find it by player names for( e = game.edicts + 1; PLAYERNUM( e ) < gs.maxclients; e++ ) { if( !G_Chase_IsValidTarget( ent, e, teamonly ) ) continue; Q_strncpyz( colorlessname, COM_RemoveColorTokens( e->r.client->netname ), sizeof(colorlessname) ); if( !Q_stricmp( COM_RemoveColorTokens( name ), colorlessname ) ) { targetNum = PLAYERNUM( e ); break; } } // didn't find it by name, try by numbers if( targetNum == -1 ) { i = atoi( name ); if( i >= 0 && i < gs.maxclients ) { e = game.edicts + 1 + i; if( G_Chase_IsValidTarget( ent, e, teamonly ) ) targetNum = PLAYERNUM( e ); } } if( targetNum == -1 ) G_PrintMsg( ent, "Requested chasecam target is not available\n" ); } // try to reuse old target if we didn't find a valid one if( targetNum == -1 && oldTarget > 0 && oldTarget < gs.maxclients ) { e = game.edicts + 1 + oldTarget; if( G_Chase_IsValidTarget( ent, e, teamonly ) ) targetNum = PLAYERNUM( e ); } // if we still don't have a target, just pick the first valid one if( targetNum == -1 ) { for( e = game.edicts + 1; PLAYERNUM( e ) < gs.maxclients; e++ ) { if( !G_Chase_IsValidTarget( ent, e, teamonly ) ) continue; targetNum = PLAYERNUM( e ); break; } } // make the client a ghost G_GhostClient( ent ); if( targetNum != -1 ) { // we found a target, set up the chasecam client->resp.chase.target = targetNum + 1; client->resp.chase.teamonly = teamonly; client->resp.chase.followmode = followmode; G_Chase_SetChaseActive( ent, true ); } else { // stay as observer if( !teamonly ) ent->movetype = MOVETYPE_NOCLIP; client->level.showscores = false; G_Chase_SetChaseActive( ent, false ); G_CenterPrintMsg( ent, "No one to chase" ); } }