codemp/game/g_main.c File Reference

#include "g_local.h"
#include "g_ICARUScb.h"
#include "g_nav.h"
#include "bg_saga.h"
#include "../namespace_begin.h"
#include "../namespace_end.h"

Go to the source code of this file.

Data Structures

struct  cvarTable_t

Defines

#define JETPACK_DEFUEL_RATE   200
#define JETPACK_REFUEL_RATE   150
#define CLOAK_DEFUEL_RATE   200
#define CLOAK_REFUEL_RATE   150

Functions

void G_InitGame (int levelTime, int randomSeed, int restart)
void G_RunFrame (int levelTime)
void G_ShutdownGame (int restart)
void CheckExitRules (void)
void G_ROFF_NotetrackCallback (gentity_t *cent, const char *notetrack)
qboolean G_ParseSpawnVars (qboolean inSubBSP)
void G_SpawnGEntityFromSpawnVars (qboolean inSubBSP)
qboolean NAV_ClearPathToPoint (gentity_t *self, vec3_t pmins, vec3_t pmaxs, vec3_t point, int clipmask, int okToHitEntNum)
qboolean NPC_ClearLOS2 (gentity_t *ent, const vec3_t end)
int NAVNEW_ClearPathBetweenPoints (vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int ignore, int clipmask)
qboolean NAV_CheckNodeFailedForEnt (gentity_t *ent, int nodeNum)
qboolean G_EntIsUnlockedDoor (int entityNum)
qboolean G_EntIsDoor (int entityNum)
qboolean G_EntIsBreakable (int entityNum)
qboolean G_EntIsRemovableUsable (int entNum)
void CP_FindCombatPointWaypoints (void)
int vmMain (int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11)
void QDECL G_Printf (const char *fmt,...)
void QDECL G_Error (const char *fmt,...)
void G_FindTeams (void)
void G_RemapTeamShaders (void)
void G_RegisterCvars (void)
void G_UpdateCvars (void)
void WP_SaberLoadParms (void)
void BG_VehicleLoadParms (void)
void RemoveAllWP (void)
void BG_ClearVehicleParseParms (void)
void QDECL Com_Error (int level, const char *error,...)
void QDECL Com_Printf (const char *msg,...)
void AddTournamentPlayer (void)
void RemoveTournamentLoser (void)
void G_PowerDuelCount (int *loners, int *doubles, qboolean countSpec)
void AddPowerDuelPlayers (void)
void RemovePowerDuelLosers (void)
void RemoveDuelDrawLoser (void)
void RemoveTournamentWinner (void)
void AdjustTournamentScores (void)
int QDECL SortRanks (const void *a, const void *b)
qboolean G_CanResetDuelists (void)
void G_ResetDuelists (void)
void CalculateRanks (void)
void SendScoreboardMessageToAllClients (void)
void MoveClientToIntermission (gentity_t *ent)
void FindIntermissionPoint (void)
qboolean DuelLimitHit (void)
void BeginIntermission (void)
void DuelResetWinsLosses (void)
void SiegeDoTeamAssign (void)
void ExitLevel (void)
void QDECL G_LogPrintf (const char *fmt,...)
void LogExit (const char *string)
void CheckIntermissionExit (void)
qboolean ScoreIsTied (void)
void G_RemoveDuelist (int team)
void CheckTournament (void)
void G_KickAllBots (void)
void CheckVote (void)
void PrintTeam (int team, char *message)
void SetLeader (int team, int client)
void CheckTeamLeader (int team)
void CheckTeamVote (int team)
void CheckCvars (void)
void G_RunThink (gentity_t *ent)
void NAV_CheckCalcPaths (void)
int BG_GetTime (void)
void ClearNPCGlobals (void)
void AI_UpdateGroups (void)
void ClearPlayerAlertEvents (void)
void SiegeCheckTimers (void)
void WP_SaberStartMissileBlockCheck (gentity_t *self, usercmd_t *ucmd)
void Jedi_Decloak (gentity_t *self)
qboolean G_PointInBounds (vec3_t point, vec3_t mins, vec3_t maxs)
const char * G_GetStringEdString (char *refSection, char *refName)

Variables

