From 997376603b684e13d6b1c21708db88fc55e9e0eb Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Sat, 7 Sep 2013 09:56:40 +0200 Subject: Remove .orig files --- src/game/g_main.c.orig | 2548 ------------------------------------------------ 1 file changed, 2548 deletions(-) delete mode 100644 src/game/g_main.c.orig (limited to 'src/game/g_main.c.orig') diff --git a/src/game/g_main.c.orig b/src/game/g_main.c.orig deleted file mode 100644 index 33784c9..0000000 --- a/src/game/g_main.c.orig +++ /dev/null @@ -1,2548 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. -Copyright (C) 2000-2009 Darklegion Development - -This file is part of Tremulous. - -Tremulous is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Tremulous is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Tremulous; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "g_local.h" - -level_locals_t level; - -typedef struct -{ - vmCvar_t *vmCvar; - char *cvarName; - char *defaultString; - int cvarFlags; - int modificationCount; // for tracking changes - qboolean trackChange; // track this variable, and announce if changed - /* certain cvars can be set in worldspawn, but we don't want those values to - persist, so keep track of non-worldspawn changes and restore that on map - end. unfortunately, if the server crashes, the value set in worldspawn may - persist */ - char *explicit; -} cvarTable_t; - -gentity_t g_entities[ MAX_GENTITIES ]; -gclient_t g_clients[ MAX_CLIENTS ]; - -vmCvar_t g_timelimit; -vmCvar_t g_suddenDeathTime; -vmCvar_t g_friendlyFire; -vmCvar_t g_friendlyBuildableFire; -vmCvar_t g_dretchPunt; -vmCvar_t g_password; -vmCvar_t g_needpass; -vmCvar_t g_maxclients; -vmCvar_t g_maxGameClients; -vmCvar_t g_dedicated; -vmCvar_t g_speed; -vmCvar_t g_gravity; -vmCvar_t g_cheats; -vmCvar_t g_knockback; -vmCvar_t g_inactivity; -vmCvar_t g_debugMove; -vmCvar_t g_debugDamage; -vmCvar_t g_motd; -vmCvar_t g_synchronousClients; -vmCvar_t g_warmup; -vmCvar_t g_doWarmup; -vmCvar_t g_restarted; -vmCvar_t g_lockTeamsAtStart; -vmCvar_t g_logFile; -vmCvar_t g_logFileSync; -vmCvar_t g_allowVote; -vmCvar_t g_voteLimit; -vmCvar_t g_suddenDeathVotePercent; -vmCvar_t g_suddenDeathVoteDelay; -vmCvar_t g_teamForceBalance; -vmCvar_t g_smoothClients; -vmCvar_t pmove_fixed; -vmCvar_t pmove_msec; -vmCvar_t g_minNameChangePeriod; -vmCvar_t g_maxNameChanges; - -vmCvar_t g_alienBuildPoints; -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; -vmCvar_t g_humanStage2Threshold; -vmCvar_t g_humanStage3Threshold; -vmCvar_t g_alienStage; -vmCvar_t g_alienCredits; -vmCvar_t g_alienMaxStage; -vmCvar_t g_alienStage2Threshold; -vmCvar_t g_alienStage3Threshold; -vmCvar_t g_teamImbalanceWarnings; -vmCvar_t g_freeFundPeriod; - -vmCvar_t g_unlagged; - -vmCvar_t g_disabledEquipment; -vmCvar_t g_disabledClasses; -vmCvar_t g_disabledBuildables; - -vmCvar_t g_markDeconstruct; - -vmCvar_t g_debugMapRotation; -vmCvar_t g_currentMapRotation; -vmCvar_t g_mapRotationNodes; -vmCvar_t g_mapRotationStack; -vmCvar_t g_nextMap; -vmCvar_t g_initialMapRotation; - -vmCvar_t g_debugVoices; -vmCvar_t g_voiceChats; - -vmCvar_t g_shove; - -vmCvar_t g_mapConfigs; -vmCvar_t g_sayAreaRange; - -vmCvar_t g_floodMaxDemerits; -vmCvar_t g_floodMinTime; - -vmCvar_t g_layouts; -vmCvar_t g_layoutAuto; - -vmCvar_t g_emoticonsAllowedInNames; - -vmCvar_t g_admin; -vmCvar_t g_adminTempBan; -vmCvar_t g_adminMaxBan; - -vmCvar_t g_privateMessages; -vmCvar_t g_specChat; -vmCvar_t g_publicAdminMessages; -vmCvar_t g_allowTeamOverlay; - -vmCvar_t g_censorship; - -vmCvar_t g_tag; - -vmCvar_t g_unlimited; -vmCvar_t g_instantBuild; -vmCvar_t g_cuboidSizeLimit; -vmCvar_t g_cuboidMode; - -vmCvar_t g_buildableDensityLimit; -vmCvar_t g_buildableDensityLimitRange; - -// copy cvars that can be set in worldspawn so they can be restored later -static char cv_gravity[ MAX_CVAR_VALUE_STRING ]; -static char cv_humanMaxStage[ MAX_CVAR_VALUE_STRING ]; -static char cv_alienMaxStage[ MAX_CVAR_VALUE_STRING ]; - -static cvarTable_t gameCvarTable[ ] = -{ - // don't override the cheat state set by the system - { &g_cheats, "sv_cheats", "", 0, 0, qfalse }, - - // noset vars - { NULL, "gamename", GAME_VERSION , CVAR_SERVERINFO | CVAR_ROM, 0, qfalse }, - { NULL, "gamedate", __DATE__ , CVAR_ROM, 0, qfalse }, - { &g_restarted, "g_restarted", "0", CVAR_ROM, 0, qfalse }, - { &g_lockTeamsAtStart, "g_lockTeamsAtStart", "0", CVAR_ROM, 0, qfalse }, - { NULL, "sv_mapname", "", CVAR_SERVERINFO | CVAR_ROM, 0, qfalse }, - { NULL, "P", "", CVAR_SERVERINFO | CVAR_ROM, 0, qfalse }, - - // latched vars - - { &g_maxclients, "sv_maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qfalse }, - - // change anytime vars - { &g_maxGameClients, "g_maxGameClients", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse }, - - { &g_timelimit, "timelimit", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue }, - { &g_suddenDeathTime, "g_suddenDeathTime", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue }, - - { &g_synchronousClients, "g_synchronousClients", "0", CVAR_SYSTEMINFO, 0, qfalse }, - - { &g_friendlyFire, "g_friendlyFire", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue }, - { &g_friendlyBuildableFire, "g_friendlyBuildableFire", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue }, - { &g_dretchPunt, "g_dretchPunt", "1", CVAR_ARCHIVE, 0, qtrue }, - - { &g_teamForceBalance, "g_teamForceBalance", "0", CVAR_ARCHIVE, 0, qtrue }, - - { &g_warmup, "g_warmup", "10", CVAR_ARCHIVE, 0, qtrue }, - { &g_doWarmup, "g_doWarmup", "0", CVAR_ARCHIVE, 0, qtrue }, - { &g_logFile, "g_logFile", "games.log", CVAR_ARCHIVE, 0, qfalse }, - { &g_logFileSync, "g_logFileSync", "0", CVAR_ARCHIVE, 0, qfalse }, - - { &g_password, "g_password", "", CVAR_USERINFO, 0, qfalse }, - - { &g_needpass, "g_needpass", "0", CVAR_SERVERINFO | CVAR_ROM, 0, qfalse }, - - { &g_dedicated, "dedicated", "0", 0, 0, qfalse }, - - { &g_speed, "g_speed", "320", 0, 0, qtrue }, - { &g_gravity, "g_gravity", "800", 0, 0, qtrue, cv_gravity }, - { &g_knockback, "g_knockback", "1000", 0, 0, qtrue }, - { &g_inactivity, "g_inactivity", "0", 0, 0, qtrue }, - { &g_debugMove, "g_debugMove", "0", 0, 0, qfalse }, - { &g_debugDamage, "g_debugDamage", "0", 0, 0, qfalse }, - { &g_motd, "g_motd", "", 0, 0, qfalse }, - - { &g_allowVote, "g_allowVote", "1", CVAR_ARCHIVE, 0, qfalse }, - { &g_voteLimit, "g_voteLimit", "5", CVAR_ARCHIVE, 0, qfalse }, - { &g_suddenDeathVotePercent, "g_suddenDeathVotePercent", "74", CVAR_ARCHIVE, 0, qfalse }, - { &g_suddenDeathVoteDelay, "g_suddenDeathVoteDelay", "180", CVAR_ARCHIVE, 0, qfalse }, - { &g_minNameChangePeriod, "g_minNameChangePeriod", "5", 0, 0, qfalse}, - { &g_maxNameChanges, "g_maxNameChanges", "5", 0, 0, qfalse}, - - { &g_smoothClients, "g_smoothClients", "1", 0, 0, qfalse}, - { &pmove_fixed, "pmove_fixed", "0", CVAR_SYSTEMINFO, 0, qfalse}, - { &pmove_msec, "pmove_msec", "8", CVAR_SYSTEMINFO, 0, qfalse}, - - { &g_alienBuildPoints, "g_alienBuildPoints", DEFAULT_ALIEN_BUILDPOINTS, 0, 0, qfalse }, - { &g_alienBuildQueueTime, "g_alienBuildQueueTime", DEFAULT_ALIEN_QUEUE_TIME, CVAR_ARCHIVE, 0, qfalse }, - { &g_humanBuildPoints, "g_humanBuildPoints", DEFAULT_HUMAN_BUILDPOINTS, 0, 0, qfalse }, - { &g_humanBuildQueueTime, "g_humanBuildQueueTime", DEFAULT_HUMAN_QUEUE_TIME, CVAR_ARCHIVE, 0, qfalse }, - { &g_humanRepeaterBuildPoints, "g_humanRepeaterBuildPoints", DEFAULT_HUMAN_REPEATER_BUILDPOINTS, CVAR_ARCHIVE, 0, qfalse }, - { &g_humanRepeaterMaxZones, "g_humanRepeaterMaxZones", DEFAULT_HUMAN_REPEATER_MAX_ZONES, CVAR_ARCHIVE, 0, qfalse }, - { &g_humanRepeaterBuildQueueTime, "g_humanRepeaterBuildQueueTime", DEFAULT_HUMAN_REPEATER_QUEUE_TIME, CVAR_ARCHIVE, 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, cv_humanMaxStage }, - { &g_humanStage2Threshold, "g_humanStage2Threshold", DEFAULT_HUMAN_STAGE2_THRESH, 0, 0, qfalse }, - { &g_humanStage3Threshold, "g_humanStage3Threshold", DEFAULT_HUMAN_STAGE3_THRESH, 0, 0, qfalse }, - { &g_alienStage, "g_alienStage", "0", 0, 0, qfalse }, - { &g_alienCredits, "g_alienCredits", "0", 0, 0, qfalse }, - { &g_alienMaxStage, "g_alienMaxStage", DEFAULT_ALIEN_MAX_STAGE, 0, 0, qfalse, cv_alienMaxStage }, - { &g_alienStage2Threshold, "g_alienStage2Threshold", DEFAULT_ALIEN_STAGE2_THRESH, 0, 0, qfalse }, - { &g_alienStage3Threshold, "g_alienStage3Threshold", DEFAULT_ALIEN_STAGE3_THRESH, 0, 0, qfalse }, - { &g_teamImbalanceWarnings, "g_teamImbalanceWarnings", "30", CVAR_ARCHIVE, 0, qfalse }, - { &g_freeFundPeriod, "g_freeFundPeriod", DEFAULT_FREEKILL_PERIOD, CVAR_ARCHIVE, 0, qtrue }, - - { &g_unlagged, "g_unlagged", "1", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue }, - - { &g_disabledEquipment, "g_disabledEquipment", "", CVAR_ROM | CVAR_SYSTEMINFO, 0, qfalse }, - { &g_disabledClasses, "g_disabledClasses", "", CVAR_ROM | CVAR_SYSTEMINFO, 0, qfalse }, - { &g_disabledBuildables, "g_disabledBuildables", "", CVAR_ROM | CVAR_SYSTEMINFO, 0, qfalse }, - - { &g_sayAreaRange, "g_sayAreaRange", "1000", CVAR_ARCHIVE, 0, qtrue }, - - { &g_floodMaxDemerits, "g_floodMaxDemerits", "5000", CVAR_ARCHIVE, 0, qfalse }, - { &g_floodMinTime, "g_floodMinTime", "2000", CVAR_ARCHIVE, 0, qfalse }, - - { &g_markDeconstruct, "g_markDeconstruct", "3", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue }, - - { &g_debugMapRotation, "g_debugMapRotation", "0", 0, 0, qfalse }, - { &g_currentMapRotation, "g_currentMapRotation", "-1", 0, 0, qfalse }, // -1 = NOT_ROTATING - { &g_mapRotationNodes, "g_mapRotationNodes", "", CVAR_ROM, 0, qfalse }, - { &g_mapRotationStack, "g_mapRotationStack", "", CVAR_ROM, 0, qfalse }, - { &g_nextMap, "g_nextMap", "", 0 , 0, qtrue }, - { &g_initialMapRotation, "g_initialMapRotation", "", CVAR_ARCHIVE, 0, qfalse }, - { &g_debugVoices, "g_debugVoices", "0", 0, 0, qfalse }, - { &g_voiceChats, "g_voiceChats", "1", CVAR_ARCHIVE, 0, qfalse }, - { &g_shove, "g_shove", "0.0", CVAR_ARCHIVE, 0, qfalse }, - { &g_mapConfigs, "g_mapConfigs", "", CVAR_ARCHIVE, 0, qfalse }, - { NULL, "g_mapConfigsLoaded", "0", CVAR_ROM, 0, qfalse }, - - { &g_layouts, "g_layouts", "", CVAR_LATCH, 0, qfalse }, - { &g_layoutAuto, "g_layoutAuto", "1", CVAR_ARCHIVE, 0, qfalse }, - - { &g_emoticonsAllowedInNames, "g_emoticonsAllowedInNames", "1", CVAR_LATCH|CVAR_ARCHIVE, 0, qfalse }, - - { &g_admin, "g_admin", "admin.dat", CVAR_ARCHIVE, 0, qfalse }, - { &g_adminTempBan, "g_adminTempBan", "2m", CVAR_ARCHIVE, 0, qfalse }, - { &g_adminMaxBan, "g_adminMaxBan", "2w", CVAR_ARCHIVE, 0, qfalse }, - - { &g_privateMessages, "g_privateMessages", "1", CVAR_ARCHIVE, 0, qfalse }, - { &g_specChat, "g_specChat", "1", CVAR_ARCHIVE, 0, qfalse }, - { &g_publicAdminMessages, "g_publicAdminMessages", "1", CVAR_ARCHIVE, 0, qfalse }, - { &g_allowTeamOverlay, "g_allowTeamOverlay", "1", CVAR_ARCHIVE, 0, qtrue }, - - { &g_censorship, "g_censorship", "", CVAR_ARCHIVE, 0, qfalse }, - - { &g_tag, "g_tag", "gpp", CVAR_INIT, 0, qfalse }, - - { &g_unlimited, "g_unlimited", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse }, - { &g_instantBuild, "g_instantBuild", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse }, - { &g_cuboidSizeLimit, "g_cuboidSizeLimit", "0", CVAR_ARCHIVE, 0, qfalse }, - { &g_cuboidMode, "g_cuboidMode", "0", CVAR_ARCHIVE, 0, qfalse }, - - { &g_buildableDensityLimit, "g_buildableDensityLimit", "0", CVAR_ARCHIVE, 0, qfalse }, - { &g_buildableDensityLimitRange, "g_buildableDensityLimitRange", "0", CVAR_ARCHIVE, 0, qfalse } -}; - -static int gameCvarTableSize = sizeof( gameCvarTable ) / sizeof( gameCvarTable[ 0 ] ); - - -void G_InitGame( int levelTime, int randomSeed, int restart ); -void G_RunFrame( int levelTime ); -void G_ShutdownGame( int restart ); -void CheckExitRules( void ); - -void G_CountSpawns( void ); -void G_CalculateBuildPoints( void ); - -/* -================ -vmMain - -This is the only way control passes into the module. -This must be the very first function compiled into the .q3vm file -================ -*/ -Q_EXPORT intptr_t 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 ) -{ - switch( command ) - { - case GAME_INIT: - G_InitGame( arg0, arg1, arg2 ); - return 0; - - case GAME_SHUTDOWN: - G_ShutdownGame( arg0 ); - return 0; - - case GAME_CLIENT_CONNECT: - return (intptr_t)ClientConnect( arg0, arg1 ); - - case GAME_CLIENT_THINK: - ClientThink( arg0 ); - return 0; - - case GAME_CLIENT_USERINFO_CHANGED: - ClientUserinfoChanged( arg0, qfalse ); - return 0; - - case GAME_CLIENT_DISCONNECT: - ClientDisconnect( arg0 ); - return 0; - - case GAME_CLIENT_BEGIN: - ClientBegin( arg0 ); - return 0; - - case GAME_CLIENT_COMMAND: - ClientCommand( arg0 ); - return 0; - - case GAME_RUN_FRAME: - G_RunFrame( arg0 ); - return 0; - - case GAME_CONSOLE_COMMAND: - return ConsoleCommand( ); - } - - return -1; -} - - -void QDECL G_Printf( const char *fmt, ... ) -{ - va_list argptr; - char text[ 1024 ]; - - va_start( argptr, fmt ); - Q_vsnprintf( text, sizeof( text ), fmt, argptr ); - va_end( argptr ); - - trap_Print( text ); -} - -void QDECL G_Error( const char *fmt, ... ) -{ - va_list argptr; - char text[ 1024 ]; - - va_start( argptr, fmt ); - Q_vsnprintf( text, sizeof( text ), fmt, argptr ); - va_end( argptr ); - - trap_Error( text ); -} - -/* -================ -G_FindTeams - -Chain together all entities with a matching team field. -Entity teams are used for item groups and multi-entity mover groups. - -All but the first will have the FL_TEAMSLAVE flag set and teammaster field set -All but the last will have the teamchain field set to the next one -================ -*/ -void G_FindTeams( void ) -{ - gentity_t *e, *e2; - int i, j; - int c, c2; - - c = 0; - c2 = 0; - - for( i = 1, e = g_entities+i; i < level.num_entities; i++, e++ ) - { - if( !e->inuse ) - continue; - - if( !e->team ) - continue; - - if( e->flags & FL_TEAMSLAVE ) - continue; - - e->teammaster = e; - c++; - c2++; - - for( j = i + 1, e2 = e + 1; j < level.num_entities; j++, e2++ ) - { - if( !e2->inuse ) - continue; - - if( !e2->team ) - continue; - - if( e2->flags & FL_TEAMSLAVE ) - continue; - - if( !strcmp( e->team, e2->team ) ) - { - c2++; - e2->teamchain = e->teamchain; - e->teamchain = e2; - e2->teammaster = e; - e2->flags |= FL_TEAMSLAVE; - - // make sure that targets only point at the master - if( e2->targetname ) - { - e->targetname = e2->targetname; - e2->targetname = NULL; - } - } - } - } - - G_Printf( "%i teams with %i entities\n", c, c2 ); -} - - -/* -================= -G_RegisterCvars -================= -*/ -void G_RegisterCvars( void ) -{ - int i; - cvarTable_t *cv; - - for( i = 0, cv = gameCvarTable; i < gameCvarTableSize; i++, cv++ ) - { - trap_Cvar_Register( cv->vmCvar, cv->cvarName, - cv->defaultString, cv->cvarFlags ); - - if( cv->vmCvar ) - cv->modificationCount = cv->vmCvar->modificationCount; - - if( cv->explicit ) - strcpy( cv->explicit, cv->vmCvar->string ); - } -} - -/* -================= -G_UpdateCvars -================= -*/ -void G_UpdateCvars( void ) -{ - int i; - cvarTable_t *cv; - - for( i = 0, cv = gameCvarTable; i < gameCvarTableSize; i++, cv++ ) - { - if( cv->vmCvar ) - { - trap_Cvar_Update( cv->vmCvar ); - - if( cv->modificationCount != cv->vmCvar->modificationCount ) - { - cv->modificationCount = cv->vmCvar->modificationCount; - - if( cv->trackChange ) - trap_SendServerCommand( -1, va( "print \"Server: %s changed to %s\n\"", - cv->cvarName, cv->vmCvar->string ) ); - - if( !level.spawning && cv->explicit ) - strcpy( cv->explicit, cv->vmCvar->string ); - } - } - } -} - -/* -================= -G_RestoreCvars -================= -*/ -void G_RestoreCvars( void ) -{ - int i; - cvarTable_t *cv; - - for( i = 0, cv = gameCvarTable; i < gameCvarTableSize; i++, cv++ ) - { - if( cv->vmCvar && cv->explicit ) - trap_Cvar_Set( cv->cvarName, cv->explicit ); - } -} - -/* -================= -G_MapConfigs -================= -*/ -void G_MapConfigs( const char *mapname ) -{ - - if( !g_mapConfigs.string[0] ) - return; - - if( trap_Cvar_VariableIntegerValue( "g_mapConfigsLoaded" ) ) - return; - - trap_SendConsoleCommand( EXEC_APPEND, - va( "exec \"%s/default.cfg\"\n", g_mapConfigs.string ) ); - - trap_SendConsoleCommand( EXEC_APPEND, - va( "exec \"%s/%s.cfg\"\n", g_mapConfigs.string, mapname ) ); - - trap_Cvar_Set( "g_mapConfigsLoaded", "1" ); -} - -/* -================ -G_CheckCuboidConfig - -even tokens are map names -odd tokens are cuboid modes -================ -*/ -void G_CheckCuboidConfig(char* mapname) -{ - char* token; - char config[MAX_CVAR_VALUE_STRING]; //should be enough for few maps - qboolean type=qfalse; - qboolean found=qfalse; - int mode; - - mode=trap_Cvar_VariableIntegerValue("g_cuboidDefaultMode"); - trap_Cvar_VariableStringBuffer("g_cuboidConfig",config,sizeof(config)); - - while(1) - { - COM_Parse(&token); - - if(!token) - break; - - if(!type) - if(!Q_stricmp(token,mapname)) - found=qtrue; - else - if(found) - { - mode=atoi(token); - break; - } - } - Com_Printf("cuboids are %s%s^7 on %s\n",(mode==0?"^2ENABLED":(mode==1?"^1DISABLED ON S1":"^1DISABLED")),(found?"":" BY DEFAULT"),mapname); -} - -/* -============ -G_InitGame - -============ -*/ -void G_InitGame( int levelTime, int randomSeed, int restart ) -{ - int i; - char map[ MAX_CVAR_VALUE_STRING ] = {""}; - - srand( randomSeed ); - - G_RegisterCvars( ); - - G_Printf( "------- Game Initialization -------\n" ); - G_Printf( "gamename: %s\n", GAME_VERSION ); - G_Printf( "gamedate: %s\n", __DATE__ ); - - BG_InitMemory( ); - - // set some level globals - memset( &level, 0, sizeof( level ) ); - level.time = levelTime; - level.startTime = levelTime; - level.alienStage2Time = level.alienStage3Time = - level.humanStage2Time = level.humanStage3Time = level.startTime; - - level.snd_fry = G_SoundIndex( "sound/misc/fry.wav" ); // FIXME standing in lava / slime - - if( g_logFile.string[ 0 ] ) - { - if( g_logFileSync.integer ) - trap_FS_FOpenFile( g_logFile.string, &level.logFile, FS_APPEND_SYNC ); - else - trap_FS_FOpenFile( g_logFile.string, &level.logFile, FS_APPEND ); - - if( !level.logFile ) - G_Printf( "WARNING: Couldn't open logfile: %s\n", g_logFile.string ); - else - { - char serverinfo[ MAX_INFO_STRING ]; - qtime_t qt; - int t; - - trap_GetServerinfo( serverinfo, sizeof( serverinfo ) ); - - G_LogPrintf( "------------------------------------------------------------\n" ); - G_LogPrintf( "InitGame: %s\n", serverinfo ); - - t = trap_RealTime( &qt ); - G_LogPrintf("RealTime: %04i/%02i/%02i %02i:%02i:%02i\n", - qt.tm_year+1900, qt.tm_mon+1, qt.tm_mday, - qt.tm_hour, qt.tm_min, qt.tm_sec ); - - } - } - else - G_Printf( "Not logging to disk\n" ); - - trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) ); - G_MapConfigs( map ); - - // we're done with g_mapConfigs, so reset this for the next map - trap_Cvar_Set( "g_mapConfigsLoaded", "0" ); - - G_RegisterCommands( ); - G_admin_readconfig( NULL ); - G_LoadCensors( ); - - // initialize all entities for this game - memset( g_entities, 0, MAX_GENTITIES * sizeof( g_entities[ 0 ] ) ); - level.gentities = g_entities; - - // initialize all clients for this game - level.maxclients = g_maxclients.integer; - memset( g_clients, 0, MAX_CLIENTS * sizeof( g_clients[ 0 ] ) ); - level.clients = g_clients; - - // set client fields on player ents - for( i = 0; i < level.maxclients; i++ ) - g_entities[ i ].client = level.clients + i; - - // always leave room for the max number of clients, - // even if they aren't all used, so numbers inside that - // range are NEVER anything but clients - level.num_entities = MAX_CLIENTS; - - // let the server system know where the entites are - trap_LocateGameData( level.gentities, level.num_entities, sizeof( gentity_t ), - &level.clients[ 0 ].ps, sizeof( level.clients[ 0 ] ) ); - - level.emoticonCount = BG_LoadEmoticons( level.emoticons, MAX_EMOTICONS ); - - trap_SetConfigstring( CS_INTERMISSION, "0" ); - - // test to see if a custom buildable layout will be loaded - G_LayoutSelect( ); - - // this has to be flipped after the first UpdateCvars - level.spawning = qtrue; - // parse the key/value pairs and spawn gentities - G_SpawnEntitiesFromString( ); - - // load up a custom building layout if there is one - G_LayoutLoad( ); - - // find out g_cuboidMode value - G_CheckCuboidConfig( map ); - - // the map might disable some things - BG_InitAllowedGameElements( ); - - // general initialization - G_FindTeams( ); - - BG_InitClassConfigs( ); - BG_InitBuildableConfigs( ); - G_InitDamageLocations( ); - G_InitMapRotations( ); - G_InitSpawnQueue( &level.alienSpawnQueue ); - G_InitSpawnQueue( &level.humanSpawnQueue ); - - if( g_debugMapRotation.integer ) - G_PrintRotations( ); - - level.voices = BG_VoiceInit( ); - BG_PrintVoices( level.voices, g_debugVoices.integer ); - - //reset stages - trap_Cvar_Set( "g_alienStage", va( "%d", S1 ) ); - trap_Cvar_Set( "g_humanStage", va( "%d", S1 ) ); - trap_Cvar_Set( "g_alienCredits", 0 ); - trap_Cvar_Set( "g_humanCredits", 0 ); - level.suddenDeathBeginTime = g_suddenDeathTime.integer * 60000; - - G_Printf( "-----------------------------------\n" ); - - // So the server counts the spawns without a client attached - G_CountSpawns( ); - - G_UpdateTeamConfigStrings( ); - - if( g_lockTeamsAtStart.integer ) - { - level.alienTeamLocked = qtrue; - level.humanTeamLocked = qtrue; - trap_Cvar_Set( "g_lockTeamsAtStart", "0" ); - } -} - -/* -================== -G_ClearVotes - -remove all currently active votes -================== -*/ -static void G_ClearVotes( void ) -{ - int i; - memset( level.voteTime, 0, sizeof( level.voteTime ) ); - for( i = 0; i < NUM_TEAMS; i++ ) - { - trap_SetConfigstring( CS_VOTE_TIME + i, "" ); - trap_SetConfigstring( CS_VOTE_STRING + i, "" ); - } -} - -/* -================= -G_ShutdownGame -================= -*/ -void G_ShutdownGame( int restart ) -{ - // in case of a map_restart - G_ClearVotes( ); - - G_RestoreCvars( ); - - G_Printf( "==== ShutdownGame ====\n" ); - - if( level.logFile ) - { - G_LogPrintf( "ShutdownGame:\n" ); - G_LogPrintf( "------------------------------------------------------------\n" ); - trap_FS_FCloseFile( level.logFile ); - level.logFile = 0; - } - - // write all the client session data so we can get it back - G_WriteSessionData( ); - - G_admin_cleanup( ); - G_namelog_cleanup( ); - G_UnregisterCommands( ); - - G_ShutdownMapRotations( ); - - level.restarted = qfalse; - level.surrenderTeam = TEAM_NONE; - trap_SetConfigstring( CS_WINNER, "" ); -} - - - -//=================================================================== - -void QDECL Com_Error( int level, const char *error, ... ) -{ - va_list argptr; - char text[ 1024 ]; - - va_start( argptr, error ); - Q_vsnprintf( text, sizeof( text ), error, argptr ); - va_end( argptr ); - - G_Error( "%s", text ); -} - -void QDECL Com_Printf( const char *msg, ... ) -{ - va_list argptr; - char text[ 1024 ]; - - va_start( argptr, msg ); - Q_vsnprintf( text, sizeof( text ), msg, argptr ); - va_end( argptr ); - - G_Printf( "%s", text ); -} - -/* -======================================================================== - -PLAYER COUNTING / SCORE SORTING - -======================================================================== -*/ - - -/* -============= -SortRanks - -============= -*/ -int QDECL SortRanks( const void *a, const void *b ) -{ - gclient_t *ca, *cb; - - ca = &level.clients[ *(int *)a ]; - cb = &level.clients[ *(int *)b ]; - - // then sort by score - if( ca->ps.persistant[ PERS_SCORE ] > cb->ps.persistant[ PERS_SCORE ] ) - return -1; - if( ca->ps.persistant[ PERS_SCORE ] < cb->ps.persistant[ PERS_SCORE ] ) - return 1; - else - return 0; -} - -/* -============ -G_InitSpawnQueue - -Initialise a spawn queue -============ -*/ -void G_InitSpawnQueue( spawnQueue_t *sq ) -{ - int i; - - sq->back = sq->front = 0; - sq->back = QUEUE_MINUS1( sq->back ); - - //0 is a valid clientNum, so use something else - for( i = 0; i < MAX_CLIENTS; i++ ) - sq->clients[ i ] = -1; -} - -/* -============ -G_GetSpawnQueueLength - -Return the length of a spawn queue -============ -*/ -int G_GetSpawnQueueLength( spawnQueue_t *sq ) -{ - int length = sq->back - sq->front + 1; - - while( length < 0 ) - length += MAX_CLIENTS; - - while( length >= MAX_CLIENTS ) - length -= MAX_CLIENTS; - - return length; -} - -/* -============ -G_PopSpawnQueue - -Remove from front element from a spawn queue -============ -*/ -int G_PopSpawnQueue( spawnQueue_t *sq ) -{ - int clientNum = sq->clients[ sq->front ]; - - if( G_GetSpawnQueueLength( sq ) > 0 ) - { - sq->clients[ sq->front ] = -1; - sq->front = QUEUE_PLUS1( sq->front ); - G_StopFollowing( g_entities + clientNum ); - g_entities[ clientNum ].client->ps.pm_flags &= ~PMF_QUEUED; - - return clientNum; - } - else - return -1; -} - -/* -============ -G_PeekSpawnQueue - -Look at front element from a spawn queue -============ -*/ -int G_PeekSpawnQueue( spawnQueue_t *sq ) -{ - return sq->clients[ sq->front ]; -} - -/* -============ -G_SearchSpawnQueue - -Look to see if clientNum is already in the spawnQueue -============ -*/ -qboolean G_SearchSpawnQueue( spawnQueue_t *sq, int clientNum ) -{ - int i; - - for( i = 0; i < MAX_CLIENTS; i++ ) - { - if( sq->clients[ i ] == clientNum ) - return qtrue; - } - - return qfalse; -} - -/* -============ -G_PushSpawnQueue - -Add an element to the back of the spawn queue -============ -*/ -qboolean G_PushSpawnQueue( spawnQueue_t *sq, int clientNum ) -{ - // don't add the same client more than once - if( G_SearchSpawnQueue( sq, clientNum ) ) - return qfalse; - - sq->back = QUEUE_PLUS1( sq->back ); - sq->clients[ sq->back ] = clientNum; - - g_entities[ clientNum ].client->ps.pm_flags |= PMF_QUEUED; - return qtrue; -} - -/* -============ -G_RemoveFromSpawnQueue - -remove a specific client from a spawn queue -============ -*/ -qboolean G_RemoveFromSpawnQueue( spawnQueue_t *sq, int clientNum ) -{ - int i = sq->front; - - if( G_GetSpawnQueueLength( sq ) ) - { - 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( i ); - } while( i != QUEUE_PLUS1( sq->back ) ); - - sq->back = QUEUE_MINUS1( sq->back ); - g_entities[ clientNum ].client->ps.pm_flags &= ~PMF_QUEUED; - - return qtrue; - } - - i = QUEUE_PLUS1( i ); - } 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; - - if( G_GetSpawnQueueLength( sq ) ) - { - do - { - if( sq->clients[ i ] == clientNum ) - { - if( i < sq->front ) - return i + MAX_CLIENTS - sq->front; - else - return i - sq->front; - } - - i = QUEUE_PLUS1( i ); - } while( i != QUEUE_PLUS1( sq->back ) ); - } - - return -1; -} - -/* -============ -G_PrintSpawnQueue - -Print the contents of a spawn queue -============ -*/ -void G_PrintSpawnQueue( spawnQueue_t *sq ) -{ - int i = sq->front; - int length = G_GetSpawnQueueLength( sq ); - - G_Printf( "l:%d f:%d b:%d :", length, sq->front, sq->back ); - - if( length > 0 ) - { - do - { - if( sq->clients[ i ] == -1 ) - G_Printf( "*:" ); - else - G_Printf( "%d:", sq->clients[ i ] ); - - i = QUEUE_PLUS1( i ); - } while( i != QUEUE_PLUS1( sq->back ) ); - } - - G_Printf( "\n" ); -} - -/* -============ -G_SpawnClients - -Spawn queued clients -============ -*/ -void G_SpawnClients( team_t team ) -{ - int clientNum; - gentity_t *ent, *spawn; - vec3_t spawn_origin, spawn_angles; - spawnQueue_t *sq = NULL; - int numSpawns = 0; - - if( team == TEAM_ALIENS ) - { - sq = &level.alienSpawnQueue; - numSpawns = level.numAlienSpawns; - } - else if( team == TEAM_HUMANS ) - { - sq = &level.humanSpawnQueue; - numSpawns = level.numHumanSpawns; - } - - if( G_GetSpawnQueueLength( sq ) > 0 && numSpawns > 0 ) - { - clientNum = G_PeekSpawnQueue( sq ); - ent = &g_entities[ clientNum ]; - - if( ( spawn = G_SelectTremulousSpawnPoint( team, - ent->client->pers.lastDeathLocation, - spawn_origin, spawn_angles ) ) ) - { - clientNum = G_PopSpawnQueue( sq ); - - if( clientNum < 0 ) - return; - - ent = &g_entities[ clientNum ]; - - ent->client->sess.spectatorState = SPECTATOR_NOT; - ClientUserinfoChanged( clientNum, qfalse ); - ClientSpawn( ent, spawn, spawn_origin, spawn_angles ); - } - } -} - -/* -============ -G_CountSpawns - -Counts the number of spawns for each team -============ -*/ -void G_CountSpawns( void ) -{ - int i; - gentity_t *ent; - - level.numAlienSpawns = 0; - level.numHumanSpawns = 0; - for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ ) - { - if( !ent->inuse || ent->s.eType != ET_BUILDABLE || ent->health <= 0 ) - continue; - - if( ent->s.modelindex == BA_A_SPAWN ) - level.numAlienSpawns++; - - if( ent->s.modelindex == BA_H_SPAWN ) - level.numHumanSpawns++; - } -} - - -/* -============ -G_TimeTilSuddenDeath -============ -*/ -#define SUDDENDEATHWARNING 60000 -int G_TimeTilSuddenDeath( void ) -{ - if( ( !g_suddenDeathTime.integer && level.suddenDeathBeginTime == 0 ) || - ( level.suddenDeathBeginTime < 0 ) ) - return SUDDENDEATHWARNING + 1; // Always some time away - - return ( ( level.suddenDeathBeginTime ) - ( level.time - level.startTime ) ); -} - - -#define PLAYER_COUNT_MOD 5.0f - -/* -============ -G_CalculateBuildPoints - -Recalculate the quantity of building points available to the teams -============ -*/ -void G_CalculateBuildPoints( void ) -{ - int i; - buildable_t buildable; - buildPointZone_t *zone; - - // BP queue updates - while( level.alienBuildPointQueue > 0 && - level.alienNextQueueTime < level.time ) - { - level.alienBuildPointQueue--; - level.alienNextQueueTime += G_NextQueueTime( level.alienBuildPointQueue, - g_alienBuildPoints.integer, - g_alienBuildQueueTime.integer ); - } - - while( level.humanBuildPointQueue > 0 && - level.humanNextQueueTime < level.time ) - { - level.humanBuildPointQueue--; - level.humanNextQueueTime += G_NextQueueTime( level.humanBuildPointQueue, - g_humanBuildPoints.integer, - g_humanBuildQueueTime.integer ); - } - - // Sudden Death checks - if( G_TimeTilSuddenDeath( ) <= 0 && level.suddenDeathWarning < TW_PASSED ) - { - G_LogPrintf( "Beginning Sudden Death\n" ); - trap_SendServerCommand( -1, "cp \"Sudden Death!\"" ); - trap_SendServerCommand( -1, "print \"Beginning Sudden Death.\n\"" ); - level.suddenDeathWarning = TW_PASSED; - G_ClearDeconMarks( ); - - // Clear blueprints, or else structs that cost 0 BP can still be built after SD - for( i = 0; i < level.maxclients; i++ ) - { - if( g_entities[ i ].client->ps.stats[ STAT_BUILDABLE ] != BA_NONE ) - g_entities[ i ].client->ps.stats[ STAT_BUILDABLE ] = BA_NONE; - } - } - else if( G_TimeTilSuddenDeath( ) <= SUDDENDEATHWARNING && - level.suddenDeathWarning < TW_IMMINENT ) - { - trap_SendServerCommand( -1, va( "cp \"Sudden Death in %d seconds!\"", - (int)( G_TimeTilSuddenDeath( ) / 1000 ) ) ); - trap_SendServerCommand( -1, va( "print \"Sudden Death will begin in %d seconds.\n\"", - (int)( G_TimeTilSuddenDeath( ) / 1000 ) ) ); - level.suddenDeathWarning = TW_IMMINENT; - } - - level.humanBuildPoints = g_humanBuildPoints.integer - level.humanBuildPointQueue; - level.alienBuildPoints = g_alienBuildPoints.integer - level.alienBuildPointQueue; - - // Reset buildPointZones - for( i = 0; i < g_humanRepeaterMaxZones.integer; i++ ) - { - buildPointZone_t *zone = &level.buildPointZones[ i ]; - - zone->active = qfalse; - zone->totalBuildPoints = g_humanRepeaterBuildPoints.integer; - } - - // Iterate through entities - for( i = MAX_CLIENTS; i < level.num_entities; i++ ) - { - gentity_t *ent = &g_entities[ i ]; - buildPointZone_t *zone; - buildable_t buildable; - int cost; - - if( ent->s.eType != ET_BUILDABLE || ent->s.eFlags & EF_DEAD ) - continue; - - // mark a zone as active - if( ent->usesBuildPointZone ) - { - assert( ent->buildPointZone >= 0 && ent->buildPointZone < g_humanRepeaterMaxZones.integer ); - - zone = &level.buildPointZones[ ent->buildPointZone ]; - zone->active = qtrue; - } - - // Subtract the BP from the appropriate pool - buildable = ent->s.modelindex; - cost = BG_Buildable( buildable, ent->cuboidSize )->buildPoints; - - if( ent->buildableTeam == TEAM_ALIENS ) - level.alienBuildPoints -= cost; - if( buildable == BA_H_REPEATER ) - level.humanBuildPoints -= cost; - else if( buildable != BA_H_REACTOR ) - { - gentity_t *power = G_PowerEntityForEntity( ent ); - - if( power ) - { - if( power->s.modelindex == BA_H_REACTOR ) - level.humanBuildPoints -= cost; - else if( power->s.modelindex == BA_H_REPEATER && power->usesBuildPointZone ) - level.buildPointZones[ power->buildPointZone ].totalBuildPoints -= cost; - } - } - } - - // Finally, update repeater zones and their queues - // note that this has to be done after the used BP is calculated - for( i = MAX_CLIENTS; i < level.num_entities; i++ ) - { - gentity_t *ent = &g_entities[ i ]; - - if( ent->s.eType != ET_BUILDABLE || ent->s.eFlags & EF_DEAD || - ent->buildableTeam != TEAM_HUMANS ) - continue; - - buildable = ent->s.modelindex; - - if( buildable != BA_H_REPEATER ) - continue; - - if( ent->usesBuildPointZone && level.buildPointZones[ ent->buildPointZone ].active ) - { - zone = &level.buildPointZones[ ent->buildPointZone ]; - - if( G_TimeTilSuddenDeath( ) > 0 ) - { - // BP queue updates - while( zone->queuedBuildPoints > 0 && - zone->nextQueueTime < level.time ) - { - zone->queuedBuildPoints--; - zone->nextQueueTime += G_NextQueueTime( zone->queuedBuildPoints, - zone->totalBuildPoints, - g_humanRepeaterBuildQueueTime.integer ); - } - } - else - { - zone->totalBuildPoints = zone->queuedBuildPoints = 0; - } - } - } - - if( level.humanBuildPoints < 0 ) - level.humanBuildPoints = 0; - - if( level.alienBuildPoints < 0 ) - level.alienBuildPoints = 0; -} - -/* -============ -G_CalculateStages -============ -*/ -void G_CalculateStages( void ) -{ - float alienPlayerCountMod = level.averageNumAlienClients / PLAYER_COUNT_MOD; - float humanPlayerCountMod = level.averageNumHumanClients / PLAYER_COUNT_MOD; - int alienNextStageThreshold, humanNextStageThreshold; - static int lastAlienStageModCount = 1; - static int lastHumanStageModCount = 1; - - if( alienPlayerCountMod < 0.1f ) - alienPlayerCountMod = 0.1f; - - if( humanPlayerCountMod < 0.1f ) - humanPlayerCountMod = 0.1f; - - if( g_alienCredits.integer >= - (int)( ceil( (float)g_alienStage2Threshold.integer * alienPlayerCountMod ) ) && - g_alienStage.integer == S1 && g_alienMaxStage.integer > S1 ) - { - trap_Cvar_Set( "g_alienStage", va( "%d", S2 ) ); - level.alienStage2Time = level.time; - lastAlienStageModCount = g_alienStage.modificationCount; - G_LogPrintf("Stage: A 2: Aliens reached Stage 2\n"); - } - - if( g_alienCredits.integer >= - (int)( ceil( (float)g_alienStage3Threshold.integer * alienPlayerCountMod ) ) && - g_alienStage.integer == S2 && g_alienMaxStage.integer > S2 ) - { - trap_Cvar_Set( "g_alienStage", va( "%d", S3 ) ); - level.alienStage3Time = level.time; - lastAlienStageModCount = g_alienStage.modificationCount; - G_LogPrintf("Stage: A 3: Aliens reached Stage 3\n"); - } - - if( g_humanCredits.integer >= - (int)( ceil( (float)g_humanStage2Threshold.integer * humanPlayerCountMod ) ) && - g_humanStage.integer == S1 && g_humanMaxStage.integer > S1 ) - { - trap_Cvar_Set( "g_humanStage", va( "%d", S2 ) ); - level.humanStage2Time = level.time; - lastHumanStageModCount = g_humanStage.modificationCount; - G_LogPrintf("Stage: H 2: Humans reached Stage 2\n"); - } - - if( g_humanCredits.integer >= - (int)( ceil( (float)g_humanStage3Threshold.integer * humanPlayerCountMod ) ) && - g_humanStage.integer == S2 && g_humanMaxStage.integer > S2 ) - { - trap_Cvar_Set( "g_humanStage", va( "%d", S3 ) ); - level.humanStage3Time = level.time; - lastHumanStageModCount = g_humanStage.modificationCount; - G_LogPrintf("Stage: H 3: Humans reached Stage 3\n"); - } - - if( g_alienStage.modificationCount > lastAlienStageModCount ) - { - G_Checktrigger_stages( TEAM_ALIENS, g_alienStage.integer ); - - if( g_alienStage.integer == S2 ) - level.alienStage2Time = level.time; - else if( g_alienStage.integer == S3 ) - level.alienStage3Time = level.time; - - lastAlienStageModCount = g_alienStage.modificationCount; - } - - if( g_humanStage.modificationCount > lastHumanStageModCount ) - { - G_Checktrigger_stages( TEAM_HUMANS, g_humanStage.integer ); - - if( g_humanStage.integer == S2 ) - level.humanStage2Time = level.time; - else if( g_humanStage.integer == S3 ) - level.humanStage3Time = level.time; - - lastHumanStageModCount = g_humanStage.modificationCount; - } - - if( g_alienStage.integer == S1 && g_alienMaxStage.integer > S1 ) - alienNextStageThreshold = (int)( ceil( (float)g_alienStage2Threshold.integer * alienPlayerCountMod ) ); - else if( g_alienStage.integer == S2 && g_alienMaxStage.integer > S2 ) - alienNextStageThreshold = (int)( ceil( (float)g_alienStage3Threshold.integer * alienPlayerCountMod ) ); - else - alienNextStageThreshold = -1; - - if( g_humanStage.integer == S1 && g_humanMaxStage.integer > S1 ) - humanNextStageThreshold = (int)( ceil( (float)g_humanStage2Threshold.integer * humanPlayerCountMod ) ); - else if( g_humanStage.integer == S2 && g_humanMaxStage.integer > S2 ) - humanNextStageThreshold = (int)( ceil( (float)g_humanStage3Threshold.integer * humanPlayerCountMod ) ); - else - humanNextStageThreshold = -1; - - // save a lot of bandwidth by rounding thresholds up to the nearest 100 - if( alienNextStageThreshold > 0 ) - alienNextStageThreshold = ceil( (float)alienNextStageThreshold / 100 ) * 100; - - if( humanNextStageThreshold > 0 ) - humanNextStageThreshold = ceil( (float)humanNextStageThreshold / 100 ) * 100; - - trap_SetConfigstring( CS_ALIEN_STAGES, va( "%d %d %d", - g_alienStage.integer, g_alienCredits.integer, - alienNextStageThreshold ) ); - - trap_SetConfigstring( CS_HUMAN_STAGES, va( "%d %d %d", - g_humanStage.integer, g_humanCredits.integer, - humanNextStageThreshold ) ); -} - -/* -============ -CalculateAvgPlayers - -Calculates the average number of players playing this game -============ -*/ -void G_CalculateAvgPlayers( void ) -{ - //there are no clients or only spectators connected, so - //reset the number of samples in order to avoid the situation - //where the average tends to 0 - if( !level.numAlienClients ) - { - level.numAlienSamples = 0; - trap_Cvar_Set( "g_alienCredits", "0" ); - } - - if( !level.numHumanClients ) - { - level.numHumanSamples = 0; - trap_Cvar_Set( "g_humanCredits", "0" ); - } - - //calculate average number of clients for stats - level.averageNumAlienClients = - ( ( level.averageNumAlienClients * level.numAlienSamples ) - + level.numAlienClients ) / - (float)( level.numAlienSamples + 1 ); - level.numAlienSamples++; - - level.averageNumHumanClients = - ( ( level.averageNumHumanClients * level.numHumanSamples ) - + level.numHumanClients ) / - (float)( level.numHumanSamples + 1 ); - level.numHumanSamples++; -} - -/* -============ -CalculateRanks - -Recalculates the score ranks of all players -This will be called on every client connect, begin, disconnect, death, -and team change. -============ -*/ -void CalculateRanks( void ) -{ - int i; - char P[ MAX_CLIENTS + 1 ] = {""}; - - level.numConnectedClients = 0; - level.numPlayingClients = 0; - memset( level.numVotingClients, 0, sizeof( level.numVotingClients ) ); - level.numAlienClients = 0; - level.numHumanClients = 0; - level.numLiveAlienClients = 0; - level.numLiveHumanClients = 0; - - for( i = 0; i < level.maxclients; i++ ) - { - P[ i ] = '-'; - if ( level.clients[ i ].pers.connected != CON_DISCONNECTED ) - { - level.sortedClients[ level.numConnectedClients ] = i; - level.numConnectedClients++; - P[ i ] = (char)'0' + level.clients[ i ].pers.teamSelection; - - level.numVotingClients[ TEAM_NONE ]++; - - if( level.clients[ i ].pers.connected != CON_CONNECTED ) - continue; - - if( level.clients[ i ].pers.teamSelection != TEAM_NONE ) - { - level.numPlayingClients++; - if( level.clients[ i ].pers.teamSelection == TEAM_ALIENS ) - { - level.numAlienClients++; - if( level.clients[ i ].sess.spectatorState == SPECTATOR_NOT ) - level.numLiveAlienClients++; - } - else if( level.clients[ i ].pers.teamSelection == TEAM_HUMANS ) - { - level.numHumanClients++; - if( level.clients[ i ].sess.spectatorState == SPECTATOR_NOT ) - level.numLiveHumanClients++; - } - } - } - } - level.numNonSpectatorClients = level.numLiveAlienClients + - level.numLiveHumanClients; - level.numVotingClients[ TEAM_ALIENS ] = level.numAlienClients; - level.numVotingClients[ TEAM_HUMANS ] = level.numHumanClients; - P[ i ] = '\0'; - trap_Cvar_Set( "P", P ); - - qsort( level.sortedClients, level.numConnectedClients, - sizeof( level.sortedClients[ 0 ] ), SortRanks ); - - // see if it is time to end the level - CheckExitRules( ); - - // if we are at the intermission, send the new info to everyone - if( level.intermissiontime ) - SendScoreboardMessageToAllClients( ); -} - - -/* -======================================================================== - -MAP CHANGING - -======================================================================== -*/ - -/* -======================== -SendScoreboardMessageToAllClients - -Do this at BeginIntermission time and whenever ranks are recalculated -due to enters/exits/forced team changes -======================== -*/ -void SendScoreboardMessageToAllClients( void ) -{ - int i; - - for( i = 0; i < level.maxclients; i++ ) - { - if( level.clients[ i ].pers.connected == CON_CONNECTED ) - ScoreboardMessage( g_entities + i ); - } -} - -/* -======================== -MoveClientToIntermission - -When the intermission starts, this will be called for all players. -If a new client connects, this will be called after the spawn function. -======================== -*/ -void MoveClientToIntermission( gentity_t *ent ) -{ - // take out of follow mode if needed - if( ent->client->sess.spectatorState == SPECTATOR_FOLLOW ) - G_StopFollowing( ent ); - - // move to the spot - VectorCopy( level.intermission_origin, ent->s.origin ); - VectorCopy( level.intermission_origin, ent->client->ps.origin ); - VectorCopy( level.intermission_angle, ent->client->ps.viewangles ); - ent->client->ps.pm_type = PM_INTERMISSION; - - // clean up powerup info - memset( ent->client->ps.misc, 0, sizeof( ent->client->ps.misc ) ); - - ent->client->ps.eFlags = 0; - ent->s.eFlags = 0; - ent->s.eType = ET_GENERAL; - ent->s.modelindex = 0; - ent->s.loopSound = 0; - ent->s.event = 0; - ent->r.contents = 0; -} - -/* -================== -FindIntermissionPoint - -This is also used for spectator spawns -================== -*/ -void FindIntermissionPoint( void ) -{ - gentity_t *ent, *target; - vec3_t dir; - - // find the intermission spot - ent = G_Find( NULL, FOFS( classname ), "info_player_intermission" ); - - if( !ent ) - { // the map creator forgot to put in an intermission point... - G_SelectSpawnPoint( vec3_origin, level.intermission_origin, level.intermission_angle ); - } - else - { - VectorCopy( ent->s.origin, level.intermission_origin ); - VectorCopy( ent->s.angles, level.intermission_angle ); - // if it has a target, look towards it - if( ent->target ) - { - target = G_PickTarget( ent->target ); - - if( target ) - { - VectorSubtract( target->s.origin, level.intermission_origin, dir ); - vectoangles( dir, level.intermission_angle ); - } - } - } - -} - -/* -================== -BeginIntermission -================== -*/ -void BeginIntermission( void ) -{ - int i; - gentity_t *client; - - if( level.intermissiontime ) - return; // already active - - level.intermissiontime = level.time; - - G_ClearVotes( ); - - G_UpdateTeamConfigStrings( ); - - FindIntermissionPoint( ); - - // move all clients to the intermission point - for( i = 0; i < level.maxclients; i++ ) - { - client = g_entities + i; - - if( !client->inuse ) - continue; - - // respawn if dead - if( client->health <= 0 ) - respawn(client); - - MoveClientToIntermission( client ); - } - - // send the current scoring to all clients - SendScoreboardMessageToAllClients( ); -} - - -/* -============= -ExitLevel - -When the intermission has been exited, the server is either moved -to a new map based on the map rotation or the current map restarted -============= -*/ -void ExitLevel( void ) -{ - int i; - gclient_t *cl; - - if ( G_MapExists( g_nextMap.string ) ) - trap_SendConsoleCommand( EXEC_APPEND, va("map \"%s\"\n", g_nextMap.string ) ); - else if( G_MapRotationActive( ) ) - G_AdvanceMapRotation( 0 ); - else - trap_SendConsoleCommand( EXEC_APPEND, "map_restart\n" ); - - trap_Cvar_Set( "g_nextMap", "" ); - - level.restarted = qtrue; - level.changemap = NULL; - level.intermissiontime = 0; - - // reset all the scores so we don't enter the intermission again - for( i = 0; i < g_maxclients.integer; i++ ) - { - cl = level.clients + i; - if( cl->pers.connected != CON_CONNECTED ) - continue; - - cl->ps.persistant[ PERS_SCORE ] = 0; - } - - // we need to do this here before chaning to CON_CONNECTING - G_WriteSessionData( ); - - // change all client states to connecting, so the early players into the - // next level will know the others aren't done reconnecting - for( i = 0; i < g_maxclients.integer; i++ ) - { - if( level.clients[ i ].pers.connected == CON_CONNECTED ) - level.clients[ i ].pers.connected = CON_CONNECTING; - } - -} - -/* -================= -G_AdminMessage - -Print to all active server admins, and to the logfile, and to the server console -================= -*/ -void G_AdminMessage( gentity_t *ent, const char *msg ) -{ - char string[ 1024 ]; - int i; - - Com_sprintf( string, sizeof( string ), "chat %d %d \"%s\"", - ent ? ent - g_entities : -1, - G_admin_permission( ent, ADMF_ADMINCHAT ) ? SAY_ADMINS : SAY_ADMINS_PUBLIC, - msg ); - - // Send to all appropriate clients - for( i = 0; i < level.maxclients; i++ ) - if( G_admin_permission( &g_entities[ i ], ADMF_ADMINCHAT ) ) - trap_SendServerCommand( i, string ); - - // Send to the logfile and server console - G_LogPrintf( "%s: %d \"%s" S_COLOR_WHITE "\": " S_COLOR_MAGENTA "%s\n", - G_admin_permission( ent, ADMF_ADMINCHAT ) ? "AdminMsg" : "AdminMsgPublic", - ent ? ent - g_entities : -1, ent ? ent->client->pers.netname : "console", - msg ); -} - - -/* -================= -G_LogPrintf - -Print to the logfile with a time stamp if it is open, and to the server console -================= -*/ -void QDECL G_LogPrintf( const char *fmt, ... ) -{ - va_list argptr; - char string[ 1024 ], decolored[ 1024 ]; - int min, tens, sec; - - sec = ( level.time - level.startTime ) / 1000; - - min = sec / 60; - sec -= min * 60; - tens = sec / 10; - sec -= tens * 10; - - Com_sprintf( string, sizeof( string ), "%3i:%i%i ", min, tens, sec ); - - va_start( argptr, fmt ); - Q_vsnprintf( string + 7, sizeof( string ) - 7, fmt, argptr ); - va_end( argptr ); - - if( g_dedicated.integer ) - { - G_UnEscapeString( string, decolored, sizeof( decolored ) ); - G_Printf( "%s", decolored + 7 ); - } - - if( !level.logFile ) - return; - - G_DecolorString( string, decolored, sizeof( decolored ) ); - trap_FS_Write( decolored, strlen( decolored ), level.logFile ); -} - -/* -================= -G_SendGameStat -================= -*/ -void G_SendGameStat( team_t team ) -{ - char map[ MAX_STRING_CHARS ]; - char teamChar; - char data[ BIG_INFO_STRING ]; - char entry[ MAX_STRING_CHARS ]; - int i, dataLength, entryLength; - gclient_t *cl; - - // games with cheats enabled are not very good for balance statistics - if( g_cheats.integer ) - return; - - trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) ); - - switch( team ) - { - case TEAM_ALIENS: teamChar = 'A'; break; - case TEAM_HUMANS: teamChar = 'H'; break; - case TEAM_NONE: teamChar = 'L'; break; - default: return; - } - - Com_sprintf( data, BIG_INFO_STRING, - "%s %s T:%c A:%f H:%f M:%s D:%d SD:%d AS:%d AS2T:%d AS3T:%d HS:%d HS2T:%d HS3T:%d CL:%d", - Q3_VERSION, - g_tag.string, - teamChar, - level.averageNumAlienClients, - level.averageNumHumanClients, - map, - level.time - level.startTime, - G_TimeTilSuddenDeath( ), - g_alienStage.integer, - level.alienStage2Time - level.startTime, - level.alienStage3Time - level.startTime, - g_humanStage.integer, - level.humanStage2Time - level.startTime, - level.humanStage3Time - level.startTime, - level.numConnectedClients ); - - dataLength = strlen( data ); - - for( i = 0; i < level.numConnectedClients; i++ ) - { - int ping; - - cl = &level.clients[ level.sortedClients[ i ] ]; - - if( cl->pers.connected == CON_CONNECTING ) - ping = -1; - else - ping = cl->ps.ping < 999 ? cl->ps.ping : 999; - - switch( cl->ps.stats[ STAT_TEAM ] ) - { - case TEAM_ALIENS: teamChar = 'A'; break; - case TEAM_HUMANS: teamChar = 'H'; break; - case TEAM_NONE: teamChar = 'S'; break; - default: return; - } - - Com_sprintf( entry, MAX_STRING_CHARS, - " \"%s\" %c %d %d %d", - cl->pers.netname, - teamChar, - cl->ps.persistant[ PERS_SCORE ], - ping, - ( level.time - cl->pers.enterTime ) / 60000 ); - - entryLength = strlen( entry ); - - if( dataLength + entryLength >= BIG_INFO_STRING ) - break; - - strcpy( data + dataLength, entry ); - dataLength += entryLength; - } - - trap_SendGameStat( data ); -} - -/* -================ -LogExit - -Append information about this game to the log file -================ -*/ -void LogExit( const char *string ) -{ - int i, numSorted; - gclient_t *cl; - gentity_t *ent; - - G_LogPrintf( "Exit: %s\n", string ); - - level.intermissionQueued = level.time; - - // this will keep the clients from playing any voice sounds - // that will get cut off when the queued intermission starts - trap_SetConfigstring( CS_INTERMISSION, "1" ); - - // don't send more than 32 scores (FIXME?) - numSorted = level.numConnectedClients; - if( numSorted > 32 ) - numSorted = 32; - - for( i = 0; i < numSorted; i++ ) - { - int ping; - - cl = &level.clients[ level.sortedClients[ i ] ]; - - if( cl->ps.stats[ STAT_TEAM ] == TEAM_NONE ) - continue; - - if( cl->pers.connected == CON_CONNECTING ) - continue; - - ping = cl->ps.ping < 999 ? cl->ps.ping : 999; - - G_LogPrintf( "score: %i ping: %i client: %i %s\n", - cl->ps.persistant[ PERS_SCORE ], ping, level.sortedClients[ i ], - cl->pers.netname ); - - } - - for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ ) - { - if( !ent->inuse ) - continue; - - if( !Q_stricmp( ent->classname, "trigger_win" ) ) - { - if( level.lastWin == ent->stageTeam ) - ent->use( ent, ent, ent ); - } - } - - G_SendGameStat( level.lastWin ); -} - - -/* -================= -CheckIntermissionExit - -The level will stay at the intermission for a minimum of 5 seconds -If all players wish to continue, the level will then exit. -If one or more players have not acknowledged the continue, the game will -wait 10 seconds before going on. -================= -*/ -void CheckIntermissionExit( void ) -{ - int ready, notReady; - int i; - gclient_t *cl; - clientList_t readyMasks; - - //if no clients are connected, just exit - if( level.numConnectedClients == 0 ) - { - ExitLevel( ); - return; - } - - // see which players are ready - ready = 0; - notReady = 0; - Com_Memset( &readyMasks, 0, sizeof( readyMasks ) ); - for( i = 0; i < g_maxclients.integer; i++ ) - { - cl = level.clients + i; - - if( cl->pers.connected != CON_CONNECTED ) - continue; - - if( cl->ps.stats[ STAT_TEAM ] == TEAM_NONE ) - continue; - - if( cl->readyToExit ) - { - ready++; - - Com_ClientListAdd( &readyMasks, i ); - } - else - notReady++; - } - - trap_SetConfigstring( CS_CLIENTS_READY, Com_ClientListString( &readyMasks ) ); - - // never exit in less than five seconds - if( level.time < level.intermissiontime + 5000 ) - return; - - // never let intermission go on for over 1 minute - if( level.time > level.intermissiontime + 60000 ) - { - ExitLevel( ); - return; - } - - // if nobody wants to go, clear timer - if( ready == 0 && notReady > 0 ) - { - level.readyToExit = qfalse; - return; - } - - // if everyone wants to go, go now - if( notReady == 0 ) - { - ExitLevel( ); - return; - } - - // the first person to ready starts the thirty second timeout - if( !level.readyToExit ) - { - level.readyToExit = qtrue; - level.exitTime = level.time; - } - - // if we have waited thirty seconds since at least one player - // wanted to exit, go ahead - if( level.time < level.exitTime + 30000 ) - return; - - ExitLevel( ); -} - -/* -============= -ScoreIsTied -============= -*/ -qboolean ScoreIsTied( void ) -{ - int a, b; - - if( level.numPlayingClients < 2 ) - return qfalse; - - a = level.clients[ level.sortedClients[ 0 ] ].ps.persistant[ PERS_SCORE ]; - b = level.clients[ level.sortedClients[ 1 ] ].ps.persistant[ PERS_SCORE ]; - - return a == b; -} - -/* -================= -CheckExitRules - -There will be a delay between the time the exit is qualified for -and the time everyone is moved to the intermission spot, so you -can see the last frag. -================= -*/ -void CheckExitRules( void ) -{ - // if at the intermission, wait for all non-bots to - // signal ready, then go to next level - if( level.intermissiontime ) - { - CheckIntermissionExit( ); - return; - } - - if( level.intermissionQueued ) - { - if( level.time - level.intermissionQueued >= INTERMISSION_DELAY_TIME ) - { - level.intermissionQueued = 0; - BeginIntermission( ); - } - - return; - } - - if( g_timelimit.integer ) - { - if( level.time - level.startTime >= g_timelimit.integer * 60000 ) - { - level.lastWin = TEAM_NONE; - trap_SendServerCommand( -1, "print \"Timelimit hit\n\"" ); - trap_SetConfigstring( CS_WINNER, "Stalemate" ); - LogExit( "Timelimit hit." ); - return; - } - else if( level.time - level.startTime >= ( g_timelimit.integer - 5 ) * 60000 && - level.timelimitWarning < TW_IMMINENT ) - { - trap_SendServerCommand( -1, "cp \"5 minutes remaining!\"" ); - level.timelimitWarning = TW_IMMINENT; - } - else if( level.time - level.startTime >= ( g_timelimit.integer - 1 ) * 60000 && - level.timelimitWarning < TW_PASSED ) - { - trap_SendServerCommand( -1, "cp \"1 minute remaining!\"" ); - level.timelimitWarning = TW_PASSED; - } - } - - if( level.uncondHumanWin || - ( !level.uncondAlienWin && - ( level.time > level.startTime + 1000 ) && - ( level.numAlienSpawns == 0 ) && - ( level.numLiveAlienClients == 0 ) ) ) - { - //humans win - level.lastWin = TEAM_HUMANS; - trap_SendServerCommand( -1, "print \"Humans win\n\""); - trap_SetConfigstring( CS_WINNER, "Humans Win" ); - LogExit( "Humans win." ); - } - else if( level.uncondAlienWin || - ( ( level.time > level.startTime + 1000 ) && - ( level.numHumanSpawns == 0 ) && - ( level.numLiveHumanClients == 0 ) ) ) - { - //aliens win - level.lastWin = TEAM_ALIENS; - trap_SendServerCommand( -1, "print \"Aliens win\n\""); - trap_SetConfigstring( CS_WINNER, "Aliens Win" ); - LogExit( "Aliens win." ); - } -} - -/* -================== -G_Vote -================== -*/ -void G_Vote( gentity_t *ent, team_t team, qboolean voting ) -{ - if( !level.voteTime[ team ] ) - return; - - if( voting && ent->client->pers.voted & ( 1 << team ) ) - return; - - if( !voting && !( ent->client->pers.voted & ( 1 << team ) ) ) - return; - - ent->client->pers.voted |= 1 << team; - - if( ent->client->pers.vote & ( 1 << team ) ) - { - if( voting ) - level.voteYes[ team ]++; - else - level.voteYes[ team ]--; - - trap_SetConfigstring( CS_VOTE_YES + team, - va( "%d", level.voteYes[ team ] ) ); - } - else - { - if( voting ) - level.voteNo[ team ]++; - else - level.voteNo[ team ]--; - - trap_SetConfigstring( CS_VOTE_NO + team, - va( "%d", level.voteNo[ team ] ) ); - } -} - - -/* -======================================================================== - -FUNCTIONS CALLED EVERY FRAME - -======================================================================== -*/ - - -void G_ExecuteVote( team_t team ) -{ - level.voteExecuteTime[ team ] = 0; - - trap_SendConsoleCommand( EXEC_APPEND, va( "%s\n", - level.voteString[ team ] ) ); - - if( !Q_stricmpn( level.voteString[ team ], "map", 3 ) ) - level.restarted = qtrue; -} - -/* -================== -G_CheckVote -================== -*/ -void G_CheckVote( team_t team ) -{ - float votePassThreshold = (float)level.voteThreshold[ team ] / 100.0f; - qboolean pass = qfalse; - char *msg; - int i; - - if( level.voteExecuteTime[ team ] && - level.voteExecuteTime[ team ] < level.time ) - { - G_ExecuteVote( team ); - } - - if( !level.voteTime[ team ] ) - return; - - if( ( level.time - level.voteTime[ team ] >= VOTE_TIME ) || - ( level.voteYes[ team ] + level.voteNo[ team ] == level.numVotingClients[ team ] ) ) - { - pass = ( level.voteYes[ team ] && - (float)level.voteYes[ team ] / ( (float)level.voteYes[ team ] + (float)level.voteNo[ team ] ) > votePassThreshold ); - } - else - { - if( (float)level.voteYes[ team ] > - (float)level.numVotingClients[ team ] * votePassThreshold ) - { - pass = qtrue; - } - else if( (float)level.voteNo[ team ] <= - (float)level.numVotingClients[ team ] * ( 1.0f - votePassThreshold ) ) - { - return; - } - } - - if( pass ) - level.voteExecuteTime[ team ] = level.time + level.voteDelay[ team ]; - - G_LogPrintf( "EndVote: %s %s %d %d %d\n", - team == TEAM_NONE ? "global" : BG_TeamName( team ), - pass ? "pass" : "fail", - level.voteYes[ team ], level.voteNo[ team ], level.numVotingClients[ team ] ); - - msg = va( "print \"%sote %sed (%d - %d)\n\"", - team == TEAM_NONE ? "V" : "Team v", pass ? "pass" : "fail", - level.voteYes[ team ], level.voteNo[ team ] ); - - if( team == TEAM_NONE ) - trap_SendServerCommand( -1, msg ); - else - G_TeamCommand( team, msg ); - - level.voteTime[ team ] = 0; - level.voteYes[ team ] = 0; - level.voteNo[ team ] = 0; - - for( i = 0; i < level.maxclients; i++ ) - level.clients[ i ].pers.voted &= ~( 1 << team ); - - trap_SetConfigstring( CS_VOTE_TIME + team, "" ); - trap_SetConfigstring( CS_VOTE_STRING + team, "" ); - trap_SetConfigstring( CS_VOTE_YES + team, "0" ); - trap_SetConfigstring( CS_VOTE_NO + team, "0" ); -} - - -/* -================== -CheckCvars -================== -*/ -void CheckCvars( void ) -{ - static int lastPasswordModCount = -1; - static int lastMarkDeconModCount = -1; - static int lastSDTimeModCount = -1; - static int lastNumZones = 0; - - if( g_password.modificationCount != lastPasswordModCount ) - { - lastPasswordModCount = g_password.modificationCount; - - if( *g_password.string && Q_stricmp( g_password.string, "none" ) ) - trap_Cvar_Set( "g_needpass", "1" ); - else - trap_Cvar_Set( "g_needpass", "0" ); - } - - // Unmark any structures for deconstruction when - // the server setting is changed - if( g_markDeconstruct.modificationCount != lastMarkDeconModCount ) - { - lastMarkDeconModCount = g_markDeconstruct.modificationCount; - G_ClearDeconMarks( ); - } - - // If we change g_suddenDeathTime during a map, we need to update - // when sd will begin - if( g_suddenDeathTime.modificationCount != lastSDTimeModCount ) - { - lastSDTimeModCount = g_suddenDeathTime.modificationCount; - level.suddenDeathBeginTime = g_suddenDeathTime.integer * 60000; - } - - // If the number of zones changes, we need a new array - if( g_humanRepeaterMaxZones.integer != lastNumZones ) - { - buildPointZone_t *newZones; - size_t newsize = g_humanRepeaterMaxZones.integer * sizeof( buildPointZone_t ); - size_t oldsize = lastNumZones * sizeof( buildPointZone_t ); - - newZones = BG_Alloc( newsize ); - if( level.buildPointZones ) - { - Com_Memcpy( newZones, level.buildPointZones, MIN( oldsize, newsize ) ); - BG_Free( level.buildPointZones ); - } - - level.buildPointZones = newZones; - lastNumZones = g_humanRepeaterMaxZones.integer; - } - - level.frameMsec = trap_Milliseconds( ); -} - -/* -============= -G_RunThink - -Runs thinking code for this frame if necessary -============= -*/ -void G_RunThink( gentity_t *ent ) -{ - float thinktime; - - thinktime = ent->nextthink; - if( thinktime <= 0 ) - return; - - if( thinktime > level.time ) - return; - - ent->nextthink = 0; - if( !ent->think ) - G_Error( "NULL ent->think" ); - - ent->think( ent ); -} - -/* -============= -G_EvaluateAcceleration - -Calculates the acceleration for an entity -============= -*/ -void G_EvaluateAcceleration( gentity_t *ent, int msec ) -{ - vec3_t deltaVelocity; - vec3_t deltaAccel; - - VectorSubtract( ent->s.pos.trDelta, ent->oldVelocity, deltaVelocity ); - VectorScale( deltaVelocity, 1.0f / (float)msec, ent->acceleration ); - - VectorSubtract( ent->acceleration, ent->oldAccel, deltaAccel ); - VectorScale( deltaAccel, 1.0f / (float)msec, ent->jerk ); - - VectorCopy( ent->s.pos.trDelta, ent->oldVelocity ); - VectorCopy( ent->acceleration, ent->oldAccel ); -} - -/* -================ -G_RunFrame - -Advances the non-player objects in the world -================ -*/ -void G_RunFrame( int levelTime ) -{ - int i; - gentity_t *ent; - int msec; - static int ptime3000 = 0; - - // if we are waiting for the level to restart, do nothing - if( level.restarted ) - return; - - if( level.pausedTime ) - { - msec = levelTime - level.time - level.pausedTime; - level.pausedTime = levelTime - level.time; - - ptime3000 += msec; - while( ptime3000 > 3000 ) - { - ptime3000 -= 3000; - trap_SendServerCommand( -1, "cp \"The game has been paused. Please wait.\"" ); - - if( level.pausedTime >= 110000 && level.pausedTime <= 119000 ) - trap_SendServerCommand( -1, va( "print \"Server: Game will auto-unpause in %d seconds\n\"", - (int) ( (float) ( 120000 - level.pausedTime ) / 1000.0f ) ) ); - } - - // Prevents clients from getting lagged-out messages - for( i = 0; i < level.maxclients; i++ ) - { - if( level.clients[ i ].pers.connected == CON_CONNECTED ) - level.clients[ i ].ps.commandTime = levelTime; - } - - if( level.pausedTime > 120000 ) - { - trap_SendServerCommand( -1, "print \"Server: The game has been unpaused automatically (2 minute max)\n\"" ); - trap_SendServerCommand( -1, "cp \"The game has been unpaused!\"" ); - level.pausedTime = 0; - } - - return; - } - - level.framenum++; - level.previousTime = level.time; - level.time = levelTime; - msec = level.time - level.previousTime; - - // get any cvar changes - G_UpdateCvars( ); - CheckCvars( ); - // now we are done spawning - level.spawning = qfalse; - - // - // go through all allocated objects - // - ent = &g_entities[ 0 ]; - - for( i = 0; i < level.num_entities; i++, ent++ ) - { - if( !ent->inuse ) - continue; - - // clear events that are too old - if( level.time - ent->eventTime > EVENT_VALID_MSEC ) - { - if( ent->s.event ) - { - ent->s.event = 0; // &= EV_EVENT_BITS; - if ( ent->client ) - { - ent->client->ps.externalEvent = 0; - //ent->client->ps.events[0] = 0; - //ent->client->ps.events[1] = 0; - } - } - - if( ent->freeAfterEvent ) - { - // tempEntities or dropped items completely go away after their event - G_FreeEntity( ent ); - continue; - } - else if( ent->unlinkAfterEvent ) - { - // items that will respawn will hide themselves after their pickup event - ent->unlinkAfterEvent = qfalse; - trap_UnlinkEntity( ent ); - } - } - - // temporary entities don't think - if( ent->freeAfterEvent ) - continue; - - // calculate the acceleration of this entity - if( ent->evaluateAcceleration ) - G_EvaluateAcceleration( ent, msec ); - - if( !ent->r.linked && ent->neverFree ) - continue; - - if( ent->s.eType == ET_MISSILE ) - { - G_RunMissile( ent ); - continue; - } - - if( ent->s.eType == ET_BUILDABLE ) - { - G_BuildableThink( ent, msec ); - continue; - } - - if( ent->s.eType == ET_CORPSE || ent->physicsObject ) - { - G_Physics( ent, msec ); - continue; - } - - if( ent->s.eType == ET_MOVER ) - { - G_RunMover( ent ); - continue; - } - - if( i < MAX_CLIENTS ) - { - G_RunClient( ent ); - continue; - } - - G_RunThink( ent ); - } - - // perform final fixups on the players - ent = &g_entities[ 0 ]; - - for( i = 0; i < level.maxclients; i++, ent++ ) - { - if( ent->inuse ) - ClientEndFrame( ent ); - } - - // save position information for all active clients - G_UnlaggedStore( ); - - G_CountSpawns( ); - G_CalculateBuildPoints( ); - G_CalculateStages( ); - - G_SpawnClients( TEAM_ALIENS ); - G_SpawnClients( TEAM_HUMANS ); - G_CalculateAvgPlayers( ); - G_UpdateZaps( msec ); - - // see if it is time to end the level - CheckExitRules( ); - - // update to team status? - CheckTeamStatus( ); - - // cancel vote if timed out - for( i = 0; i < NUM_TEAMS; i++ ) - G_CheckVote( i ); - - level.frameMsec = trap_Milliseconds(); -} - -- cgit