Index: src/game/g_local.h =================================================================== --- src/game/g_local.h (revision 2074) +++ src/game/g_local.h (working copy) @@ -649,6 +649,7 @@ typedef struct qboolean uncondHumanWin; qboolean alienTeamLocked; qboolean humanTeamLocked; + int pausedTime; int unlaggedIndex; int unlaggedTimes[ MAX_UNLAGGED_MARKERS ]; Index: src/game/g_buildable.c =================================================================== --- src/game/g_buildable.c (revision 2073) +++ src/game/g_buildable.c (working copy) @@ -2660,7 +2660,7 @@ void G_BuildableThink( gentity_t *ent, int msec ) int buildTime = BG_Buildable( ent->s.modelindex )->buildTime; //toggle spawned flag for buildables - if( !ent->spawned && ent->health > 0 ) + if( !ent->spawned && ent->health > 0 && !level.pausedTime ) { if( ent->buildTime + buildTime < level.time ) { Index: src/game/g_main.c =================================================================== --- src/game/g_main.c (revision 2074) +++ src/game/g_main.c (working copy) @@ -2283,6 +2283,22 @@ void G_RunFrame( int levelTime ) if( level.restarted ) return; + if( level.pausedTime ) + { + level.pausedTime = levelTime - level.time; + if( ( level.pausedTime % 3000 ) == 0 ) + trap_SendServerCommand( -1, "cp \"The game has been paused. Please wait.\"" ); + + // 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; + } + + return; + } + level.framenum++; level.previousTime = level.time; level.time = levelTime; Index: src/game/g_admin.c =================================================================== --- src/game/g_admin.c (revision 2073) +++ src/game/g_admin.c (working copy) @@ -144,6 +144,11 @@ g_admin_cmd_t g_admin_cmds[ ] = "pass a vote currently taking place", "(^5a|h^7)" }, + + {"pause", G_admin_pause, "pause", + "Pause (or unpause) the game.", + "" + }, {"putteam", G_admin_putteam, "putteam", "move a player to a specified team", @@ -2913,6 +2918,34 @@ qboolean G_admin_builder( gentity_t *ent ) return qtrue; } +qboolean G_admin_pause( gentity_t *ent ) +{ + if( !level.pausedTime ) + { + AP( va( "print \"^3!pause: ^7%s^7 paused the game.\n\"", + ( ent ) ? ent->client->pers.netname : "console" ) ); + level.pausedTime = 1; + trap_SendServerCommand( -1, "cp \"The game has been paused. Please wait.\"" ); + } + else + { + // Prevent accidental pause->unpause race conditions by two admins + if( level.pausedTime < 1000 ) + { + ADMP( "^3pause: ^7Unpausing so soon assumed accidental and ignored.\n" ); + return qfalse; + } + + AP( va( "print \"^3!pause: ^7%s^7 unpaused the game (Paused for %d msec) \n\"", + ( ent ) ? ent->client->pers.netname : "console",level.pausedTime ) ); + trap_SendServerCommand( -1, "cp \"The game has been unpaused!\"" ); + + level.pausedTime = 0; + } + + return qtrue; +} + static char *fates[] = { "^2built^7", Index: src/game/g_admin.h =================================================================== --- src/game/g_admin.h (revision 2073) +++ src/game/g_admin.h (working copy) @@ -171,6 +171,7 @@ qboolean G_admin_restart( gentity_t *ent ); qboolean G_admin_nextmap( gentity_t *ent ); qboolean G_admin_namelog( gentity_t *ent ); qboolean G_admin_lock( gentity_t *ent ); +qboolean G_admin_pause( gentity_t *ent ); qboolean G_admin_builder( gentity_t *ent ); qboolean G_admin_buildlog( gentity_t *ent ); qboolean G_admin_revert( gentity_t *ent ); Index: src/game/g_cmds.c =================================================================== --- src/game/g_cmds.c (revision 2073) +++ src/game/g_cmds.c (working copy) @@ -3089,7 +3089,8 @@ void ClientCommand( int clientNum ) // do tests here to reduce the amount of repeated code - if( !( command->cmdFlags & CMD_INTERMISSION ) && level.intermissiontime ) + if( !( command->cmdFlags & CMD_INTERMISSION ) && + ( level.intermissiontime || level.pausedTime ) ) return; if( command->cmdFlags & CMD_CHEAT && !g_cheats.integer )