level_locals_t level
int eventClearTime = 0
int fatalErrors
int killPlayerTimer = 0
gentity_t g_entities [MAX_GENTITIES]
gclient_t g_clients [MAX_CLIENTS]
qboolean gDuelExit = qfalse
vmCvar_t g_trueJedi
vmCvar_t g_gametype
vmCvar_t g_MaxHolocronCarry
vmCvar_t g_ff_objectives
vmCvar_t g_autoMapCycle
vmCvar_t g_dmflags
vmCvar_t g_maxForceRank
vmCvar_t g_forceBasedTeams
vmCvar_t g_privateDuel
vmCvar_t g_allowNPC
vmCvar_t g_armBreakage
vmCvar_t g_saberLocking
vmCvar_t g_saberLockFactor
vmCvar_t g_saberTraceSaberFirst
vmCvar_t d_saberKickTweak
vmCvar_t d_powerDuelPrint
vmCvar_t d_saberGhoul2Collision
vmCvar_t g_saberBladeFaces
vmCvar_t d_saberAlwaysBoxTrace
vmCvar_t d_saberBoxTraceSize
vmCvar_t d_siegeSeekerNPC
vmCvar_t g_debugMelee
vmCvar_t g_stepSlideFix
vmCvar_t g_noSpecMove
vmCvar_t d_perPlayerGhoul2
vmCvar_t d_projectileGhoul2Collision
vmCvar_t g_g2TraceLod
vmCvar_t g_optvehtrace
vmCvar_t g_locationBasedDamage
vmCvar_t g_allowHighPingDuelist
vmCvar_t g_logClientInfo
vmCvar_t g_slowmoDuelEnd
vmCvar_t g_saberDamageScale
vmCvar_t g_useWhileThrowing
vmCvar_t g_RMG
vmCvar_t g_svfps
vmCvar_t g_forceRegenTime
vmCvar_t g_spawnInvulnerability
vmCvar_t g_forcePowerDisable
vmCvar_t g_weaponDisable
vmCvar_t g_duelWeaponDisable
vmCvar_t g_allowDuelSuicide
vmCvar_t g_fraglimitVoteCorrection
vmCvar_t g_fraglimit
vmCvar_t g_duel_fraglimit
vmCvar_t g_timelimit
vmCvar_t g_capturelimit
vmCvar_t d_saberInterpolate
vmCvar_t g_friendlyFire
vmCvar_t g_friendlySaber
vmCvar_t g_password
vmCvar_t g_needpass
vmCvar_t g_maxclients
vmCvar_t g_maxGameClients
vmCvar_t g_dedicated
vmCvar_t g_developer
vmCvar_t g_speed
vmCvar_t g_gravity
vmCvar_t g_cheats
vmCvar_t g_knockback
vmCvar_t g_quadfactor
vmCvar_t g_forcerespawn
vmCvar_t g_siegeRespawn
vmCvar_t g_inactivity
vmCvar_t g_debugMove
vmCvar_t g_debugDamage
vmCvar_t g_debugAlloc
vmCvar_t g_debugServerSkel
vmCvar_t g_weaponRespawn
vmCvar_t g_weaponTeamRespawn
vmCvar_t g_adaptRespawn
vmCvar_t g_motd
vmCvar_t g_synchronousClients
vmCvar_t g_warmup
vmCvar_t g_doWarmup
vmCvar_t g_restarted
vmCvar_t g_log
vmCvar_t g_logSync
vmCvar_t g_statLog
vmCvar_t g_statLogFile
vmCvar_t g_blood
vmCvar_t g_podiumDist
vmCvar_t g_podiumDrop
vmCvar_t g_allowVote
vmCvar_t g_teamAutoJoin
vmCvar_t g_teamForceBalance
vmCvar_t g_banIPs
vmCvar_t g_filterBan
vmCvar_t g_debugForward
vmCvar_t g_debugRight
vmCvar_t g_debugUp
vmCvar_t g_smoothClients
vmCvar_t pmove_fixed
vmCvar_t pmove_msec
vmCvar_t g_listEntity
vmCvar_t g_singlePlayer
vmCvar_t g_enableBreath
vmCvar_t g_dismember
vmCvar_t g_forceDodge
vmCvar_t g_timeouttospec
vmCvar_t g_saberDmgVelocityScale
vmCvar_t g_saberDmgDelay_Idle
vmCvar_t g_saberDmgDelay_Wound
vmCvar_t g_saberDebugPrint
vmCvar_t g_siegeTeamSwitch
vmCvar_t bg_fighterAltControl
vmCvar_t g_saberDebugBox
vmCvar_t d_altRoutes
vmCvar_t d_patched
vmCvar_t g_saberRealisticCombat
vmCvar_t g_saberRestrictForce
vmCvar_t d_saberSPStyleDamage
vmCvar_t g_debugSaberLocks
vmCvar_t g_saberLockRandomNess
vmCvar_t g_saberWallDamageScale
vmCvar_t d_saberStanceDebug
vmCvar_t debugNPCAI
vmCvar_t debugNPCFreeze
vmCvar_t debugNPCAimingBeam
vmCvar_t debugBreak
vmCvar_t debugNoRoam
vmCvar_t d_saberCombat
vmCvar_t d_JediAI
vmCvar_t d_noGroupAI
vmCvar_t d_asynchronousGroupAI
vmCvar_t d_slowmodeath
vmCvar_t d_noIntermissionWait
vmCvar_t g_spskill
vmCvar_t g_siegeTeam1
vmCvar_t g_siegeTeam2
vmCvar_t g_austrian
vmCvar_t g_powerDuelStartHealth
vmCvar_t g_powerDuelEndHealth
vmCvar_t g_showDuelHealths
stringID_table_t setTable []
char gSharedBuffer [MAX_G_SHARED_BUFFER_SIZE]
qboolean g_duelAssigning = qfalse
qboolean g_dontFrickinCheck = qfalse
qboolean gQueueScoreMessage = qfalse
int gQueueScoreMessageTime = 0
qboolean g_noPDuelCheck = qfalse
qboolean gSiegeRoundBegun
qboolean gSiegeRoundEnded
qboolean gSiegeRoundWinningTeam
siegePers_t g_siegePersistant
qboolean gDidDuelStuff = qfalse
qboolean g_endPDuel = qfalse
int g_duelPrintTimer = 0
int g_LastFrameTime = 0
int g_TimeSinceLastFrame = 0
qboolean gDoSlowMoDuel = qfalse
int gSlowMoDuelTime = 0
int g_siegeRespawnCheck = 0


