2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code 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 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# include "../idlib/precompiled.h"
# pragma hdrstop
# include "Common_local.h"
# include "../sys/sys_lobby_backend.h"
# define LAUNCH_TITLE_DOOM_EXECUTABLE "doom1.exe"
# define LAUNCH_TITLE_DOOM2_EXECUTABLE "doom2.exe"
idCVar com_wipeSeconds ( " com_wipeSeconds " , " 1 " , CVAR_SYSTEM , " " ) ;
idCVar com_disableAutoSaves ( " com_disableAutoSaves " , " 0 " , CVAR_SYSTEM | CVAR_BOOL , " " ) ;
idCVar com_disableAllSaves ( " com_disableAllSaves " , " 0 " , CVAR_SYSTEM | CVAR_BOOL , " " ) ;
extern idCVar sys_lang ;
extern idCVar g_demoMode ;
// This is for the dirty hack to get a dialog to show up before we capture the screen for autorender.
const int NumScreenUpdatesToShowDialog = 25 ;
/*
= = = = = = = = = = = = = = = =
idCommonLocal : : LaunchExternalTitle
2012-11-28 15:47:07 +00:00
Launches an external title ( Doom 1 , or 2 ) based on title index .
for PS3 , a device number is sent in , for the game to register as a local
2012-11-26 18:58:24 +00:00
user by default , when title initializes .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : LaunchExternalTitle ( int titleIndex , int device , const lobbyConnectInfo_t * const connectInfo )
{
2012-11-26 18:58:24 +00:00
idStr deviceString ( device ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// We want to pass in the current executable, so that the launching title knows which title to return to.
2012-11-28 15:47:07 +00:00
// as of right now, this feature is TBD.
const char * currentExecutablePath = " ImNotSureYet " ;
2012-11-26 18:58:24 +00:00
idStr launchingExecutablePath ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idCmdArgs cmdArgs ;
cmdArgs . AppendArg ( currentExecutablePath ) ;
2012-11-28 15:47:07 +00:00
if ( titleIndex = = LAUNCH_TITLE_DOOM )
{
launchingExecutablePath . Format ( " %s%s " , Sys_DefaultBasePath ( ) , LAUNCH_TITLE_DOOM_EXECUTABLE ) ;
2012-11-26 18:58:24 +00:00
cmdArgs . AppendArg ( " d1bfg " ) ;
2012-11-28 15:47:07 +00:00
}
else if ( titleIndex = = LAUNCH_TITLE_DOOM2 )
{
launchingExecutablePath . Format ( " %s%s " , Sys_DefaultBasePath ( ) , LAUNCH_TITLE_DOOM2_EXECUTABLE ) ;
2012-11-26 18:58:24 +00:00
cmdArgs . AppendArg ( " d2bfg " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
else
{
idLib : : Warning ( " Unhandled Launch Title %d \n " , titleIndex ) ;
}
2012-11-26 18:58:24 +00:00
cmdArgs . AppendArg ( deviceString . c_str ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Add an argument so that the new process knows whether or not to read exitspawn data.
2012-11-28 15:47:07 +00:00
if ( connectInfo ! = NULL )
{
2012-11-26 18:58:24 +00:00
cmdArgs . AppendArg ( " exitspawnInvite " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Add arguments so that the new process will know which command line to invoke to relaunch this process
// if necessary.
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int launchDataSize = ( connectInfo = = NULL ) ? 0 : sizeof ( * connectInfo ) ;
2012-11-28 15:47:07 +00:00
Sys_Launch ( launchingExecutablePath . c_str ( ) , cmdArgs , const_cast < lobbyConnectInfo_t * const > ( connectInfo ) , launchDataSize ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idCommonLocal : : StartWipe
Draws and captures the current state , then starts a wipe with that image
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : StartWipe ( const char * _wipeMaterial , bool hold )
{
2012-11-26 18:58:24 +00:00
console - > Close ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Draw ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderSystem - > CaptureRenderToImage ( " _currentRender " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
wipeMaterial = declManager - > FindMaterial ( _wipeMaterial , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
wipeStartTime = Sys_Milliseconds ( ) ;
wipeStopTime = wipeStartTime + SEC2MS ( com_wipeSeconds . GetFloat ( ) ) ;
wipeHold = hold ;
}
/*
= = = = = = = = = = = = = = = =
idCommonLocal : : CompleteWipe
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : CompleteWipe ( )
{
while ( Sys_Milliseconds ( ) < wipeStopTime )
{
2012-11-26 18:58:24 +00:00
BusyWait ( ) ;
Sys_Sleep ( 10 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// ensure it is completely faded out
wipeStopTime = Sys_Milliseconds ( ) ;
BusyWait ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idCommonLocal : : ClearWipe
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : ClearWipe ( )
{
2012-11-26 18:58:24 +00:00
wipeHold = false ;
wipeStopTime = 0 ;
wipeStartTime = 0 ;
wipeForced = false ;
}
/*
= = = = = = = = = = = = = = =
idCommonLocal : : StartNewGame
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : StartNewGame ( const char * mapName , bool devmap , int gameMode )
{
if ( session - > GetSignInManager ( ) . GetMasterLocalUser ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
// For development make sure a controller is registered
// Can't just register the local user because it will be removed because of it's persistent state
session - > GetSignInManager ( ) . SetDesiredLocalUsers ( 1 , 1 ) ;
session - > GetSignInManager ( ) . Pump ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStr mapNameClean = mapName ;
mapNameClean . StripFileExtension ( ) ;
mapNameClean . BackSlashesToSlashes ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idMatchParameters matchParameters ;
matchParameters . mapName = mapNameClean ;
2012-11-28 15:47:07 +00:00
if ( gameMode = = GAME_MODE_SINGLEPLAYER )
{
2012-11-26 18:58:24 +00:00
matchParameters . numSlots = 1 ;
matchParameters . gameMode = GAME_MODE_SINGLEPLAYER ;
matchParameters . gameMap = GAME_MAP_SINGLEPLAYER ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
matchParameters . gameMap = mpGameMaps . Num ( ) ; // If this map isn't found in mpGameMaps, then set it to some undefined value (this happens when, for example, we load a box map with netmap)
matchParameters . gameMode = gameMode ;
matchParameters . matchFlags = DefaultPartyFlags ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < mpGameMaps . Num ( ) ; i + + )
{
if ( idStr : : Icmp ( mpGameMaps [ i ] . mapFile , mapNameClean ) = = 0 )
{
2012-11-26 18:58:24 +00:00
matchParameters . gameMap = i ;
break ;
}
}
2012-11-28 15:47:07 +00:00
matchParameters . numSlots = session - > GetTitleStorageInt ( " MAX_PLAYERS_ALLOWED " , 4 ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
cvarSystem - > MoveCVarsToDict ( CVAR_SERVERINFO , matchParameters . serverInfo ) ;
2012-11-28 15:47:07 +00:00
if ( devmap )
{
2012-11-26 18:58:24 +00:00
matchParameters . serverInfo . Set ( " devmap " , " 1 " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
matchParameters . serverInfo . Delete ( " devmap " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
session - > QuitMatchToTitle ( ) ;
2012-11-28 15:47:07 +00:00
if ( WaitForSessionState ( idSession : : IDLE ) )
{
2012-11-26 18:58:24 +00:00
session - > CreatePartyLobby ( matchParameters ) ;
2012-11-28 15:47:07 +00:00
if ( WaitForSessionState ( idSession : : PARTY_LOBBY ) )
{
2012-11-26 18:58:24 +00:00
session - > CreateMatch ( matchParameters ) ;
2012-11-28 15:47:07 +00:00
if ( WaitForSessionState ( idSession : : GAME_LOBBY ) )
{
2012-11-26 18:58:24 +00:00
cvarSystem - > SetCVarBool ( " developer " , devmap ) ;
session - > StartMatch ( ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = =
idCommonLocal : : MoveToNewMap
Single player transition from one map to another
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : MoveToNewMap ( const char * mapName , bool devmap )
{
2012-11-26 18:58:24 +00:00
idMatchParameters matchParameters ;
matchParameters . numSlots = 1 ;
matchParameters . gameMode = GAME_MODE_SINGLEPLAYER ;
matchParameters . gameMap = GAME_MAP_SINGLEPLAYER ;
matchParameters . mapName = mapName ;
cvarSystem - > MoveCVarsToDict ( CVAR_SERVERINFO , matchParameters . serverInfo ) ;
2012-11-28 15:47:07 +00:00
if ( devmap )
{
2012-11-26 18:58:24 +00:00
matchParameters . serverInfo . Set ( " devmap " , " 1 " ) ;
mapSpawnData . persistentPlayerInfo . Clear ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
matchParameters . serverInfo . Delete ( " devmap " ) ;
mapSpawnData . persistentPlayerInfo = game - > GetPersistentPlayerInfo ( 0 ) ;
}
session - > QuitMatchToTitle ( ) ;
2012-11-28 15:47:07 +00:00
if ( WaitForSessionState ( idSession : : IDLE ) )
{
2012-11-26 18:58:24 +00:00
session - > CreatePartyLobby ( matchParameters ) ;
2012-11-28 15:47:07 +00:00
if ( WaitForSessionState ( idSession : : PARTY_LOBBY ) )
{
2012-11-26 18:58:24 +00:00
session - > CreateMatch ( matchParameters ) ;
2012-11-28 15:47:07 +00:00
if ( WaitForSessionState ( idSession : : GAME_LOBBY ) )
{
2012-11-26 18:58:24 +00:00
session - > StartMatch ( ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = =
idCommonLocal : : UnloadMap
Performs cleanup that needs to happen between maps , or when a
game is exited .
Exits with mapSpawned = false
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : UnloadMap ( )
{
2012-11-26 18:58:24 +00:00
StopPlayingRenderDemo ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// end the current map in the game
2012-11-28 15:47:07 +00:00
if ( game )
{
2012-11-26 18:58:24 +00:00
game - > MapShutdown ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( writeDemo )
{
2012-11-26 18:58:24 +00:00
StopRecordingRenderDemo ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mapSpawned = false ;
}
/*
= = = = = = = = = = = = = = =
idCommonLocal : : LoadLoadingGui
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : LoadLoadingGui ( const char * mapName , bool & hellMap )
{
2012-11-26 18:58:24 +00:00
defaultLoadscreen = false ;
2012-11-28 15:47:07 +00:00
loadGUI = new idSWF ( " loading/default " , NULL ) ;
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( g_demoMode . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
hellMap = false ;
2012-11-28 15:47:07 +00:00
if ( loadGUI ! = NULL )
{
const idMaterial * defaultMat = declManager - > FindMaterial ( " guis/assets/loadscreens/default " ) ;
2012-11-26 18:58:24 +00:00
renderSystem - > LoadLevelImages ( ) ;
loadGUI - > Activate ( true ) ;
2012-11-28 15:47:07 +00:00
idSWFSpriteInstance * bgImg = loadGUI - > GetRootObject ( ) . GetSprite ( " bgImage " ) ;
if ( bgImg ! = NULL )
{
2012-11-26 18:58:24 +00:00
bgImg - > SetMaterial ( defaultMat ) ;
}
}
defaultLoadscreen = true ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load / program a gui to stay up on the screen while loading
idStrStatic < MAX_OSPATH > stripped = mapName ;
stripped . StripFileExtension ( ) ;
stripped . StripPath ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// use default load screen for demo
idStrStatic < MAX_OSPATH > matName = " guis/assets/loadscreens/ " ;
matName . Append ( stripped ) ;
2012-11-28 15:47:07 +00:00
const idMaterial * mat = declManager - > FindMaterial ( matName ) ;
2012-11-26 18:58:24 +00:00
renderSystem - > LoadLevelImages ( ) ;
2012-11-28 15:47:07 +00:00
if ( mat - > GetImageWidth ( ) < 32 )
{
2012-11-26 18:58:24 +00:00
mat = declManager - > FindMaterial ( " guis/assets/loadscreens/default " ) ;
renderSystem - > LoadLevelImages ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
loadTipList . SetNum ( loadTipList . Max ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < loadTipList . Max ( ) ; + + i )
{
2012-11-26 18:58:24 +00:00
loadTipList [ i ] = i ;
}
2012-11-28 15:47:07 +00:00
if ( loadGUI ! = NULL )
{
2012-11-26 18:58:24 +00:00
loadGUI - > Activate ( true ) ;
nextLoadTip = Sys_Milliseconds ( ) + LOAD_TIP_CHANGE_INTERVAL ;
2012-11-28 15:47:07 +00:00
idSWFSpriteInstance * bgImg = loadGUI - > GetRootObject ( ) . GetSprite ( " bgImage " ) ;
if ( bgImg ! = NULL )
{
2012-11-26 18:58:24 +00:00
bgImg - > SetMaterial ( mat ) ;
}
2012-11-28 15:47:07 +00:00
idSWFSpriteInstance * overlay = loadGUI - > GetRootObject ( ) . GetSprite ( " overlay " ) ;
const idDeclEntityDef * mapDef = static_cast < const idDeclEntityDef * > ( declManager - > FindType ( DECL_MAPDEF , mapName , false ) ) ;
if ( mapDef ! = NULL )
{
2012-11-26 18:58:24 +00:00
isHellMap = mapDef - > dict . GetBool ( " hellMap " , false ) ;
2012-11-28 15:47:07 +00:00
if ( isHellMap & & overlay ! = NULL )
{
2012-11-26 18:58:24 +00:00
overlay - > SetVisible ( false ) ;
}
2012-11-28 15:47:07 +00:00
idStr desc ;
2012-11-26 18:58:24 +00:00
idStr subTitle ;
idStr displayName ;
2012-11-28 15:47:07 +00:00
idSWFTextInstance * txtVal = NULL ;
2012-11-26 18:58:24 +00:00
txtVal = loadGUI - > GetRootObject ( ) . GetNestedText ( " txtRegLoad " ) ;
displayName = idLocalization : : GetString ( mapDef - > dict . GetString ( " name " , mapName ) ) ;
2012-11-28 15:47:07 +00:00
if ( txtVal ! = NULL )
{
2012-11-26 18:58:24 +00:00
txtVal - > SetText ( " #str_00408 " ) ;
txtVal - > SetStrokeInfo ( true , 2.0f , 1.0f ) ;
2012-11-28 15:47:07 +00:00
}
const idMatchParameters & matchParameters = session - > GetActingGameStateLobbyBase ( ) . GetMatchParms ( ) ;
if ( matchParameters . gameMode = = GAME_MODE_SINGLEPLAYER )
{
2012-11-26 18:58:24 +00:00
desc = idLocalization : : GetString ( mapDef - > dict . GetString ( " desc " , " " ) ) ;
subTitle = idLocalization : : GetString ( mapDef - > dict . GetString ( " subTitle " , " " ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
const idStrList & modes = common - > GetModeDisplayList ( ) ;
2012-11-26 18:58:24 +00:00
subTitle = modes [ idMath : : ClampInt ( 0 , modes . Num ( ) - 1 , matchParameters . gameMode ) ] ;
2012-11-28 15:47:07 +00:00
const char * modeDescs [ ] = { " #str_swf_deathmatch_desc " , " #str_swf_tourney_desc " , " #str_swf_team_deathmatch_desc " , " #str_swf_lastman_desc " , " #str_swf_ctf_desc " } ;
2012-11-26 18:58:24 +00:00
desc = idLocalization : : GetString ( modeDescs [ matchParameters . gameMode ] ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! isHellMap )
{
2012-11-26 18:58:24 +00:00
txtVal = loadGUI - > GetRootObject ( ) . GetNestedText ( " txtName " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
txtVal = loadGUI - > GetRootObject ( ) . GetNestedText ( " txtHellName " ) ;
}
2012-11-28 15:47:07 +00:00
if ( txtVal ! = NULL )
{
2012-11-26 18:58:24 +00:00
txtVal - > SetText ( displayName ) ;
txtVal - > SetStrokeInfo ( true , 2.0f , 1.0f ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
txtVal = loadGUI - > GetRootObject ( ) . GetNestedText ( " txtSub " ) ;
2012-11-28 15:47:07 +00:00
if ( txtVal ! = NULL & & ! isHellMap )
{
2012-11-26 18:58:24 +00:00
txtVal - > SetText ( subTitle ) ;
txtVal - > SetStrokeInfo ( true , 1.75f , 0.75f ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
txtVal = loadGUI - > GetRootObject ( ) . GetNestedText ( " txtDesc " ) ;
2012-11-28 15:47:07 +00:00
if ( txtVal ! = NULL )
{
if ( isHellMap )
{
2012-11-26 18:58:24 +00:00
txtVal - > SetText ( va ( " \n %s " , desc . c_str ( ) ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
txtVal - > SetText ( desc ) ;
}
txtVal - > SetStrokeInfo ( true , 1.75f , 0.75f ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = =
idCommonLocal : : ExecuteMapChange
Performs the initialization of a game based on session match parameters , used for both single
player and multiplayer , but not for renderDemos , which don ' t create a game at all .
Exits with mapSpawned = true
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : ExecuteMapChange ( )
{
if ( session - > GetState ( ) ! = idSession : : LOADING )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " Session state is not LOADING in ExecuteMapChange " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Clear all dialogs before beginning the load
common - > Dialog ( ) . ClearDialogs ( true ) ;
// Remember the current load ID.
// This is so we can tell if we had a new loadmap request from within an existing loadmap call
const int cachedLoadingID = session - > GetLoadingID ( ) ;
2012-11-28 15:47:07 +00:00
const idMatchParameters & matchParameters = session - > GetActingGameStateLobbyBase ( ) . GetMatchParms ( ) ;
if ( matchParameters . numSlots < = 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " numSlots <= 0 in ExecuteMapChange " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
insideExecuteMapChange = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " --------- Execute Map Change --------- \n " ) ;
common - > Printf ( " Map: %s \n " , matchParameters . mapName . c_str ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// ensure that r_znear is reset to the default value
// this fixes issues with the projection matrix getting messed up when switching maps or loading a saved game
// while an in-game cinematic is playing.
cvarSystem - > SetCVarFloat ( " r_znear " , 3.0f ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reset all cheat cvars for a multiplayer game
2012-11-28 15:47:07 +00:00
if ( IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
cvarSystem - > ResetFlaggedVariables ( CVAR_CHEAT ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int start = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_INPUT_DEVICES ; i + + )
{
2012-11-26 18:58:24 +00:00
Sys_SetRumble ( i , 0 , 0 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// close console and remove any prints from the notify lines
console - > Close ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear all menu sounds
soundWorld - > Pause ( ) ;
menuSoundWorld - > ClearAllSoundEmitters ( ) ;
soundSystem - > SetPlayingSoundWorld ( menuSoundWorld ) ;
soundSystem - > Render ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// extract the map name from serverinfo
currentMapName = matchParameters . mapName ;
currentMapName . StripFileExtension ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStrStatic < MAX_OSPATH > fullMapName = " maps/ " ;
fullMapName + = currentMapName ;
fullMapName . SetFileExtension ( " map " ) ;
2012-11-28 15:47:07 +00:00
if ( mapSpawnData . savegameFile )
{
2012-11-26 18:58:24 +00:00
fileSystem - > BeginLevelLoad ( currentMapName , NULL , 0 ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
fileSystem - > BeginLevelLoad ( currentMapName , saveFile . GetDataPtr ( ) , saveFile . GetAllocated ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// capture the current screen and start a wipe
// immediately complete the wipe to fade out the level transition
// run the wipe to completion
StartWipe ( " wipeMaterial " , true ) ;
CompleteWipe ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int sm = Sys_Milliseconds ( ) ;
// shut down the existing game if it is running
UnloadMap ( ) ;
int ms = Sys_Milliseconds ( ) - sm ;
common - > Printf ( " %6d msec to unload map \n " , ms ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Free media from previous level and
// note which media we are going to need to load
sm = Sys_Milliseconds ( ) ;
renderSystem - > BeginLevelLoad ( ) ;
soundSystem - > BeginLevelLoad ( ) ;
declManager - > BeginLevelLoad ( ) ;
uiManager - > BeginLevelLoad ( ) ;
ms = Sys_Milliseconds ( ) - sm ;
common - > Printf ( " %6d msec to free assets \n " , ms ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//Sys_DumpMemory( true );
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load / program a gui to stay up on the screen while loading
// set the loading gui that we will wipe to
bool hellMap = false ;
LoadLoadingGui ( currentMapName , hellMap ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Stop rendering the wipe
ClearWipe ( ) ;
2012-11-28 15:47:07 +00:00
if ( fileSystem - > UsingResourceFiles ( ) )
{
2012-11-26 18:58:24 +00:00
idStrStatic < MAX_OSPATH > manifestName = currentMapName ;
manifestName . Replace ( " game/ " , " maps/ " ) ;
manifestName . Replace ( " /mp/ " , " / " ) ;
manifestName + = " .preload " ;
idPreloadManifest manifest ;
manifest . LoadManifest ( manifestName ) ;
renderSystem - > Preload ( manifest , currentMapName ) ;
soundSystem - > Preload ( manifest ) ;
game - > Preload ( manifest ) ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
// In multiplayer, make sure the player is either 60Hz or 120Hz
// to avoid potential issues.
const float mpEngineHz = ( com_engineHz . GetFloat ( ) < 90.0f ) ? 60.0f : 120.0f ;
com_engineHz_denominator = 100LL * mpEngineHz ;
com_engineHz_latched = mpEngineHz ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// allow com_engineHz to be changed between map loads
com_engineHz_denominator = 100LL * com_engineHz . GetFloat ( ) ;
com_engineHz_latched = com_engineHz . GetFloat ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// note any warning prints that happen during the load process
common - > ClearWarnings ( currentMapName ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// release the mouse cursor
// before we do this potentially long operation
Sys_GrabMouseCursor ( false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// let the renderSystem load all the geometry
2012-11-28 15:47:07 +00:00
if ( ! renderWorld - > InitFromMap ( fullMapName ) )
{
2012-11-26 18:58:24 +00:00
common - > Error ( " couldn't load %s " , fullMapName . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// for the synchronous networking we needed to roll the angles over from
// level to level, but now we can just clear everything
usercmdGen - > InitForNewMap ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load and spawn all other entities ( from a savegame possibly )
2012-11-28 15:47:07 +00:00
if ( mapSpawnData . savegameFile )
{
if ( ! game - > InitFromSaveGame ( fullMapName , renderWorld , soundWorld , mapSpawnData . savegameFile , mapSpawnData . stringTableFile , mapSpawnData . savegameVersion ) )
{
2012-11-26 18:58:24 +00:00
// If the loadgame failed, end the session, which will force us to go back to the main menu
session - > QuitMatchToTitle ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( ! IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
assert ( game - > GetLocalClientNum ( ) = = 0 ) ;
assert ( matchParameters . gameMode = = GAME_MODE_SINGLEPLAYER ) ;
assert ( matchParameters . gameMap = = GAME_MAP_SINGLEPLAYER ) ;
game - > SetPersistentPlayerInfo ( 0 , mapSpawnData . persistentPlayerInfo ) ;
}
game - > SetServerInfo ( matchParameters . serverInfo ) ;
game - > InitFromNewMap ( fullMapName , renderWorld , soundWorld , matchParameters . gameMode , Sys_Milliseconds ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
game - > Shell_CreateMenu ( true ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Reset some values important to multiplayer
ResetNetworkingState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// If the session state is not loading here, something went wrong.
2012-11-28 15:47:07 +00:00
if ( session - > GetState ( ) = = idSession : : LOADING & & session - > GetLoadingID ( ) = = cachedLoadingID )
{
2012-11-26 18:58:24 +00:00
// Notify session we are done loading
session - > LoadingFinished ( ) ;
2012-11-28 15:47:07 +00:00
while ( session - > GetState ( ) = = idSession : : LOADING )
{
2012-11-26 18:58:24 +00:00
Sys_GenerateEvents ( ) ;
session - > UpdateSignInManager ( ) ;
session - > Pump ( ) ;
Sys_Sleep ( 10 ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! mapSpawnData . savegameFile )
{
2012-11-26 18:58:24 +00:00
// run a single frame to catch any resources that are referenced by events posted in spawn
idUserCmdMgr emptyCommandManager ;
gameReturn_t emptyGameReturn ;
2012-11-28 15:47:07 +00:00
for ( int playerIndex = 0 ; playerIndex < MAX_PLAYERS ; + + playerIndex )
{
2012-11-26 18:58:24 +00:00
emptyCommandManager . PutUserCmdForPlayer ( playerIndex , usercmd_t ( ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
game - > ClientRunFrame ( emptyCommandManager , false , emptyGameReturn ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
game - > RunFrame ( emptyCommandManager , emptyGameReturn ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderSystem - > EndLevelLoad ( ) ;
soundSystem - > EndLevelLoad ( ) ;
declManager - > EndLevelLoad ( ) ;
uiManager - > EndLevelLoad ( currentMapName ) ;
fileSystem - > EndLevelLoad ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! mapSpawnData . savegameFile & & ! IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " ----- Running initial game frames ----- \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// In single player, run a bunch of frames to make sure ragdolls are settled
idUserCmdMgr emptyCommandManager ;
gameReturn_t emptyGameReturn ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < 100 ; i + + )
{
for ( int playerIndex = 0 ; playerIndex < MAX_PLAYERS ; + + playerIndex )
{
2012-11-26 18:58:24 +00:00
emptyCommandManager . PutUserCmdForPlayer ( playerIndex , usercmd_t ( ) ) ;
}
game - > RunFrame ( emptyCommandManager , emptyGameReturn ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// kick off an auto-save of the game (so we can always continue in this map if we die before hitting an autosave)
common - > Printf ( " ----- Saving Game ----- \n " ) ;
SaveGame ( " autosave " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " ----- Generating Interactions ----- \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// let the renderSystem generate interactions now that everything is spawned
renderWorld - > GenerateAllInteractions ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
{
int vertexMemUsedKB = vertexCache . staticData . vertexMemUsed . GetValue ( ) / 1024 ;
int indexMemUsedKB = vertexCache . staticData . indexMemUsed . GetValue ( ) / 1024 ;
idLib : : Printf ( " Used %dkb of static vertex memory (%d%%) \n " , vertexMemUsedKB , vertexMemUsedKB * 100 / ( STATIC_VERTEX_MEMORY / 1024 ) ) ;
idLib : : Printf ( " Used %dkb of static index memory (%d%%) \n " , indexMemUsedKB , indexMemUsedKB * 100 / ( STATIC_INDEX_MEMORY / 1024 ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( common - > JapaneseCensorship ( ) )
{
if ( currentMapName . Icmp ( " game/mp/d3xpdm3 " ) = = 0 )
{
const idMaterial * gizpool2 = declManager - > FindMaterial ( " textures/hell/gizpool2 " ) ;
idMaterial * chiglass1bluex = const_cast < idMaterial * > ( declManager - > FindMaterial ( " textures/sfx/chiglass1bluex " ) ) ;
2012-11-26 18:58:24 +00:00
idTempArray < char > text ( gizpool2 - > GetTextLength ( ) ) ;
gizpool2 - > GetText ( text . Ptr ( ) ) ;
chiglass1bluex - > Parse ( text . Ptr ( ) , text . Num ( ) , false ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > PrintWarnings ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
session - > Pump ( ) ;
2012-11-28 15:47:07 +00:00
if ( session - > GetState ( ) ! = idSession : : INGAME )
{
2012-11-26 18:58:24 +00:00
// Something went wrong, don't process stale reliables that have been queued up.
reliableQueue . Clear ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
usercmdGen - > Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// remove any prints from the notify lines
console - > ClearNotifyLines ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Sys_SetPhysicalWorkMemory ( - 1 , - 1 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// at this point we should be done with the loading gui so we kill it
delete loadGUI ;
loadGUI = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// capture the current screen and start a wipe
StartWipe ( " wipe2Material " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// we are valid for game draws now
insideExecuteMapChange = false ;
mapSpawned = true ;
Sys_ClearEvents ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int msec = Sys_Milliseconds ( ) - start ;
common - > Printf ( " %6d msec to load %s \n " , msec , currentMapName . c_str ( ) ) ;
2012-11-28 15:47:07 +00:00
//Sys_DumpMemory( false );
2012-11-26 18:58:24 +00:00
// Issue a render at the very end of the load process to update soundTime before the first frame
soundSystem - > Render ( ) ;
}
/*
= = = = = = = = = = = = = = =
idCommonLocal : : UpdateLevelLoadPacifier
Pumps the session and if multiplayer , displays dialogs during the loading process .
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : UpdateLevelLoadPacifier ( )
{
2012-11-26 18:58:24 +00:00
autoRenderIconType_t icon = AUTORENDER_DEFAULTICON ;
bool autoswapsRunning = renderSystem - > AreAutomaticBackgroundSwapsRunning ( & icon ) ;
2012-11-28 15:47:07 +00:00
if ( ! insideExecuteMapChange & & ! autoswapsRunning )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int sessionUpdateTime = common - > IsMultiplayer ( ) ? 16 : 100 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int time = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Throttle session pumps.
2012-11-28 15:47:07 +00:00
if ( time - lastPacifierSessionTime > = sessionUpdateTime )
{
2012-11-26 18:58:24 +00:00
lastPacifierSessionTime = time ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Sys_GenerateEvents ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
session - > UpdateSignInManager ( ) ;
session - > Pump ( ) ;
session - > ProcessSnapAckQueue ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( autoswapsRunning )
{
2012-11-26 18:58:24 +00:00
// If autoswaps are running, only update if a Dialog is shown/dismissed
bool dialogState = Dialog ( ) . HasAnyActiveDialog ( ) ;
2012-11-28 15:47:07 +00:00
if ( lastPacifierDialogState ! = dialogState )
{
2012-11-26 18:58:24 +00:00
lastPacifierDialogState = dialogState ;
renderSystem - > EndAutomaticBackgroundSwaps ( ) ;
2012-11-28 15:47:07 +00:00
if ( dialogState )
{
2012-11-26 18:58:24 +00:00
icon = AUTORENDER_DIALOGICON ; // Done this way to handle the rare case of a tip changing at the same time a dialog comes up
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < NumScreenUpdatesToShowDialog ; + + i )
{
2012-11-26 18:58:24 +00:00
UpdateScreen ( false ) ;
}
}
renderSystem - > BeginAutomaticBackgroundSwaps ( icon ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// On the PC just update at a constant rate for the Steam overlay
2012-11-28 15:47:07 +00:00
if ( time - lastPacifierGuiTime > = 50 )
{
2012-11-26 18:58:24 +00:00
lastPacifierGuiTime = time ;
UpdateScreen ( false ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( time > = nextLoadTip & & loadGUI ! = NULL & & loadTipList . Num ( ) > 0 & & ! defaultLoadscreen )
{
if ( autoswapsRunning )
{
2012-11-26 18:58:24 +00:00
renderSystem - > EndAutomaticBackgroundSwaps ( ) ;
}
nextLoadTip = time + LOAD_TIP_CHANGE_INTERVAL ;
const int rnd = time % loadTipList . Num ( ) ;
idStrStatic < 20 > tipId ;
tipId . Format ( " #str_loadtip_%d " , loadTipList [ rnd ] ) ;
loadTipList . RemoveIndex ( rnd ) ;
2012-11-28 15:47:07 +00:00
idSWFTextInstance * txtVal = loadGUI - > GetRootObject ( ) . GetNestedText ( " txtDesc " ) ;
if ( txtVal ! = NULL )
{
if ( isHellMap )
{
2012-11-26 18:58:24 +00:00
txtVal - > SetText ( va ( " \n %s " , idLocalization : : GetString ( tipId ) ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
txtVal - > SetText ( idLocalization : : GetString ( tipId ) ) ;
}
txtVal - > SetStrokeInfo ( true , 1.75f , 0.75f ) ;
}
UpdateScreen ( false ) ;
2012-11-28 15:47:07 +00:00
if ( autoswapsRunning )
{
2012-11-26 18:58:24 +00:00
renderSystem - > BeginAutomaticBackgroundSwaps ( icon ) ;
}
}
}
/*
= = = = = = = = = = = = = = =
idCommonLocal : : ScrubSaveGameFileName
Turns a bad file name into a good one or your money back
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : ScrubSaveGameFileName ( idStr & saveFileName ) const
{
2012-11-26 18:58:24 +00:00
int i ;
idStr inFileName ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inFileName = saveFileName ;
inFileName . RemoveColors ( ) ;
inFileName . StripFileExtension ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
saveFileName . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int len = inFileName . Length ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < len ; i + + )
{
if ( strchr ( " ',.~!@#$%^&*()[]{}<> \\ |/=?+;:- \' \" " , inFileName [ i ] ) )
{
2012-11-26 18:58:24 +00:00
// random junk
saveFileName + = ' _ ' ;
2012-11-28 15:47:07 +00:00
}
else if ( ( const unsigned char ) inFileName [ i ] > = 128 )
{
2012-11-26 18:58:24 +00:00
// high ascii chars
saveFileName + = ' _ ' ;
2012-11-28 15:47:07 +00:00
}
else if ( inFileName [ i ] = = ' ' )
{
2012-11-26 18:58:24 +00:00
saveFileName + = ' _ ' ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
saveFileName + = inFileName [ i ] ;
}
}
}
/*
= = = = = = = = = = = = = = =
idCommonLocal : : SaveGame
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idCommonLocal : : SaveGame ( const char * saveName )
{
if ( pipelineFile ! = NULL )
{
2012-11-26 18:58:24 +00:00
// We're already in the middle of a save. Leave us alone.
return false ;
}
2012-11-28 15:47:07 +00:00
if ( com_disableAllSaves . GetBool ( ) | | ( com_disableAutoSaves . GetBool ( ) & & ( idStr : : Icmp ( saveName , " autosave " ) = = 0 ) ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " Can't save during net play. \n " ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
if ( mapSpawnData . savegameFile ! = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
const idDict & persistentPlayerInfo = game - > GetPersistentPlayerInfo ( 0 ) ;
if ( persistentPlayerInfo . GetInt ( " health " ) < = 0 )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " You must be alive to save the game \n " ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
soundWorld - > Pause ( ) ;
soundSystem - > SetPlayingSoundWorld ( menuSoundWorld ) ;
soundSystem - > Render ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Dialog ( ) . ShowSaveIndicator ( true ) ;
2012-11-28 15:47:07 +00:00
if ( insideExecuteMapChange )
{
2012-11-26 18:58:24 +00:00
UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Heremake sure we pump the gui enough times to show the 'saving' dialog
const bool captureToImage = false ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < NumScreenUpdatesToShowDialog ; + + i )
{
2012-11-26 18:58:24 +00:00
UpdateScreen ( captureToImage ) ;
}
renderSystem - > BeginAutomaticBackgroundSwaps ( AUTORENDER_DIALOGICON ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Make sure the file is writable and the contents are cleared out (Set to write from the start of file)
saveFile . MakeWritable ( ) ;
saveFile . Clear ( false ) ;
stringsFile . MakeWritable ( ) ;
stringsFile . Clear ( false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Setup the save pipeline
2012-11-28 15:47:07 +00:00
pipelineFile = new ( TAG_SAVEGAMES ) idFile_SaveGamePipelined ( ) ;
2012-11-26 18:58:24 +00:00
pipelineFile - > OpenForWriting ( & saveFile ) ;
2012-11-28 15:47:07 +00:00
// Write SaveGame Header:
2012-11-26 18:58:24 +00:00
// Game Name / Version / Map Name / Persistant Player Info
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// game
2012-11-28 15:47:07 +00:00
const char * gamename = GAME_NAME ;
2012-11-26 18:58:24 +00:00
saveFile . WriteString ( gamename ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// map
saveFile . WriteString ( currentMapName ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
saveFile . WriteBool ( consoleUsed ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
game - > GetServerInfo ( ) . WriteToFileHandle ( & saveFile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// let the game save its state
game - > SaveGame ( pipelineFile , & stringsFile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
pipelineFile - > Finish ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idSaveGameDetails gameDetails ;
game - > GetSaveGameDetails ( gameDetails ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameDetails . descriptors . Set ( SAVEGAME_DETAIL_FIELD_LANGUAGE , sys_lang . GetString ( ) ) ;
2012-11-28 15:47:07 +00:00
gameDetails . descriptors . SetInt ( SAVEGAME_DETAIL_FIELD_CHECKSUM , ( int ) gameDetails . descriptors . Checksum ( ) ) ;
2012-11-26 18:58:24 +00:00
gameDetails . slotName = saveName ;
ScrubSaveGameFileName ( gameDetails . slotName ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
saveFileEntryList_t files ;
files . Append ( & stringsFile ) ;
files . Append ( & saveFile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
session - > SaveGameSync ( gameDetails . slotName , files , gameDetails ) ;
2012-11-28 15:47:07 +00:00
if ( ! insideExecuteMapChange )
{
2012-11-26 18:58:24 +00:00
renderSystem - > EndAutomaticBackgroundSwaps ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
syncNextGameFrame = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = =
idCommonLocal : : LoadGame
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idCommonLocal : : LoadGame ( const char * saveName )
{
if ( IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " Can't load during net play. \n " ) ;
2012-11-28 15:47:07 +00:00
if ( wipeForced )
{
2012-11-26 18:58:24 +00:00
ClearWipe ( ) ;
}
return false ;
}
2012-11-28 15:47:07 +00:00
2012-12-06 23:09:53 +00:00
// RB begin
# if defined(USE_DOOMCLASSIC)
2012-11-28 15:47:07 +00:00
if ( GetCurrentGame ( ) ! = DOOM3_BFG )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-12-06 23:09:53 +00:00
# endif
// RB end
2012-11-28 15:47:07 +00:00
if ( session - > GetSignInManager ( ) . GetMasterLocalUser ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( mapSpawnData . savegameFile ! = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool found = false ;
2012-11-28 15:47:07 +00:00
const saveGameDetailsList_t & sgdl = session - > GetSaveGameManager ( ) . GetEnumeratedSavegames ( ) ;
for ( int i = 0 ; i < sgdl . Num ( ) ; i + + )
{
if ( sgdl [ i ] . slotName = = saveName )
{
if ( sgdl [ i ] . GetLanguage ( ) ! = sys_lang . GetString ( ) )
{
idStaticList < idSWFScriptFunction * , 4 > callbacks ;
2012-11-26 18:58:24 +00:00
idStaticList < idStrId , 4 > optionText ;
optionText . Append ( idStrId ( " #str_swf_continue " ) ) ;
idStrStatic < 256 > langName = " #str_lang_ " + sgdl [ i ] . GetLanguage ( ) ;
idStrStatic < 256 > msg ;
msg . Format ( idLocalization : : GetString ( " #str_dlg_wrong_language " ) , idLocalization : : GetString ( langName ) ) ;
Dialog ( ) . AddDynamicDialog ( GDM_SAVEGAME_WRONG_LANGUAGE , callbacks , optionText , true , msg , false , true ) ;
2012-11-28 15:47:07 +00:00
if ( wipeForced )
{
2012-11-26 18:58:24 +00:00
ClearWipe ( ) ;
}
return false ;
}
found = true ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! found )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " Could not find save '%s' \n " , saveName ) ;
2012-11-28 15:47:07 +00:00
if ( wipeForced )
{
2012-11-26 18:58:24 +00:00
ClearWipe ( ) ;
}
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mapSpawnData . savegameFile = & saveFile ;
mapSpawnData . stringTableFile = & stringsFile ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
saveFileEntryList_t files ;
files . Append ( mapSpawnData . stringTableFile ) ;
files . Append ( mapSpawnData . savegameFile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStr slotName = saveName ;
ScrubSaveGameFileName ( slotName ) ;
saveFile . Clear ( false ) ;
stringsFile . Clear ( false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
saveGameHandle_t loadGameHandle = session - > LoadGameSync ( slotName , files ) ;
2012-11-28 15:47:07 +00:00
if ( loadGameHandle ! = 0 )
{
2012-11-26 18:58:24 +00:00
return true ;
}
mapSpawnData . savegameFile = NULL ;
2012-11-28 15:47:07 +00:00
if ( wipeForced )
{
2012-11-26 18:58:24 +00:00
ClearWipe ( ) ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
HandleInsufficientStorage
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void HandleInsufficientStorage ( const idSaveLoadParms & parms )
{
2012-11-26 18:58:24 +00:00
session - > GetSaveGameManager ( ) . ShowRetySaveDialog ( parms . directory , parms . requiredSpaceInBytes ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
HandleCommonErrors
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool HandleCommonErrors ( const idSaveLoadParms & parms )
{
if ( parms . GetError ( ) = = SAVEGAME_E_NONE )
{
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . ShowSaveIndicator ( false ) ;
2012-11-28 15:47:07 +00:00
if ( parms . GetError ( ) & SAVEGAME_E_CORRUPTED )
{
2012-11-26 18:58:24 +00:00
// This one might need to be handled by the game
common - > Dialog ( ) . AddDialog ( GDM_CORRUPT_CONTINUE , DIALOG_CONTINUE , NULL , NULL , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Find the game in the enumerated details, mark as corrupt so the menus can show as corrupt
2012-11-28 15:47:07 +00:00
saveGameDetailsList_t & list = session - > GetSaveGameManager ( ) . GetEnumeratedSavegamesNonConst ( ) ;
for ( int i = 0 ; i < list . Num ( ) ; i + + )
{
if ( idStr : : Icmp ( list [ i ] . slotName , parms . description . slotName ) = = 0 )
{
2012-11-26 18:58:24 +00:00
list [ i ] . damaged = true ;
}
}
return true ;
2012-11-28 15:47:07 +00:00
}
else if ( parms . GetError ( ) & SAVEGAME_E_INSUFFICIENT_ROOM )
{
2012-11-26 18:58:24 +00:00
HandleInsufficientStorage ( parms ) ;
return true ;
2012-11-28 15:47:07 +00:00
}
else if ( parms . GetError ( ) & SAVEGAME_E_UNABLE_TO_SELECT_STORAGE_DEVICE & & saveGame_enable . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_UNABLE_TO_USE_SELECTED_STORAGE_DEVICE , DIALOG_CONTINUE , NULL , NULL , false ) ;
return true ;
2012-11-28 15:47:07 +00:00
}
else if ( parms . GetError ( ) & SAVEGAME_E_INVALID_FILENAME )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( va ( " Invalid savegame filename [%s]! " , parms . directory . c_str ( ) ) ) ;
return true ;
2012-11-28 15:47:07 +00:00
}
else if ( parms . GetError ( ) & SAVEGAME_E_DLC_NOT_FOUND )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_DLC_ERROR_MISSING_GENERIC , DIALOG_CONTINUE , NULL , NULL , false ) ;
return true ;
2012-11-28 15:47:07 +00:00
}
else if ( parms . GetError ( ) & SAVEGAME_E_DISC_SWAP )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_DISC_SWAP , DIALOG_CONTINUE , NULL , NULL , false ) ;
return true ;
2012-11-28 15:47:07 +00:00
}
else if ( parms . GetError ( ) & SAVEGAME_E_INCOMPATIBLE_NEWER_VERSION )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_INCOMPATIBLE_NEWER_SAVE , DIALOG_CONTINUE , NULL , NULL , false ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idCommonLocal : : OnSaveCompleted
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : OnSaveCompleted ( idSaveLoadParms & parms )
{
2012-11-26 18:58:24 +00:00
assert ( pipelineFile ! = NULL ) ;
delete pipelineFile ;
pipelineFile = NULL ;
2012-11-28 15:47:07 +00:00
if ( parms . GetError ( ) = = SAVEGAME_E_NONE )
{
2012-11-26 18:58:24 +00:00
game - > Shell_UpdateSavedGames ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! HandleCommonErrors ( parms ) )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_ERROR_SAVING_SAVEGAME , DIALOG_CONTINUE , NULL , NULL , false ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idCommonLocal : : OnLoadCompleted
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : OnLoadCompleted ( idSaveLoadParms & parms )
{
if ( ! HandleCommonErrors ( parms ) )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_ERROR_LOADING_SAVEGAME , DIALOG_CONTINUE , NULL , NULL , false ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idCommonLocal : : OnLoadFilesCompleted
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : OnLoadFilesCompleted ( idSaveLoadParms & parms )
{
if ( ( mapSpawnData . savegameFile ! = NULL ) & & ( parms . GetError ( ) = = SAVEGAME_E_NONE ) )
{
2012-11-26 18:58:24 +00:00
// just need to make the file readable
2012-11-28 15:47:07 +00:00
( ( idFile_Memory * ) mapSpawnData . savegameFile ) - > MakeReadOnly ( ) ;
( ( idFile_Memory * ) mapSpawnData . stringTableFile ) - > MakeReadOnly ( ) ;
2012-11-26 18:58:24 +00:00
idStr gamename ;
idStr mapname ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mapSpawnData . savegameVersion = parms . description . GetSaveVersion ( ) ;
mapSpawnData . savegameFile - > ReadString ( gamename ) ;
mapSpawnData . savegameFile - > ReadString ( mapname ) ;
2012-11-28 15:47:07 +00:00
if ( ( gamename ! = GAME_NAME ) | | ( mapname . IsEmpty ( ) ) | | ( parms . description . GetSaveVersion ( ) > BUILD_NUMBER ) )
{
2012-11-26 18:58:24 +00:00
// if this isn't a savegame for the correct game, abort loadgame
common - > Warning ( " Attempted to load an invalid savegame " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
common - > DPrintf ( " loading savegame \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mapSpawnData . savegameFile - > ReadBool ( consoleUsed ) ;
consoleUsed = consoleUsed | | com_allowConsole . GetBool ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idMatchParameters matchParameters ;
matchParameters . numSlots = 1 ;
matchParameters . gameMode = GAME_MODE_SINGLEPLAYER ;
matchParameters . gameMap = GAME_MAP_SINGLEPLAYER ;
matchParameters . mapName = mapname ;
matchParameters . serverInfo . ReadFromFileHandle ( mapSpawnData . savegameFile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
session - > QuitMatchToTitle ( ) ;
2012-11-28 15:47:07 +00:00
if ( WaitForSessionState ( idSession : : IDLE ) )
{
2012-11-26 18:58:24 +00:00
session - > CreatePartyLobby ( matchParameters ) ;
2012-11-28 15:47:07 +00:00
if ( WaitForSessionState ( idSession : : PARTY_LOBBY ) )
{
2012-11-26 18:58:24 +00:00
session - > CreateMatch ( matchParameters ) ;
2012-11-28 15:47:07 +00:00
if ( WaitForSessionState ( idSession : : GAME_LOBBY ) )
{
2012-11-26 18:58:24 +00:00
session - > StartMatch ( ) ;
return ;
}
}
}
}
}
// If we got here then we didn't actually load the save game for some reason
mapSpawnData . savegameFile = NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idCommonLocal : : TriggerScreenWipe
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : TriggerScreenWipe ( const char * _wipeMaterial , bool hold )
{
2012-11-26 18:58:24 +00:00
StartWipe ( _wipeMaterial , hold ) ;
CompleteWipe ( ) ;
wipeForced = true ;
renderSystem - > BeginAutomaticBackgroundSwaps ( AUTORENDER_DEFAULTICON ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idCommonLocal : : OnEnumerationCompleted
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : OnEnumerationCompleted ( idSaveLoadParms & parms )
{
if ( parms . GetError ( ) = = SAVEGAME_E_NONE )
{
2012-11-26 18:58:24 +00:00
game - > Shell_UpdateSavedGames ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idCommonLocal : : OnDeleteCompleted
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idCommonLocal : : OnDeleteCompleted ( idSaveLoadParms & parms )
{
if ( parms . GetError ( ) = = SAVEGAME_E_NONE )
{
2012-11-26 18:58:24 +00:00
game - > Shell_UpdateSavedGames ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
LoadGame_f
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND_SHIP ( loadGame , " loads a game " , idCmdSystem : : ArgCompletion_SaveGame )
{
2012-11-26 18:58:24 +00:00
console - > Close ( ) ;
2012-11-28 15:47:07 +00:00
commonLocal . LoadGame ( ( args . Argc ( ) > 1 ) ? args . Argv ( 1 ) : " quick " ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = =
SaveGame_f
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND_SHIP ( saveGame , " saves a game " , NULL )
{
const char * savename = ( args . Argc ( ) > 1 ) ? args . Argv ( 1 ) : " quick " ;
if ( commonLocal . SaveGame ( savename ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " Saved: %s \n " , savename ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
Common_Map_f
Restart the server on a different map
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND_SHIP ( map , " loads a map " , idCmdSystem : : ArgCompletion_MapName )
{
commonLocal . StartNewGame ( args . Argv ( 1 ) , false , GAME_MODE_SINGLEPLAYER ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
Common_RestartMap_f
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND_SHIP ( restartMap , " restarts the current map " , NULL )
{
if ( g_demoMode . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
cmdSystem - > AppendCommandText ( va ( " devmap %s %d \n " , commonLocal . GetCurrentMapName ( ) , 0 ) ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
Common_DevMap_f
Restart the server on a different map in developer mode
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND_SHIP ( devmap , " loads a map in developer mode " , idCmdSystem : : ArgCompletion_MapName )
{
commonLocal . StartNewGame ( args . Argv ( 1 ) , true , GAME_MODE_SINGLEPLAYER ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
Common_NetMap_f
Restart the server on a different map in multiplayer mode
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND_SHIP ( netmap , " loads a map in multiplayer mode " , idCmdSystem : : ArgCompletion_MapName )
{
2012-11-26 18:58:24 +00:00
int gameMode = 0 ; // Default to deathmatch
2012-11-28 15:47:07 +00:00
if ( args . Argc ( ) > 2 )
{
gameMode = atoi ( args . Argv ( 2 ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
commonLocal . StartNewGame ( args . Argv ( 1 ) , true , gameMode ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
Common_TestMap_f
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND ( testmap , " tests a map " , idCmdSystem : : ArgCompletion_MapName )
{
2012-11-26 18:58:24 +00:00
idStr map , string ;
2012-11-28 15:47:07 +00:00
map = args . Argv ( 1 ) ;
if ( ! map . Length ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
map . StripFileExtension ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , " disconnect " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
sprintf ( string , " dmap maps/%s.map " , map . c_str ( ) ) ;
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , string ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
sprintf ( string , " devmap %s " , map . c_str ( ) ) ;
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , string ) ;
}