Define Documentation

#define CLOAK_DEFUEL_RATE   200
 

Referenced by G_RunFrame().

#define CLOAK_REFUEL_RATE   150
 

Referenced by G_RunFrame().

#define JETPACK_DEFUEL_RATE   200
 

Referenced by G_RunFrame().

#define JETPACK_REFUEL_RATE   150
 

Referenced by G_RunFrame().


Function Documentation

void AddPowerDuelPlayers void   ) 
 

Definition at line 1330 of file g_main.c.

References client, level_locals_t::clients, CON_CONNECTED, clientPersistant_t::connected, clientSession_t::duelTeam, DUELTEAM_DOUBLE, DUELTEAM_FREE, DUELTEAM_LONE, g_entities, G_PowerDuelCount(), gclient_t, level, level_locals_t::maxclients, NULL, level_locals_t::numPlayingClients, gclient_s::pers, qfalse, qtrue, gclient_s::sess, clientSession_t::sessionTeam, SetTeam(), SPECTATOR_SCOREBOARD, clientSession_t::spectatorClient, clientSession_t::spectatorState, clientSession_t::spectatorTime, TEAM_SPECTATOR, and level_locals_t::warmupTime.

Referenced by CheckIntermissionExit(), and CheckTournament().

01331 {
01332         int                     i;
01333         int                     loners = 0;
01334         int                     doubles = 0;
01335         int                     nonspecLoners = 0;
01336         int                     nonspecDoubles = 0;
01337         gclient_t       *client;
01338         gclient_t       *nextInLine;
01339 
01340         if ( level.numPlayingClients >= 3 )
01341         {
01342                 return;
01343         }
01344 
01345         nextInLine = NULL;
01346 
01347         G_PowerDuelCount(&nonspecLoners, &nonspecDoubles, qfalse);
01348         if (nonspecLoners >= 1 && nonspecDoubles >= 2)
01349         { //we have enough people, stop
01350                 return;
01351         }
01352 
01353         //Could be written faster, but it's not enough to care I suppose.
01354         G_PowerDuelCount(&loners, &doubles, qtrue);
01355 
01356         if (loners < 1 || doubles < 2)
01357         { //don't bother trying to spawn anyone yet if the balance is not even set up between spectators
01358                 return;
01359         }
01360 
01361         //Count again, with only in-game clients in mind.
01362         loners = nonspecLoners;
01363         doubles = nonspecDoubles;
01364 //      G_PowerDuelCount(&loners, &doubles, qfalse);
01365 
01366         for ( i = 0 ; i < level.maxclients ; i++ ) {
01367                 client = &level.clients[i];
01368                 if ( client->pers.connected != CON_CONNECTED ) {
01369                         continue;
01370                 }
01371                 if ( client->sess.sessionTeam != TEAM_SPECTATOR ) {
01372                         continue;
01373                 }
01374                 if (client->sess.duelTeam == DUELTEAM_FREE)
01375                 {
01376                         continue;
01377                 }
01378                 if (client->sess.duelTeam == DUELTEAM_LONE && loners >= 1)
01379                 {
01380                         continue;
01381                 }
01382                 if (client->sess.duelTeam == DUELTEAM_DOUBLE && doubles >= 2)
01383                 {
01384                         continue;
01385                 }
01386 
01387                 // never select the dedicated follow or scoreboard clients
01388                 if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD || 
01389                         client->sess.spectatorClient < 0  ) {
01390                         continue;
01391                 }
01392 
01393                 if ( !nextInLine || client->sess.spectatorTime < nextInLine->sess.spectatorTime ) {
01394                         nextInLine = client;
01395                 }
01396         }
01397 
01398         if ( !nextInLine ) {
01399                 return;
01400         }
01401 
01402         level.warmupTime = -1;
01403 
01404         // set them to free-for-all team
01405         SetTeam( &g_entities[ nextInLine - level.clients ], "f" );
01406 
01407         //Call recursively until everyone is in
01408         AddPowerDuelPlayers();
01409 }

void AddTournamentPlayer void   ) 
 

Definition at line 1232 of file g_main.c.

References client, level_locals_t::clients, CON_CONNECTED, clientPersistant_t::connected, g_allowHighPingDuelist, g_entities, gclient_t, vmCvar_t::integer, level, level_locals_t::maxclients, NULL, level_locals_t::numPlayingClients, gclient_s::pers, playerState_s::ping, gclient_s::ps, gclient_s::sess, clientSession_t::sessionTeam, SetTeam(), SPECTATOR_SCOREBOARD, clientSession_t::spectatorClient, clientSession_t::spectatorState, clientSession_t::spectatorTime, TEAM_SPECTATOR, and level_locals_t::warmupTime.

Referenced by CheckIntermissionExit(), and CheckTournament().

01232                                  {
01233         int                     i;
01234         gclient_t       *client;
01235         gclient_t       *nextInLine;
01236 
01237         if ( level.numPlayingClients >= 2 ) {
01238                 return;
01239         }
01240 
01241         // never change during intermission
01242 //      if ( level.intermissiontime ) {
01243 //              return;
01244 //      }
01245 
01246         nextInLine = NULL;
01247 
01248         for ( i = 0 ; i < level.maxclients ; i++ ) {
01249                 client = &level.clients[i];
01250                 if ( client->pers.connected != CON_CONNECTED ) {
01251                         continue;
01252                 }
01253                 if (!g_allowHighPingDuelist.integer && client->ps.ping >= 999)
01254                 { //don't add people who are lagging out if cvar is not set to allow it.
01255                         continue;
01256                 }
01257                 if ( client->sess.sessionTeam != TEAM_SPECTATOR ) {
01258                         continue;
01259                 }
01260                 // never select the dedicated follow or scoreboard clients
01261                 if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD || 
01262                         client->sess.spectatorClient < 0  ) {
01263                         continue;
01264                 }
01265 
01266                 if ( !nextInLine || client->sess.spectatorTime < nextInLine->sess.spectatorTime ) {
01267                         nextInLine = client;
01268                 }
01269         }
01270 
01271         if ( !nextInLine ) {
01272                 return;
01273         }
01274 
01275         level.warmupTime = -1;
01276 
01277         // set them to free-for-all team
01278         SetTeam( &g_entities[ nextInLine - level.clients ], "f" );
01279 }

void AdjustTournamentScores void   ) 
 

Definition at line 1525 of file g_main.c.

References level_locals_t::clients, ClientUserinfoChanged(), CON_CONNECTED, clientPersistant_t::connected, CS_CLIENT_DUELWINNER, level, clientSession_t::losses, gclient_s::pers, PERS_SCORE, gclient_s::sess, level_locals_t::sortedClients, STAT_ARMOR, STAT_HEALTH, trap_SetConfigstring(), va(), and clientSession_t::wins.

Referenced by BeginIntermission().

01525                                     {
01526         int                     clientNum;
01527 
01528         if (level.clients[level.sortedClients[0]].ps.persistant[PERS_SCORE] ==
01529                 level.clients[level.sortedClients[1]].ps.persistant[PERS_SCORE] &&
01530                 level.clients[level.sortedClients[0]].pers.connected == CON_CONNECTED &&
01531                 level.clients[level.sortedClients[1]].pers.connected == CON_CONNECTED)
01532         {
01533                 int clFirst = level.clients[ level.sortedClients[0] ].ps.stats[STAT_HEALTH] + level.clients[ level.sortedClients[0] ].ps.stats[STAT_ARMOR];
01534                 int clSec = level.clients[ level.sortedClients[1] ].ps.stats[STAT_HEALTH] + level.clients[ level.sortedClients[1] ].ps.stats[STAT_ARMOR];
01535                 int clFailure = 0;
01536                 int clSuccess = 0;
01537 
01538                 if (clFirst > clSec)
01539                 {
01540                         clFailure = 1;
01541                         clSuccess = 0;
01542                 }
01543                 else if (clSec > clFirst)
01544                 {
01545                         clFailure = 0;
01546                         clSuccess = 1;
01547                 }
01548                 else
01549                 {
01550                         clFailure = 2;
01551                         clSuccess = 2;
01552                 }
01553 
01554                 if (clFailure != 2)
01555                 {
01556                         clientNum = level.sortedClients[clSuccess];
01557 
01558                         level.clients[ clientNum ].sess.wins++;
01559                         ClientUserinfoChanged( clientNum );
01560                         trap_SetConfigstring ( CS_CLIENT_DUELWINNER, va("%i", clientNum ) );
01561 
01562                         clientNum = level.sortedClients[clFailure];
01563 
01564                         level.clients[ clientNum ].sess.losses++;
01565                         ClientUserinfoChanged( clientNum );
01566                 }
01567                 else
01568                 {
01569                         clSuccess = 0;
01570                         clFailure = 1;
01571 
01572                         clientNum = level.sortedClients[clSuccess];
01573 
01574                         level.clients[ clientNum ].sess.wins++;
01575                         ClientUserinfoChanged( clientNum );
01576                         trap_SetConfigstring ( CS_CLIENT_DUELWINNER, va("%i", clientNum ) );
01577 
01578                         clientNum = level.sortedClients[clFailure];
01579 
01580                         level.clients[ clientNum ].sess.losses++;
01581                         ClientUserinfoChanged( clientNum );
01582                 }
01583         }
01584         else
01585         {
01586                 clientNum = level.sortedClients[0];
01587                 if ( level.clients[ clientNum ].pers.connected == CON_CONNECTED ) {
01588                         level.clients[ clientNum ].sess.wins++;
01589                         ClientUserinfoChanged( clientNum );
01590 
01591                         trap_SetConfigstring ( CS_CLIENT_DUELWINNER, va("%i", clientNum ) );
01592                 }
01593 
01594                 clientNum = level.sortedClients[1];
01595                 if ( level.clients[ clientNum ].pers.connected == CON_CONNECTED ) {
01596                         level.clients[ clientNum ].sess.losses++;
01597                         ClientUserinfoChanged( clientNum );
01598                 }
01599         }
01600 }

void AI_UpdateGroups void   ) 
 

Definition at line 964 of file NPC_AI_Utils.c.

References AI_RefreshGroup(), d_noGroupAI, level_locals_t::groups, vmCvar_t::integer, level, MAX_FRAME_GROUPS, memset(), AIGroupInfo_s::numGroup, and qfalse.

Referenced by G_RunFrame().

00965 {
00966         int i;
00967 
00968         if ( d_noGroupAI.integer )
00969         {
00970                 return;
00971         }
00972         //Clear all Groups
00973         for ( i = 0; i < MAX_FRAME_GROUPS; i++ ) 
00974         {
00975                 if ( !level.groups[i].numGroup || AI_RefreshGroup( &level.groups[i] ) == qfalse )//level.groups[i].enemy == NULL || 
00976                 {
00977                         memset( &level.groups[i], 0, sizeof( level.groups[i] ) );
00978                 }
00979         }
00980 }

void BeginIntermission void   ) 
 

Definition at line 2019 of file g_main.c.

References AdjustTournamentScores(), client, CS_CLIENT_DUELWINNER, DuelLimitHit(), FindIntermissionPoint(), g_entities, g_gametype, gDuelExit, gentity_t, GT_DUEL, GT_POWERDUEL, vmCvar_t::integer, level_locals_t::intermissiontime, level, level_locals_t::maxclients, MoveClientToIntermission(), qfalse, qtrue, respawn(), SendScoreboardMessageToAllClients(), gclient_s::sess, clientSession_t::sessionTeam, TEAM_SPECTATOR, level_locals_t::time, and trap_SetConfigstring().

Referenced by CheckExitRules(), and Cmd_LevelShot_f().

02019                                {
02020         int                     i;
02021         gentity_t       *client;
02022 
02023         if ( level.intermissiontime ) {
02024                 return;         // already active
02025         }
02026 
02027         // if in tournement mode, change the wins / losses
02028         if ( g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL ) {
02029                 trap_SetConfigstring ( CS_CLIENT_DUELWINNER, "-1" );
02030 
02031                 if (g_gametype.integer != GT_POWERDUEL)
02032                 {
02033                         AdjustTournamentScores();
02034                 }
02035                 if (DuelLimitHit())
02036                 {
02037                         gDuelExit = qtrue;
02038                 }
02039                 else
02040                 {
02041                         gDuelExit = qfalse;
02042                 }
02043         }
02044 
02045         level.intermissiontime = level.time;
02046         FindIntermissionPoint();
02047 
02048         /*
02049         if (g_singlePlayer.integer) {
02050                 trap_Cvar_Set("ui_singlePlayerActive", "0");
02051                 UpdateTournamentInfo();
02052         }
02053         */
02054         //what the? Well, I don't want this to happen.
02055 
02056         // move all clients to the intermission point
02057         for (i=0 ; i< level.maxclients ; i++) {
02058                 client = g_entities + i;
02059                 if (!client->inuse)
02060                         continue;
02061                 // respawn if dead
02062                 if (client->health <= 0) {
02063                         if (g_gametype.integer != GT_POWERDUEL ||
02064                                 !client->client ||
02065                                 client->client->sess.sessionTeam != TEAM_SPECTATOR)
02066                         { //don't respawn spectators in powerduel or it will mess the line order all up
02067                                 respawn(client);
02068                         }
02069                 }
02070                 MoveClientToIntermission( client );
02071         }
02072 
02073         // send the current scoring to all clients
02074         SendScoreboardMessageToAllClients();
02075 
02076 }

void BG_ClearVehicleParseParms void   ) 
 

Definition at line 79 of file bg_vehicleLoad.c.

References VehicleParms, and VehWeaponParms.

Referenced by G_InitGame().

00080 {
00081         //You can't strcat to these forever without clearing them!
00082         VehWeaponParms[0] = 0;
00083         VehicleParms[0] = 0;
00084 }

int BG_GetTime void   ) 
 

Definition at line 3543 of file g_main.c.

References level, and level_locals_t::time.

03544 {
03545         return level.time;
03546 }

void BG_VehicleLoadParms void   ) 
 

void CalculateRanks void   ) 
 

Definition at line 1735 of file g_main.c.

References CheckExitRules(), level_locals_t::clients, CON_CONNECTED, CON_DISCONNECTED, clientPersistant_t::connected, CS_CLIENT_DUELWINNER, CS_SCORES1, CS_SCORES2, level_locals_t::follow1, level_locals_t::follow2, g_entities, g_gametype, gclient_t, gQueueScoreMessage, gQueueScoreMessageTime, GT_DUEL, GT_POWERDUEL, GT_SINGLE_PLAYER, GT_TEAM, gclient_s::iAmALoser, vmCvar_t::integer, level_locals_t::intermissiontime, level, level_locals_t::maxclients, level_locals_t::numConnectedClients, level_locals_t::numNonSpectatorClients, level_locals_t::numPlayingClients, level_locals_t::numteamVotingClients, level_locals_t::numVotingClients, gclient_s::pers, PERS_RANK, PERS_SCORE, playerState_s::persistant, gclient_s::ps, qsort(), qtrue, gentity_s::r, RANK_TIED_FLAG, SCORE_NOT_PRESENT, gclient_s::sess, clientSession_t::sessionTeam, level_locals_t::sortedClients, SortRanks(), SVF_BOT, entityShared_t::svFlags, TEAM_BLUE, TEAM_NUM_TEAMS, TEAM_RED, TEAM_SPECTATOR, level_locals_t::teamScores, level_locals_t::time, trap_SetConfigstring(), va(), and level_locals_t::warmupTime.

Referenced by AddScore(), ClientBegin(), ClientConnect(), ClientDisconnect(), RemovePowerDuelLosers(), Team_TouchOurFlag(), and UpdateTournamentInfo().

01735                             {
01736         int             i;
01737         int             rank;
01738         int             score;
01739         int             newScore;
01740         int             preNumSpec = 0;
01741         //int           nonSpecIndex = -1;
01742         gclient_t       *cl;
01743 
01744         preNumSpec = level.numNonSpectatorClients;
01745 
01746         level.follow1 = -1;
01747         level.follow2 = -1;
01748         level.numConnectedClients = 0;
01749         level.numNonSpectatorClients = 0;
01750         level.numPlayingClients = 0;
01751         level.numVotingClients = 0;             // don't count bots
01752         for ( i = 0; i < TEAM_NUM_TEAMS; i++ ) {
01753                 level.numteamVotingClients[i] = 0;
01754         }
01755         for ( i = 0 ; i < level.maxclients ; i++ ) {
01756                 if ( level.clients[i].pers.connected != CON_DISCONNECTED ) {
01757                         level.sortedClients[level.numConnectedClients] = i;
01758                         level.numConnectedClients++;
01759 
01760                         if ( level.clients[i].sess.sessionTeam != TEAM_SPECTATOR || g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL )
01761                         {
01762                                 if (level.clients[i].sess.sessionTeam != TEAM_SPECTATOR)
01763                                 {
01764                                         level.numNonSpectatorClients++;
01765                                         //nonSpecIndex = i;
01766                                 }
01767                         
01768                                 // decide if this should be auto-followed
01769                                 if ( level.clients[i].pers.connected == CON_CONNECTED )
01770                                 {
01771                                         if (level.clients[i].sess.sessionTeam != TEAM_SPECTATOR || level.clients[i].iAmALoser)
01772                                         {
01773                                                 level.numPlayingClients++;
01774                                         }
01775                                         if ( !(g_entities[i].r.svFlags & SVF_BOT) )
01776                                         {
01777                                                 level.numVotingClients++;
01778                                                 if ( level.clients[i].sess.sessionTeam == TEAM_RED )
01779                                                         level.numteamVotingClients[0]++;
01780                                                 else if ( level.clients[i].sess.sessionTeam == TEAM_BLUE )
01781                                                         level.numteamVotingClients[1]++;
01782                                         }
01783                                         if ( level.follow1 == -1 ) {
01784                                                 level.follow1 = i;
01785                                         } else if ( level.follow2 == -1 ) {
01786                                                 level.follow2 = i;
01787                                         }
01788                                 }
01789                         }
01790                 }
01791         }
01792 
01793         //if (!g_warmup.integer)
01794         if (1)
01795         {
01796                 level.warmupTime = 0;
01797         }
01798 
01799         /*
01800         if (level.numNonSpectatorClients == 2 && preNumSpec < 2 && nonSpecIndex != -1 && g_gametype.integer == GT_DUEL && !level.warmupTime)
01801         {
01802                 gentity_t *currentWinner = G_GetDuelWinner(&level.clients[nonSpecIndex]);
01803 
01804                 if (currentWinner && currentWinner->client)
01805                 {
01806                         trap_SendServerCommand( -1, va("cp \"%s" S_COLOR_WHITE " %s %s\n\"",
01807                         currentWinner->client->pers.netname, G_GetStringEdString("MP_SVGAME", "VERSUS"), level.clients[nonSpecIndex].pers.netname));
01808                 }
01809         }
01810         */
01811         //NOTE: for now not doing this either. May use later if appropriate.
01812 
01813         qsort( level.sortedClients, level.numConnectedClients, 
01814                 sizeof(level.sortedClients[0]), SortRanks );
01815 
01816         // set the rank value for all clients that are connected and not spectators
01817         if ( g_gametype.integer >= GT_TEAM ) {
01818                 // in team games, rank is just the order of the teams, 0=red, 1=blue, 2=tied
01819                 for ( i = 0;  i < level.numConnectedClients; i++ ) {
01820                         cl = &level.clients[ level.sortedClients[i] ];
01821                         if ( level.teamScores[TEAM_RED] == level.teamScores[TEAM_BLUE] ) {
01822                                 cl->ps.persistant[PERS_RANK] = 2;
01823                         } else if ( level.teamScores[TEAM_RED] > level.teamScores[TEAM_BLUE] ) {
01824                                 cl->ps.persistant[PERS_RANK] = 0;
01825                         } else {
01826                                 cl->ps.persistant[PERS_RANK] = 1;
01827                         }
01828                 }
01829         } else {        
01830                 rank = -1;
01831                 score = 0;
01832                 for ( i = 0;  i < level.numPlayingClients; i++ ) {
01833                         cl = &level.clients[ level.sortedClients[i] ];
01834                         newScore = cl->ps.persistant[PERS_SCORE];
01835                         if ( i == 0 || newScore != score ) {
01836                                 rank = i;
01837                                 // assume we aren't tied until the next client is checked
01838                                 level.clients[ level.sortedClients[i] ].ps.persistant[PERS_RANK] = rank;
01839                         } else {
01840                                 // we are tied with the previous client
01841                                 level.clients[ level.sortedClients[i-1] ].ps.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
01842                                 level.clients[ level.sortedClients[i] ].ps.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
01843                         }
01844                         score = newScore;
01845                         if ( g_gametype.integer == GT_SINGLE_PLAYER && level.numPlayingClients == 1 ) {
01846                                 level.clients[ level.sortedClients[i] ].ps.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
01847                         }
01848                 }
01849         }
01850 
01851         // set the CS_SCORES1/2 configstrings, which will be visible to everyone
01852         if ( g_gametype.integer >= GT_TEAM ) {
01853                 trap_SetConfigstring( CS_SCORES1, va("%i", level.teamScores[TEAM_RED] ) );
01854                 trap_SetConfigstring( CS_SCORES2, va("%i", level.teamScores[TEAM_BLUE] ) );
01855         } else {
01856                 if ( level.numConnectedClients == 0 ) {
01857                         trap_SetConfigstring( CS_SCORES1, va("%i", SCORE_NOT_PRESENT) );
01858                         trap_SetConfigstring( CS_SCORES2, va("%i", SCORE_NOT_PRESENT) );
01859                 } else if ( level.numConnectedClients == 1 ) {
01860                         trap_SetConfigstring( CS_SCORES1, va("%i", level.clients[ level.sortedClients[0] ].ps.persistant[PERS_SCORE] ) );
01861                         trap_SetConfigstring( CS_SCORES2, va("%i", SCORE_NOT_PRESENT) );
01862                 } else {
01863                         trap_SetConfigstring( CS_SCORES1, va("%i", level.clients[ level.sortedClients[0] ].ps.persistant[PERS_SCORE] ) );
01864                         trap_SetConfigstring( CS_SCORES2, va("%i", level.clients[ level.sortedClients</