2009-05-08 13:28:41 +00:00
/*
* OpenClonk , http : //www.openclonk.org
*
2009-06-05 13:41:20 +00:00
* Copyright ( c ) 1998 - 2000 , 2003 - 2005 , 2007 - 2008 Matthes Bender
2013-01-09 23:23:06 +00:00
* Copyright ( c ) 2001 - 2009 , 2011 - 2012 Sven Eberhardt
2009-06-05 13:41:20 +00:00
* Copyright ( c ) 2001 - 2009 Peter Wortmann
2011-09-01 14:58:52 +00:00
* Copyright ( c ) 2004 , 2011 Tobias Zwick
2013-01-09 23:23:06 +00:00
* Copyright ( c ) 2004 - 2012 G ü nther Brammer
2009-06-05 13:41:20 +00:00
* Copyright ( c ) 2006 Florian Gro ß
2013-01-09 23:23:06 +00:00
* Copyright ( c ) 2008 , 2010 - 2012 Armin Burgmeier
2010-12-23 00:01:24 +00:00
* Copyright ( c ) 2009 - 2010 Nicolas Hake
2011-09-01 14:58:52 +00:00
* Copyright ( c ) 2009 David Dormagen
2010-12-23 00:01:24 +00:00
* Copyright ( c ) 2010 Benjamin Herr
2013-01-09 23:23:06 +00:00
* Copyright ( c ) 2011 Felix Wagner
* Copyright ( c ) 2011 - 2012 Julius Michaelis
2009-05-08 13:28:41 +00:00
* Copyright ( c ) 2001 - 2009 , RedWolf Design GmbH , http : //www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk .
*
* Permission to use , copy , modify , and / or distribute this software for any
* purpose with or without fee is hereby granted , provided that the above
* copyright notice and this permission notice appear in all copies .
* See isc_license . txt for full license and disclaimer .
*
* " Clonk " is a registered trademark of Matthes Bender .
* See clonk_trademark_license . txt for full license .
*/
/* Main class to run the game */
# include <C4Include.h>
# include <C4Game.h>
2011-03-02 23:58:43 +00:00
# include <C4AulDebug.h>
2011-03-03 16:10:22 +00:00
# include <C4DefList.h>
2012-04-27 17:04:43 +00:00
# include <C4Effect.h>
2011-01-08 16:04:20 +00:00
# include <C4FileMonitor.h>
2009-05-08 13:28:41 +00:00
# include <C4GameSave.h>
# include <C4Record.h>
# include <C4Application.h>
# include <C4Object.h>
# include <C4ObjectInfo.h>
# include <C4Random.h>
# include <C4ObjectCom.h>
# include <C4FullScreen.h>
# include <C4Startup.h>
# include <C4Viewport.h>
# include <C4Command.h>
# include <C4Stat.h>
# include <C4League.h>
# include <C4PlayerInfo.h>
# include <C4LoaderScreen.h>
# include <C4Network2Dialogs.h>
# include <C4Console.h>
# include <C4Network2Stats.h>
# include <C4Log.h>
# include <C4Player.h>
# include <C4GameOverDlg.h>
2011-03-11 02:43:38 +00:00
# include <C4GameParameters.h>
2009-05-08 13:28:41 +00:00
# include <C4ObjectMenu.h>
# include <C4GameLobby.h>
# include <C4ChatDlg.h>
2009-05-26 06:10:38 +00:00
# include <C4PlayerControl.h>
2009-06-05 18:00:23 +00:00
# include <C4MouseControl.h>
# include <C4PXS.h>
# include <C4MessageInput.h>
# include <C4MassMover.h>
# include <C4RankSystem.h>
2011-03-11 02:43:38 +00:00
# include <C4RoundResults.h>
2009-06-05 18:12:43 +00:00
# include <C4GameMessage.h>
2009-06-05 18:46:03 +00:00
# include <C4Material.h>
2011-01-08 16:04:20 +00:00
# include <C4Network2Reference.h>
2009-06-11 19:59:35 +00:00
# include <C4Weather.h>
2009-06-12 18:52:21 +00:00
# include <C4GraphicsResource.h>
# include <C4GraphicsSystem.h>
# include <C4Texture.h>
# include <C4Landscape.h>
2009-06-12 23:09:32 +00:00
# include <C4PlayerList.h>
2009-06-15 21:47:26 +00:00
# include <C4GameObjects.h>
2009-06-15 22:06:37 +00:00
# include <C4GameControl.h>
2011-01-08 16:04:20 +00:00
# include <C4Version.h>
2012-04-13 18:28:30 +00:00
# include <C4AulExec.h>
2009-05-08 13:28:41 +00:00
# include <StdFile.h>
2013-03-18 23:35:00 +00:00
# include <C4MapScript.h>
2009-05-08 13:28:41 +00:00
class C4GameSec1Timer : public C4ApplicationSec1Timer
2010-03-28 17:58:21 +00:00
{
public :
C4GameSec1Timer ( ) { Application . Add ( this ) ; }
~ C4GameSec1Timer ( ) { Application . Remove ( this ) ; }
void OnSec1Timer ( ) ;
} ;
2009-05-08 13:28:41 +00:00
2011-03-11 02:43:38 +00:00
static C4GameParameters GameParameters ;
static C4RoundResults GameRoundResults ;
2011-03-13 15:46:18 +00:00
C4Game : : C4Game ( ) :
2011-03-11 02:43:38 +00:00
Parameters ( GameParameters ) ,
2011-03-13 15:46:18 +00:00
Clients ( Parameters . Clients ) ,
2010-03-28 17:58:21 +00:00
Teams ( Parameters . Teams ) ,
PlayerInfos ( Parameters . PlayerInfos ) ,
RestorePlayerInfos ( Parameters . RestorePlayerInfos ) ,
2011-03-11 02:43:38 +00:00
RoundResults ( GameRoundResults ) ,
2010-03-28 17:58:21 +00:00
Input ( Control . Input ) ,
KeyboardInput ( C4KeyboardInput_Init ( ) ) ,
pFileMonitor ( NULL ) ,
pSec1Timer ( new C4GameSec1Timer ( ) ) ,
fPreinited ( false ) , StartupLogPos ( 0 ) , QuitLogPos ( 0 ) ,
fQuitWithError ( false )
{
2009-05-08 13:28:41 +00:00
Default ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
C4Game : : ~ C4Game ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// remove timer
delete pSec1Timer ; pSec1Timer = NULL ;
// make sure no startup gfx remain loaded
C4Startup : : Unload ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : InitDefs ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t iDefs = 0 ;
Log ( LoadResStr ( " IDS_PRC_INITDEFS " ) ) ;
int iDefResCount = 0 ;
C4GameRes * pDef ;
2010-03-28 17:58:21 +00:00
for ( pDef = Parameters . GameRes . iterRes ( NULL , NRT_Definitions ) ; pDef ; pDef = Parameters . GameRes . iterRes ( pDef , NRT_Definitions ) )
2009-05-08 13:28:41 +00:00
+ + iDefResCount ;
int i = 0 ;
// Load specified defs
2010-03-28 17:58:21 +00:00
for ( pDef = Parameters . GameRes . iterRes ( NULL , NRT_Definitions ) ; pDef ; pDef = Parameters . GameRes . iterRes ( pDef , NRT_Definitions ) )
{
2010-12-29 16:00:13 +00:00
int iMinProgress = 25 + ( 25 * i ) / iDefResCount ;
int iMaxProgress = 25 + ( 25 * ( i + 1 ) ) / iDefResCount ;
2009-05-08 13:28:41 +00:00
+ + i ;
2009-08-15 18:50:32 +00:00
iDefs + = : : Definitions . Load ( pDef - > getFile ( ) , C4D_Load_RX , Config . General . LanguageEx , & Application . SoundSystem , true , iMinProgress , iMaxProgress ) ;
2009-05-08 13:28:41 +00:00
// Def load failure
2009-08-15 18:50:32 +00:00
if ( : : Definitions . LoadFailure ) return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Load for scenario file - ignore sys group here, because it has been loaded already
2009-08-15 18:50:32 +00:00
iDefs + = : : Definitions . Load ( ScenarioFile , C4D_Load_RX , Config . General . LanguageEx , & Application . SoundSystem , true , true , 35 , 40 , false ) ;
2009-05-08 13:28:41 +00:00
// Absolutely no defs: we don't like that
2009-08-15 18:50:32 +00:00
if ( ! iDefs ) { LogFatal ( LoadResStr ( " IDS_PRC_NODEFS " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// Check def engine version (should be done immediately on def load)
2012-10-18 21:54:50 +00:00
iDefs = : : Definitions . CheckEngineVersion ( C4XVER1 , C4XVER2 , C4XVER3 ) ;
2010-03-27 16:05:02 +00:00
if ( iDefs > 0 ) { LogF ( LoadResStr ( " IDS_PRC_DEFSINVC4X " ) , iDefs ) ; }
2009-05-08 13:28:41 +00:00
// Check for unmet requirements
2009-06-05 16:46:37 +00:00
: : Definitions . CheckRequireDef ( ) ;
2009-05-08 13:28:41 +00:00
// build quick access table
2009-06-05 16:46:37 +00:00
: : Definitions . BuildTable ( ) ;
2009-05-08 13:28:41 +00:00
// get default particles
Particles . SetDefParticles ( ) ;
// Done
2010-03-27 16:05:02 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2011-03-27 14:51:14 +00:00
bool C4Game : : OpenScenario ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Scenario from record stream
2010-03-28 17:58:21 +00:00
if ( RecordStream . getSize ( ) )
{
2009-05-08 13:28:41 +00:00
StdStrBuf RecordFile ;
2010-03-28 17:58:21 +00:00
if ( ! C4Playback : : StreamToRecord ( RecordStream . getData ( ) , & RecordFile ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( " [!] Could not process record stream data! " ) ; return false ; }
2009-05-08 13:28:41 +00:00
SCopy ( RecordFile . getData ( ) , ScenarioFilename , _MAX_PATH ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Scenario filename check & log
2009-08-15 18:50:32 +00:00
if ( ! ScenarioFilename [ 0 ] ) { LogFatal ( LoadResStr ( " IDS_PRC_NOC4S " ) ) ; return false ; }
2010-03-27 16:05:02 +00:00
LogF ( LoadResStr ( " IDS_PRC_LOADC4S " ) , ScenarioFilename ) ;
2009-05-08 13:28:41 +00:00
2011-03-13 15:38:33 +00:00
// get parent folder, if it's ocf
2009-05-08 13:28:41 +00:00
pParentGroup = GroupSet . RegisterParentFolders ( ScenarioFilename ) ;
// open scenario
if ( pParentGroup )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// open from parent group
if ( ! ScenarioFile . OpenAsChild ( pParentGroup , GetFilename ( ScenarioFilename ) ) )
2009-08-15 18:50:32 +00:00
{ LogF ( " %s: %s " , LoadResStr ( " IDS_PRC_FILENOTFOUND " ) , ( const char * ) ScenarioFilename ) ; return false ; }
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
2011-01-06 20:18:13 +00:00
{
2009-05-08 13:28:41 +00:00
// open directly
2011-01-06 20:18:13 +00:00
if ( ! Reloc . Open ( ScenarioFile , ScenarioFilename ) )
2009-08-15 18:50:32 +00:00
{ LogF ( " %s: %s " , LoadResStr ( " IDS_PRC_FILENOTFOUND " ) , ( const char * ) ScenarioFilename ) ; return false ; }
2011-01-06 20:18:13 +00:00
}
// Remember full (absolute) path
SCopy ( ScenarioFile . GetFullName ( ) . getData ( ) , ScenarioFilename , _MAX_PATH ) ;
2009-05-08 13:28:41 +00:00
// add scenario to group
GroupSet . RegisterGroup ( ScenarioFile , false , C4GSPrio_Scenario , C4GSCnt_Scenario ) ;
2010-03-27 16:05:02 +00:00
// Read scenario core
if ( ! C4S . Load ( ScenarioFile ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_FILEINVALID " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// Check minimum engine version
2012-10-18 21:54:50 +00:00
if ( CompareVersion ( C4S . Head . C4XVer [ 0 ] , C4S . Head . C4XVer [ 1 ] , C4S . Head . C4XVer [ 2 ] ) > 0 )
2010-03-28 17:58:21 +00:00
{
2012-10-18 21:54:50 +00:00
LogFatal ( FormatString ( LoadResStr ( " IDS_PRC_NOREQC4X " ) , C4S . Head . C4XVer [ 0 ] , C4S . Head . C4XVer [ 1 ] , C4S . Head . C4XVer [ 2 ] ) . getData ( ) ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Add scenario origin to group set
if ( C4S . Head . Origin . getLength ( ) & & ! ItemIdentical ( C4S . Head . Origin . getData ( ) , ScenarioFilename ) )
GroupSet . RegisterParentFolders ( C4S . Head . Origin . getData ( ) ) ;
// Scenario definition preset
StdStrBuf sDefinitionFilenames ;
if ( ! C4S . Definitions . AllowUserChange & & C4S . Definitions . GetModules ( & sDefinitionFilenames ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
SCopy ( sDefinitionFilenames . getData ( ) , DefinitionFilenames , ( sizeof DefinitionFilenames ) - 1 ) ;
if ( DefinitionFilenames [ 0 ] ) Log ( LoadResStr ( " IDS_PRC_SCEOWNDEFS " ) ) ;
else Log ( LoadResStr ( " IDS_PRC_LOCALONLY " ) ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2011-03-13 15:38:33 +00:00
// add all .ocf-modules to the group set
2009-05-08 13:28:41 +00:00
// (for savegames, network games, etc.)
2010-03-28 17:58:21 +00:00
/* char szModule[_MAX_PATH+1]; C4Group *pGrp=NULL; int32_t iDefGrpPrio=C4GSPrio_Definition;
for ( int32_t cseg = 0 ; SCopySegment ( DefinitionFilenames , cseg , szModule , ' ; ' , _MAX_PATH ) ; cseg + + )
2011-03-13 15:38:33 +00:00
if ( SEqualNoCase ( GetExtension ( szModule ) , " ocf " ) )
2010-03-28 17:58:21 +00:00
{
if ( ! pGrp ) pGrp = new C4Group ( ) ;
if ( ! pGrp - > Open ( szModule ) ) continue ;
int32_t iContent = GroupSet . CheckGroupContents ( * pGrp , C4GSCnt_Folder ) ;
if ( ! iContent ) { pGrp - > Close ( ) ; continue ; }
GroupSet . RegisterGroup ( * pGrp , true , Min ( iDefGrpPrio + + , C4GSPrio_Definition2 ) , iContent , false ) ;
// group owned by groupset now
pGrp = NULL ;
}
if ( pGrp ) delete pGrp ; */
2009-05-08 13:28:41 +00:00
// Check mission access
2013-03-03 18:41:23 +00:00
# ifndef USE_CONSOLE
2013-03-03 18:29:00 +00:00
if ( C4S . Head . MissionAccess [ 0 ] )
if ( ! SIsModule ( Config . General . MissionAccess , C4S . Head . MissionAccess ) )
{ LogFatal ( LoadResStr ( " IDS_PRC_NOMISSIONACCESS " ) ) ; return false ; }
# endif
2009-05-08 13:28:41 +00:00
// Title
2013-10-29 20:32:21 +00:00
C4Language : : LoadComponentHost ( & Title , ScenarioFile , C4CFN_Title , Config . General . LanguageEx ) ;
2009-05-08 13:28:41 +00:00
if ( ! Title . GetLanguageString ( Config . General . LanguageEx , ScenarioTitle ) )
ScenarioTitle . Copy ( C4S . Head . Title ) ;
// String tables
2013-10-29 20:32:21 +00:00
C4Language : : LoadComponentHost ( & ScenarioLangStringTable , ScenarioFile , C4CFN_ScriptStringTbl , Config . General . LanguageEx ) ;
2009-05-08 13:28:41 +00:00
// Load parameters (not as network client, because then team info has already been sent by host)
if ( ! Network . isEnabled ( ) | | Network . isHost ( ) )
2010-03-28 17:58:21 +00:00
if ( ! Parameters . Load ( ScenarioFile , & C4S , GameText . GetData ( ) , & ScenarioLangStringTable , DefinitionFilenames ) )
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
SetInitProgress ( 4 ) ;
// If scenario is a directory: Watch for changes
2010-03-28 17:58:21 +00:00
if ( ! ScenarioFile . IsPacked ( ) & & pFileMonitor )
2009-05-08 13:28:41 +00:00
Game . pFileMonitor - > AddDirectory ( ScenarioFile . GetFullName ( ) . getData ( ) ) ;
2010-03-27 16:05:02 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : CloseScenario ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// safe scenario file name
char szSzenarioFile [ _MAX_PATH + 1 ] ;
SCopy ( ScenarioFile . GetFullName ( ) . getData ( ) , szSzenarioFile , _MAX_PATH ) ;
// close scenario
2010-03-27 16:05:02 +00:00
ScenarioFile . Close ( ) ;
2009-05-08 13:28:41 +00:00
GroupSet . CloseFolders ( ) ;
pParentGroup = NULL ;
// remove if temporary
2010-03-28 17:58:21 +00:00
if ( TempScenarioFile )
2009-05-08 13:28:41 +00:00
{
2010-03-28 17:58:21 +00:00
EraseItem ( szSzenarioFile ) ;
2009-08-15 18:50:32 +00:00
TempScenarioFile = false ;
2009-05-08 13:28:41 +00:00
}
// clear scenario section
// this removes any temp files, which may yet need to be used by any future features
// so better don't do this too early (like, in C4Game::Clear)
if ( pScenarioSections ) { delete pScenarioSections ; pScenarioSections = pCurrentScenarioSection = NULL ; }
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : PreInit ( )
2010-03-28 17:58:21 +00:00
{
2010-06-28 23:02:14 +00:00
// init extra root group
// this loads font definitions in this group as well
// the function may return false, if no extra group is present - that is OK
Extra . InitGroup ( ) ;
2011-10-13 15:05:40 +00:00
2010-06-28 23:02:14 +00:00
Log ( LoadResStr ( " IDS_PRC_GFXRES " ) ) ;
if ( ! GraphicsResource . Init ( ) ) return false ;
Game . SetInitProgress ( 30.0f ) ;
2009-05-08 13:28:41 +00:00
2010-06-27 00:42:48 +00:00
RandomSeed = time ( NULL ) ;
// Randomize
FixRandom ( RandomSeed ) ;
// Timer flags
GameGo = false ;
// set gamma
2011-10-03 14:30:18 +00:00
pDraw - > SetGamma ( Config . Graphics . Gamma1 , Config . Graphics . Gamma2 , Config . Graphics . Gamma3 , C4GRI_USER ) ;
2010-06-27 00:42:48 +00:00
// init message input (default commands)
MessageInput . Init ( ) ;
2010-06-28 23:02:14 +00:00
Game . SetInitProgress ( 31.0f ) ;
2010-06-27 00:42:48 +00:00
// init keyboard input (default keys, plus overloads)
if ( ! InitKeyboard ( ) )
{ LogFatal ( LoadResStr ( " IDS_ERR_NOKEYBOARD " ) ) ; return false ; }
// Load string table
UpdateLanguage ( ) ;
// Player keyboard input: Key definitions and default sets
if ( ! InitPlayerControlSettings ( ) ) return false ;
2010-06-28 23:02:14 +00:00
Game . SetInitProgress ( 32.0f ) ;
2010-06-27 00:42:48 +00:00
// Rank system
: : DefaultRanks . Init ( Config . GetSubkeyPath ( " ClonkRanks " ) , LoadResStr ( " IDS_GAME_DEFRANKS " ) , 1000 ) ;
2010-06-28 23:02:14 +00:00
Game . SetInitProgress ( 33.0f ) ;
2009-05-08 13:28:41 +00:00
// Graphics system (required for GUI)
if ( ! GraphicsSystem . Init ( ) )
{ LogFatal ( LoadResStr ( " IDS_ERR_NOGFXSYS " ) ) ; return false ; }
// load GUI
2012-10-22 21:15:48 +00:00
C4Rect r ;
if ( Application . isEditor )
Console . GetSize ( & r ) ;
else
FullScreen . GetSize ( & r ) ;
pGUI - > Init ( 0 , 0 , r . Wdt , r . Hgt ) ;
2009-05-08 13:28:41 +00:00
fPreinited = true ;
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : Init ( )
2010-03-28 17:58:21 +00:00
{
2011-03-26 22:59:35 +00:00
C4ValueNumbers numbers ;
2009-08-15 18:50:32 +00:00
IsRunning = false ;
2009-05-08 13:28:41 +00:00
InitProgress = 0 ; LastInitProgress = 0 ; LastInitProgressShowTime = 0 ;
SetInitProgress ( 0 ) ;
2011-01-06 23:51:35 +00:00
// reinit keyboard to reflect any config changes that might have been done
// this is a good time to do it, because no GUI dialogs are opened
if ( ! InitKeyboard ( ) ) LogFatal ( LoadResStr ( " IDS_ERR_NOKEYBOARD " ) ) ;
2009-05-08 13:28:41 +00:00
// start log pos (used by startup)
StartupLogPos = GetLogPos ( ) ;
fQuitWithError = false ;
C4GameLobby : : UserAbort = false ;
// Store a start time that identifies this game on this host
StartTime = time ( NULL ) ;
// Get PlayerFilenames from Config, if ParseCommandLine did not fill some in
// Must be done here, because InitGame calls PlayerInfos.InitLocal
if ( ! * PlayerFilenames )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
SCopy ( Config . General . Participants , PlayerFilenames , Min ( sizeof ( PlayerFilenames ) , sizeof ( Config . General . Participants ) ) - 1 ) ;
StartupPlayerCount = SModuleCount ( PlayerFilenames ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Join a game?
2010-03-28 17:58:21 +00:00
if ( pJoinReference | | * DirectJoinAddress )
{
2009-05-08 13:28:41 +00:00
2010-03-28 17:58:21 +00:00
if ( ! GraphicsSystem . pLoaderScreen )
{
2009-05-08 13:28:41 +00:00
// init extra; needed for loader screen
Log ( LoadResStr ( " IDS_PRC_INITEXTRA " ) ) ;
if ( ! Extra . Init ( ) )
{ LogFatal ( LoadResStr ( " IDS_PRC_ERREXTRA " ) ) ; return false ; }
// init loader
2012-10-02 21:02:52 +00:00
if ( ! Application . isEditor & & ! GraphicsSystem . InitLoaderScreen ( C4S . Head . Loader ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_ERRLOADER " ) ) ; return false ; }
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
SetInitProgress ( 5 ) ;
// Initialize network
2010-03-28 17:58:21 +00:00
if ( pJoinReference )
{
2009-05-08 13:28:41 +00:00
// By reference
2009-08-15 18:50:32 +00:00
bool fSuccess = InitNetworkFromReference ( * pJoinReference ) ;
2009-05-08 13:28:41 +00:00
delete pJoinReference ; pJoinReference = NULL ;
2010-03-28 17:58:21 +00:00
if ( ! fSuccess )
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// By address
2010-03-28 17:58:21 +00:00
if ( ! InitNetworkFromAddress ( DirectJoinAddress ) )
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// check wether console mode is allowed
2010-09-28 18:16:33 +00:00
if ( Application . isEditor & & ! Parameters . AllowDebug )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_TEXT_JOININCONSOLEMODENOTALLOW " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// do lobby (if desired)
2010-03-28 17:58:21 +00:00
if ( Network . isLobbyActive ( ) )
if ( ! Network . DoLobby ( ) )
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
// get scenario
char szScenario [ _MAX_PATH + 1 ] ;
SetInitProgress ( 6 ) ;
2010-03-28 17:58:21 +00:00
if ( ! Network . RetrieveScenario ( szScenario ) ) return false ;
2009-05-08 13:28:41 +00:00
// open new scenario
SCopy ( szScenario , ScenarioFilename , _MAX_PATH ) ;
2011-03-27 14:51:14 +00:00
if ( ! OpenScenario ( ) ) return false ;
2009-08-15 18:50:32 +00:00
TempScenarioFile = true ;
2009-05-08 13:28:41 +00:00
2010-03-27 16:05:02 +00:00
// get everything else
2010-03-28 17:58:21 +00:00
if ( ! Parameters . GameRes . RetrieveFiles ( ) ) return false ;
2009-05-08 13:28:41 +00:00
// Check network game data scenario type (safety)
if ( ! C4S . Head . NetworkGame )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_NET_NONETGAME " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
SetInitProgress ( 7 ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Local game or host?
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Open scenario
2011-03-27 14:51:14 +00:00
if ( ! OpenScenario ( ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_FAIL " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// init extra; needed for loader screen
2010-03-27 16:05:02 +00:00
Log ( LoadResStr ( " IDS_PRC_INITEXTRA " ) ) ;
2009-05-08 13:28:41 +00:00
if ( ! Extra . Init ( ) )
{ LogFatal ( LoadResStr ( " IDS_PRC_ERREXTRA " ) ) ; return false ; }
// init loader
2012-10-02 21:02:52 +00:00
if ( ! Application . isEditor & & ! GraphicsSystem . InitLoaderScreen ( C4S . Head . Loader ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_ERRLOADER " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// Init network
2010-03-28 17:58:21 +00:00
if ( ! InitNetworkHost ( ) ) return false ;
2009-05-08 13:28:41 +00:00
SetInitProgress ( 7 ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// now free all startup gfx to make room for game gfx
C4Startup : : Unload ( ) ;
// Init debugmode
2011-03-02 17:13:43 +00:00
DebugMode = ! ! Application . isEditor ;
2010-03-28 17:58:21 +00:00
if ( Config . General . AlwaysDebug )
2009-05-08 13:28:41 +00:00
DebugMode = true ;
2010-03-28 17:58:21 +00:00
if ( ! Parameters . AllowDebug )
2009-05-08 13:28:41 +00:00
DebugMode = false ;
// Init game
2011-03-26 22:59:35 +00:00
if ( ! InitGame ( ScenarioFile , false , true , & numbers ) ) return false ;
2009-05-08 13:28:41 +00:00
// Network final init
2010-03-28 17:58:21 +00:00
if ( Network . isEnabled ( ) )
{
2009-08-15 18:50:32 +00:00
if ( ! Network . FinalInit ( ) ) return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// non-net may have to synchronize now to keep in sync with replays
// also needs to synchronize to update transfer zones
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// - would kill DebugRec-sync for runtime debugrec starts
C4DebugRecOff DBGRECOFF ( ! ! C4S . Head . SaveGame ) ;
SyncClearance ( ) ;
2009-08-15 18:50:32 +00:00
Synchronize ( false ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Init players
2011-03-26 22:59:35 +00:00
if ( ! InitPlayers ( & numbers ) ) return false ;
2009-05-08 13:28:41 +00:00
SetInitProgress ( 98 ) ;
// Final init
2010-03-28 17:58:21 +00:00
if ( ! InitGameFinal ( ) ) return false ;
2009-05-08 13:28:41 +00:00
SetInitProgress ( 99 ) ;
2010-06-28 23:02:16 +00:00
// Gamma
2011-10-03 14:30:18 +00:00
pDraw - > ApplyGamma ( ) ;
2009-05-08 13:28:41 +00:00
// Message board and upper board
2010-09-28 18:16:33 +00:00
if ( ! Application . isEditor )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
InitFullscreenComponents ( true ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Default fullscreen menu, in case any old surfaces are left (extra safety)
FullScreen . CloseMenu ( ) ;
// start statistics (always for now. Make this a config?)
pNetworkStatistics = new C4Network2Stats ( ) ;
// clear loader screen
if ( GraphicsSystem . pLoaderScreen )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
delete GraphicsSystem . pLoaderScreen ;
GraphicsSystem . pLoaderScreen = NULL ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// game running now!
2009-08-15 18:50:32 +00:00
IsRunning = true ;
2009-05-08 13:28:41 +00:00
// Start message
Log ( LoadResStr ( C4S . Head . NetworkGame ? " IDS_PRC_JOIN " : C4S . Head . SaveGame ? " IDS_PRC_RESUME " : " IDS_PRC_START " ) ) ;
// set non-exclusive GUI
2010-10-29 23:47:50 +00:00
pGUI - > SetExclusive ( false ) ;
2009-05-08 13:28:41 +00:00
// after GUI is made non-exclusive, recheck the scoreboard
Scoreboard . DoDlgShow ( 0 , false ) ;
SetInitProgress ( 100 ) ;
// and redraw background
GraphicsSystem . InvalidateBg ( ) ;
2011-01-06 23:51:35 +00:00
// Notify editor
Console . InitGame ( ) ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2010-10-04 19:39:19 +00:00
void C4Game : : SetScenarioFilename ( const char * c4sfile )
{
SCopy ( c4sfile , ScenarioFilename , _MAX_PATH ) ;
if ( SEqualNoCase ( GetFilename ( c4sfile ) , " scenario.txt " ) )
{
if ( GetFilename ( ScenarioFilename ) ! = ScenarioFilename ) * ( GetFilename ( ScenarioFilename ) - 1 ) = 0 ;
}
}
2009-05-08 13:28:41 +00:00
void C4Game : : Clear ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
delete pFileMonitor ; pFileMonitor = NULL ;
// fade out music
Application . MusicSystem . FadeOut ( 2000 ) ;
// game no longer running
2009-08-15 18:50:32 +00:00
IsRunning = false ;
2009-05-08 13:28:41 +00:00
PointersDenumerated = false ;
C4ST_SHOWSTAT
// C4ST_RESET
// Evaluation
if ( GameOver )
2010-03-28 17:58:21 +00:00
{
if ( ! Evaluated ) Evaluate ( ) ;
}
2009-05-08 13:28:41 +00:00
// stop statistics
if ( pNetworkStatistics ) { delete pNetworkStatistics ; pNetworkStatistics = NULL ; }
C4AulProfiler : : Abort ( ) ;
// exit gui
2010-10-29 23:19:54 +00:00
pGUI - > Clear ( ) ;
2011-10-13 15:05:40 +00:00
2009-05-08 13:28:41 +00:00
// next mission (shoud have been transferred to C4Application now if next mission was desired)
NextMission . Clear ( ) ; NextMissionText . Clear ( ) ; NextMissionDesc . Clear ( ) ;
Network . Clear ( ) ;
Control . Clear ( ) ;
// Clear
Scoreboard . Clear ( ) ;
MouseControl . Clear ( ) ;
Players . Clear ( ) ;
Parameters . Clear ( ) ;
RoundResults . Clear ( ) ;
C4S . Clear ( ) ;
Weather . Clear ( ) ;
GraphicsSystem . Clear ( ) ;
2010-01-26 21:47:40 +00:00
DeleteObjects ( true ) ;
: : Definitions . Clear ( ) ;
2009-05-08 13:28:41 +00:00
Landscape . Clear ( ) ;
PXS . Clear ( ) ;
if ( pGlobalEffects ) { delete pGlobalEffects ; pGlobalEffects = NULL ; }
Particles . Clear ( ) ;
2013-10-08 23:28:58 +00:00
DynamicParticles . Clear ( ) ;
2009-06-05 18:46:03 +00:00
: : MaterialMap . Clear ( ) ;
2010-01-26 21:47:40 +00:00
TextureMap . Clear ( ) ; // texture map *MUST* be cleared after the materials, because of the patterns!
2010-06-28 23:02:14 +00:00
//::GraphicsResource.Clear();
2009-06-05 18:12:43 +00:00
: : Messages . Clear ( ) ;
2009-05-08 13:28:41 +00:00
MessageInput . Clear ( ) ;
Info . Clear ( ) ;
Title . Clear ( ) ;
2013-03-18 23:35:00 +00:00
: : MapScript . Clear ( ) ;
2011-01-08 16:04:20 +00:00
: : GameScript . Clear ( ) ;
2009-05-08 13:28:41 +00:00
Names . Clear ( ) ;
GameText . Clear ( ) ;
RecordDumpFile . Clear ( ) ;
RecordStream . Clear ( ) ;
2010-03-27 16:05:02 +00:00
PathFinder . Clear ( ) ;
2009-05-08 13:28:41 +00:00
TransferZones . Clear ( ) ;
# ifndef USE_CONSOLE
2010-06-27 00:21:23 +00:00
: : FontLoader . Clear ( ) ;
2009-05-08 13:28:41 +00:00
# endif
ScriptEngine . Clear ( ) ;
MainSysLangStringTable . Clear ( ) ;
ScenarioLangStringTable . Clear ( ) ;
2010-03-27 16:05:02 +00:00
CloseScenario ( ) ;
2009-05-08 13:28:41 +00:00
GroupSet . Clear ( ) ;
KeyboardInput . Clear ( ) ;
SetMusicLevel ( 100 ) ;
PlayList . Clear ( ) ;
2011-03-30 20:11:47 +00:00
PlayerControlUserAssignmentSets . Clear ( ) ;
PlayerControlDefaultAssignmentSets . Clear ( ) ;
2009-05-26 06:10:38 +00:00
PlayerControlDefs . Clear ( ) ;
2011-01-08 16:04:20 +00:00
: : MeshMaterialManager . Clear ( ) ;
2012-09-29 21:49:30 +00:00
Application . SoundSystem . Init ( ) ; // clear it up and re-init it for startup menu use
2009-05-08 13:28:41 +00:00
// global fullscreen class is not cleared, because it holds the carrier window
// but the menu must be cleared (maybe move Fullscreen.Menu somewhere else?)
FullScreen . CloseMenu ( ) ;
2011-01-06 23:51:35 +00:00
// notify editor
Console . CloseGame ( ) ;
2009-05-08 13:28:41 +00:00
// Message
// avoid double message by not printing it if no restbl is loaded
// this would log an "[Undefined]" only, anyway
// (could abort the whole clear-procedure here, btw?)
2013-10-19 17:28:54 +00:00
if ( : : Languages . HasStringTable ( ) ) Log ( LoadResStr ( " IDS_CNS_GAMECLOSED " ) ) ;
2009-05-08 13:28:41 +00:00
// clear game starting parameters
* DefinitionFilenames = * DirectJoinAddress = * ScenarioFilename = * PlayerFilenames = 0 ;
// join reference
delete pJoinReference ; pJoinReference = NULL ;
// okay, game cleared now. Remember log section
QuitLogPos = GetLogPos ( ) ;
fPreinited = false ;
2011-03-05 02:32:51 +00:00
C4PropListNumbered : : ResetEnumerationIndex ( ) ;
2012-09-29 21:49:30 +00:00
2011-01-19 01:13:51 +00:00
// FIXME: remove this
Default ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : GameOverCheck ( )
2010-03-28 17:58:21 +00:00
{
2009-08-15 18:50:32 +00:00
bool fDoGameOver = false ;
2009-05-08 13:28:41 +00:00
# ifdef _DEBUG
2009-08-15 18:50:32 +00:00
//return false;
2009-05-08 13:28:41 +00:00
# endif
// Only every 35 ticks
2009-08-15 18:50:32 +00:00
if ( : : Game . iTick35 ) return false ;
2009-05-08 13:28:41 +00:00
// do not GameOver in replay
2009-08-15 18:50:32 +00:00
if ( Control . isReplay ( ) ) return false ;
2009-05-08 13:28:41 +00:00
// All players eliminated: game over
if ( ! Players . GetCountNotEliminated ( ) )
2009-08-15 18:50:32 +00:00
fDoGameOver = true ;
2009-05-08 13:28:41 +00:00
// Message
if ( fDoGameOver ) DoGameOver ( ) ;
return GameOver ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2010-03-28 17:58:21 +00:00
C4ST_NEW ( ControlRcvStat , " C4Game::Execute ReceiveControl " )
C4ST_NEW ( ControlStat , " C4Game::Execute ExecuteControl " )
C4ST_NEW ( ExecObjectsStat , " C4Game::Execute ExecObjects " )
C4ST_NEW ( GEStats , " C4Game::Execute pGlobalEffects->Execute " )
C4ST_NEW ( PXSStat , " C4Game::Execute PXS.Execute " )
C4ST_NEW ( PartStat , " C4Game::Execute Particles.Execute " )
2013-09-21 14:48:28 +00:00
C4ST_NEW ( DynPartStat , " C4Game::Execute DynamicParticles.Execute " )
2010-03-28 17:58:21 +00:00
C4ST_NEW ( MassMoverStat , " C4Game::Execute MassMover.Execute " )
C4ST_NEW ( WeatherStat , " C4Game::Execute Weather.Execute " )
C4ST_NEW ( PlayersStat , " C4Game::Execute Players.Execute " )
C4ST_NEW ( LandscapeStat , " C4Game::Execute Landscape.Execute " )
C4ST_NEW ( MusicSystemStat , " C4Game::Execute MusicSystem.Execute " )
C4ST_NEW ( MessagesStat , " C4Game::Execute Messages.Execute " )
2009-05-08 13:28:41 +00:00
# define EXEC_S(Expressions, Stat) \
2010-03-28 17:58:21 +00:00
{ C4ST_START ( Stat ) Expressions C4ST_STOP ( Stat ) }
2009-05-08 13:28:41 +00:00
2013-05-25 20:38:08 +00:00
# define EXEC_S_DR(Expressions, Stat, DebugRecName) { if (Config.General.DebugRec) AddDbgRec(RCT_Block, DebugRecName, 6); EXEC_S(Expressions, Stat) }
# define EXEC_DR(Expressions, DebugRecName) { if (Config.General.DebugRec) AddDbgRec(RCT_Block, DebugRecName, 6); Expressions }
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : Execute ( ) // Returns true if the game is over
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
2010-03-27 16:05:02 +00:00
// Let's go
GameGo = true ;
2009-05-08 13:28:41 +00:00
// Network
Network . Execute ( ) ;
// Prepare control
2009-08-15 18:50:32 +00:00
bool fControl ;
2010-03-28 17:58:21 +00:00
EXEC_S ( fControl = Control . Prepare ( ) ; , ControlStat )
if ( ! fControl ) return false ; // not ready yet: wait
2009-05-08 13:28:41 +00:00
// Halt
2009-08-15 18:50:32 +00:00
if ( HaltCount ) return false ;
2009-05-08 13:28:41 +00:00
2013-05-25 20:38:08 +00:00
if ( Config . General . DebugRec )
Landscape . DoRelights ( ) ;
2009-05-08 13:28:41 +00:00
// Execute the control
Control . Execute ( ) ;
2010-03-28 17:58:21 +00:00
if ( ! IsRunning ) return false ;
2009-05-08 13:28:41 +00:00
// Ticks
2010-03-28 17:58:21 +00:00
EXEC_DR ( Ticks ( ) ; , " Ticks " )
2009-05-08 13:28:41 +00:00
2013-05-25 20:38:08 +00:00
if ( Config . General . DebugRec )
// debugrec
AddDbgRec ( RCT_DbgFrame , & FrameCounter , sizeof ( int32_t ) ) ;
2009-05-08 13:28:41 +00:00
2013-10-07 21:37:01 +00:00
// allow the particle system to execute the next frame BEFORE the other game stuff is calculated since it will run in parallel to the main thread
DynamicParticles . CalculateNextStep ( ) ;
2009-05-08 13:28:41 +00:00
// Game
2010-03-28 17:58:21 +00:00
EXEC_S ( ExecObjects ( ) ; , ExecObjectsStat )
2009-05-08 13:28:41 +00:00
if ( pGlobalEffects )
2010-03-28 17:58:21 +00:00
EXEC_S_DR ( pGlobalEffects - > Execute ( NULL ) ; , GEStats , " GEEx \0 " ) ;
EXEC_S_DR ( PXS . Execute ( ) ; , PXSStat , " PXSEx " )
EXEC_S_DR ( Particles . GlobalParticles . Exec ( ) ; , PartStat , " ParEx " )
EXEC_S_DR ( MassMover . Execute ( ) ; , MassMoverStat , " MMvEx " )
EXEC_S_DR ( Weather . Execute ( ) ; , WeatherStat , " WtrEx " )
EXEC_S_DR ( Landscape . Execute ( ) ; , LandscapeStat , " LdsEx " )
EXEC_S_DR ( Players . Execute ( ) ; , PlayersStat , " PlrEx " )
2009-05-08 13:28:41 +00:00
//FIXME: C4Application::Execute should do this, but what about the stats?
2011-03-05 16:36:16 +00:00
EXEC_S_DR ( Application . MusicSystem . Execute ( ) ; , MusicSystemStat , " Music " )
EXEC_S_DR ( : : Messages . Execute ( ) ; , MessagesStat , " MsgEx " )
2009-05-08 13:28:41 +00:00
2010-03-28 17:58:21 +00:00
EXEC_DR ( MouseControl . Execute ( ) ; , " Input " )
2009-05-08 13:28:41 +00:00
2010-03-28 17:58:21 +00:00
EXEC_DR ( UpdateRules ( ) ;
GameOverCheck ( ) ; , " Misc \0 " )
2009-05-08 13:28:41 +00:00
Control . DoSyncCheck ( ) ;
// Evaluation; Game over dlg
if ( GameOver )
2010-03-28 17:58:21 +00:00
{
if ( ! Evaluated ) Evaluate ( ) ;
2009-05-08 13:28:41 +00:00
if ( ! GameOverDlgShown ) ShowGameOverDlg ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2010-03-27 16:05:02 +00:00
// show stat each 1000 ticks
2010-03-28 17:58:21 +00:00
if ( ! ( FrameCounter % 1000 ) )
2009-05-08 13:28:41 +00:00
{
2009-08-04 22:53:38 +00:00
C4ST_SHOWPARTSTAT ( FrameCounter )
2009-05-08 13:28:41 +00:00
C4ST_RESETPART
}
2013-05-25 20:38:08 +00:00
if ( Config . General . DebugRec )
{
AddDbgRec ( RCT_Block , " eGame " , 6 ) ;
Landscape . DoRelights ( ) ;
}
2009-05-08 13:28:41 +00:00
2010-03-27 16:05:02 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : InitFullscreenComponents ( bool fRunning )
2010-03-28 17:58:21 +00:00
{
2010-06-27 00:42:48 +00:00
// fullscreen message board
C4Facet cgo ;
cgo . Set ( FullScreen . pSurface , 0 , 0 , C4GUI : : GetScreenWdt ( ) , C4GUI : : GetScreenHgt ( ) ) ;
GraphicsSystem . MessageBoard . Init ( cgo , ! fRunning ) ;
2009-05-08 13:28:41 +00:00
if ( fRunning )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// running game: Message board upper board and viewports
C4Facet cgo2 ;
2010-03-06 14:07:30 +00:00
cgo2 . Set ( FullScreen . pSurface , 0 , 0 , C4GUI : : GetScreenWdt ( ) , C4UpperBoardHeight ) ;
2009-05-08 13:28:41 +00:00
GraphicsSystem . UpperBoard . Init ( cgo2 ) ;
2010-09-29 01:44:05 +00:00
: : Viewports . RecalculateViewports ( ) ;
2010-03-28 17:58:21 +00:00
}
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : InitMaterialTexture ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Clear old data
TextureMap . Clear ( ) ;
2009-06-05 18:46:03 +00:00
: : MaterialMap . Clear ( ) ;
2009-05-08 13:28:41 +00:00
// Check for scenario local materials
bool fHaveScenMaterials = Game . ScenarioFile . FindEntry ( C4CFN_Material ) ;
// Load all materials
C4GameRes * pMatRes = NULL ;
2009-08-15 18:50:32 +00:00
bool fFirst = true , fOverloadMaterials = true , fOverloadTextures = true ;
2009-05-08 13:28:41 +00:00
long tex_count = 0 , mat_count = 0 ;
2010-03-28 17:58:21 +00:00
while ( fOverloadMaterials | | fOverloadTextures )
{
2009-05-08 13:28:41 +00:00
// Are there any scenario local materials that need to be looked at firs?
C4Group Mats ;
2010-03-28 17:58:21 +00:00
if ( fHaveScenMaterials )
{
if ( ! Mats . OpenAsChild ( & Game . ScenarioFile , C4CFN_Material ) )
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
// Once only
fHaveScenMaterials = false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Find next external material source
pMatRes = Game . Parameters . GameRes . iterRes ( pMatRes , NRT_Material ) ;
2010-03-28 17:58:21 +00:00
if ( ! pMatRes ) break ;
2011-01-06 20:18:13 +00:00
if ( ! Reloc . Open ( Mats , pMatRes - > getFile ( ) ) )
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// First material file? Load texture map.
2009-08-15 18:50:32 +00:00
bool fNewOverloadMaterials = false , fNewOverloadTextures = false ;
2010-03-28 17:58:21 +00:00
if ( fFirst )
{
2009-05-08 13:28:41 +00:00
long tme_count = TextureMap . LoadMap ( Mats , C4CFN_TexMap , & fNewOverloadMaterials , & fNewOverloadTextures ) ;
LogF ( LoadResStr ( " IDS_PRC_TEXMAPENTRIES " ) , tme_count ) ;
// Only once
fFirst = false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Check overload-flags only
2010-03-28 17:58:21 +00:00
if ( ! C4TextureMap : : LoadFlags ( Mats , C4CFN_TexMap , & fNewOverloadMaterials , & fNewOverloadTextures ) )
2009-05-08 13:28:41 +00:00
fOverloadMaterials = fOverloadTextures = false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Load textures
2010-03-28 17:58:21 +00:00
if ( fOverloadTextures )
{
2009-05-08 13:28:41 +00:00
int iTexs = TextureMap . LoadTextures ( Mats ) ;
// Automatically continue search if no texture was found
2010-03-28 17:58:21 +00:00
if ( ! iTexs ) fNewOverloadTextures = true ;
2009-05-08 13:28:41 +00:00
tex_count + = iTexs ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Load materials
2010-03-28 17:58:21 +00:00
if ( fOverloadMaterials )
{
2009-06-05 18:46:03 +00:00
int iMats = : : MaterialMap . Load ( Mats ) ;
2009-05-08 13:28:41 +00:00
// Automatically continue search if no material was found
2010-03-28 17:58:21 +00:00
if ( ! iMats ) fNewOverloadMaterials = true ;
2009-05-08 13:28:41 +00:00
mat_count + = iMats ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Set flags
fOverloadTextures = fNewOverloadTextures ;
fOverloadMaterials = fNewOverloadMaterials ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Logs
2010-03-27 16:05:02 +00:00
LogF ( LoadResStr ( " IDS_PRC_TEXTURES " ) , tex_count ) ;
LogF ( LoadResStr ( " IDS_PRC_MATERIALS " ) , mat_count ) ;
2009-05-08 13:28:41 +00:00
// Load material enumeration
2009-06-05 18:46:03 +00:00
if ( ! : : MaterialMap . LoadEnumeration ( ScenarioFile ) )
2010-03-28 17:58:21 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_NOMATENUM " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// Initialize texture map
TextureMap . Init ( ) ;
2010-03-27 16:05:02 +00:00
// Cross map mats (after texture init, because Material-Texture-combinations are used)
2013-01-08 22:41:20 +00:00
if ( ! : : MaterialMap . CrossMapMaterials ( C4S . Landscape . Material ) ) return false ;
2009-05-08 13:28:41 +00:00
// get material script funcs
2009-06-05 18:46:03 +00:00
: : MaterialMap . UpdateScriptPointers ( ) ;
2009-05-08 13:28:41 +00:00
2010-03-27 16:05:02 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : ClearObjectPtrs ( C4Object * pObj )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// May not call Objects.ClearPointers() because that would
// remove pObj from primary list and pObj is to be kept
// until CheckObjectRemoval().
2010-03-27 16:05:02 +00:00
C4Object * cObj ; C4ObjectLink * clnk ;
for ( clnk = Objects . First ; clnk & & ( cObj = clnk - > Obj ) ; clnk = clnk - > Next )
2009-05-08 13:28:41 +00:00
cObj - > ClearPointers ( pObj ) ;
// check in inactive objects as well
2010-03-27 16:05:02 +00:00
for ( clnk = Objects . InactiveObjects . First ; clnk & & ( cObj = clnk - > Obj ) ; clnk = clnk - > Next )
2009-05-08 13:28:41 +00:00
cObj - > ClearPointers ( pObj ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2010-10-29 22:05:36 +00:00
void C4Game : : ClearPointers ( C4Object * pObj )
2010-03-28 17:58:21 +00:00
{
2012-04-13 18:28:30 +00:00
: : AulExec . ClearPointers ( pObj ) ;
2009-06-15 21:47:26 +00:00
: : Objects . ForeObjects . ClearPointers ( pObj ) ;
2009-06-05 18:12:43 +00:00
: : Messages . ClearPointers ( pObj ) ;
2010-03-27 16:05:02 +00:00
ClearObjectPtrs ( pObj ) ;
2012-04-13 18:28:30 +00:00
Application . SoundSystem . ClearPointers ( pObj ) ;
: : Players . ClearPointers ( pObj ) ;
2010-09-29 01:44:05 +00:00
: : Viewports . ClearPointers ( pObj ) ;
2012-04-13 18:28:30 +00:00
: : MessageInput . ClearPointers ( pObj ) ;
: : Console . ClearPointers ( pObj ) ;
: : MouseControl . ClearPointers ( pObj ) ;
2009-05-08 13:28:41 +00:00
TransferZones . ClearPointers ( pObj ) ;
2010-03-28 17:58:21 +00:00
if ( pGlobalEffects )
2010-03-27 16:05:02 +00:00
pGlobalEffects - > ClearPointers ( pObj ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : TogglePause ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// pause toggling disabled during round evaluation
if ( C4GameOverDlg : : IsShown ( ) ) return false ;
// otherwise, toggle
if ( IsPaused ( ) ) return Unpause ( ) ; else return Pause ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : Pause ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// already paused?
if ( IsPaused ( ) ) return false ;
// pause by net?
2010-03-28 17:58:21 +00:00
if ( : : Network . isEnabled ( ) )
{
2009-05-08 13:28:41 +00:00
// league? Vote...
2010-03-28 17:58:21 +00:00
if ( Parameters . isLeague ( ) & & ! Game . Evaluated )
{
2009-06-05 15:19:46 +00:00
: : Network . Vote ( VT_Pause , true , true ) ;
2009-05-08 13:28:41 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// host only
2010-03-28 17:58:21 +00:00
if ( ! : : Network . isHost ( ) ) return true ;
2009-06-05 15:19:46 +00:00
: : Network . Pause ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// pause game directly
Game . HaltCount = true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
Console . UpdateHaltCtrls ( IsPaused ( ) ) ;
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : Unpause ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// already paused?
if ( ! IsPaused ( ) ) return false ;
// pause by net?
2010-03-28 17:58:21 +00:00
if ( : : Network . isEnabled ( ) )
{
2009-05-08 13:28:41 +00:00
// league? Vote...
2010-03-28 17:58:21 +00:00
if ( Parameters . isLeague ( ) & & ! Game . Evaluated )
{
2009-06-05 15:19:46 +00:00
: : Network . Vote ( VT_Pause , true , false ) ;
2009-05-08 13:28:41 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// host only
2010-03-28 17:58:21 +00:00
if ( ! : : Network . isHost ( ) ) return true ;
2009-06-05 15:19:46 +00:00
: : Network . Start ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// unpause game directly
Game . HaltCount = false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
Console . UpdateHaltCtrls ( IsPaused ( ) ) ;
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : IsPaused ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// pause state defined either by network or by game halt count
2009-06-05 15:19:46 +00:00
if ( : : Network . isEnabled ( ) )
return ! : : Network . isRunning ( ) ;
2009-05-08 13:28:41 +00:00
return ! ! HaltCount ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-04-12 12:04:28 +00:00
C4Object * C4Game : : NewObject ( C4PropList * pDef , C4Object * pCreator ,
2010-03-28 17:58:21 +00:00
int32_t iOwner , C4ObjectInfo * pInfo ,
int32_t iX , int32_t iY , int32_t iR ,
2010-05-04 15:35:18 +00:00
C4Real xdir , C4Real ydir , C4Real rdir ,
2010-03-28 17:58:21 +00:00
int32_t iCon , int32_t iController )
{
2009-05-08 13:28:41 +00:00
// Safety
2010-03-27 16:05:02 +00:00
if ( ! pDef ) return NULL ;
2013-05-25 20:38:08 +00:00
if ( Config . General . DebugRec )
{
C4RCCreateObj rc ;
memset ( & rc , ' \0 ' , sizeof ( rc ) ) ;
strncpy ( rc . id , pDef - > GetName ( ) , 32 + 1 ) ;
rc . oei = C4PropListNumbered : : GetEnumerationIndex ( ) + 1 ;
rc . x = iX ; rc . y = iY ; rc . ownr = iOwner ;
AddDbgRec ( RCT_CrObj , & rc , sizeof ( rc ) ) ;
}
2009-05-08 13:28:41 +00:00
// Create object
2010-03-27 16:05:02 +00:00
C4Object * pObj ;
if ( ! ( pObj = new C4Object ) ) return NULL ;
2009-05-08 13:28:41 +00:00
// Initialize object
2010-03-28 17:58:21 +00:00
pObj - > Init ( pDef , pCreator , iOwner , pInfo , iX , iY , iR , xdir , ydir , rdir , iController ) ;
2009-05-08 13:28:41 +00:00
// Add to object list
2010-03-27 16:05:02 +00:00
if ( ! Objects . Add ( pObj ) ) { delete pObj ; return NULL ; }
2009-05-08 13:28:41 +00:00
// ---- From now on, object is ready to be used in scripts!
// Construction callback
C4AulParSet pars ( C4VObj ( pCreator ) ) ;
pObj - > Call ( PSF_Construction , & pars ) ;
// AssignRemoval called? (Con 0)
2010-03-28 17:58:21 +00:00
if ( ! pObj - > Status ) { return NULL ; }
2009-05-08 13:28:41 +00:00
// Do initial con
2011-01-02 01:03:44 +00:00
pObj - > DoCon ( iCon ) ;
2009-05-08 13:28:41 +00:00
// AssignRemoval called? (Con 0)
2010-03-28 17:58:21 +00:00
if ( ! pObj - > Status ) { return NULL ; }
2009-05-08 13:28:41 +00:00
// Success
2010-03-27 16:05:02 +00:00
return pObj ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : DeleteObjects ( bool fDeleteInactive )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// del any objects
2009-06-15 21:47:26 +00:00
: : Objects . DeleteObjects ( fDeleteInactive ) ;
2009-05-08 13:28:41 +00:00
// reset resort flag
2009-08-15 18:50:32 +00:00
fResortAnyObject = false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
C4Object * C4Game : : CreateObject ( C4ID id , C4Object * pCreator , int32_t iOwner ,
2010-03-28 17:58:21 +00:00
int32_t x , int32_t y , int32_t r ,
2010-05-04 15:35:18 +00:00
C4Real xdir , C4Real ydir , C4Real rdir , int32_t iController )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
C4Def * pDef ;
// Get pDef
if ( ! ( pDef = C4Id2Def ( id ) ) ) return NULL ;
// Create object
return NewObject ( pDef , pCreator ,
2010-03-28 17:58:21 +00:00
iOwner , NULL ,
x , y , r ,
xdir , ydir , rdir ,
FullCon , iController ) ;
}
2009-05-08 13:28:41 +00:00
2009-04-12 12:04:28 +00:00
C4Object * C4Game : : CreateObject ( C4PropList * PropList , C4Object * pCreator , int32_t iOwner ,
2010-03-28 17:58:21 +00:00
int32_t x , int32_t y , int32_t r ,
2010-05-04 15:35:18 +00:00
C4Real xdir , C4Real ydir , C4Real rdir , int32_t iController )
2010-03-28 17:58:21 +00:00
{
2010-09-08 23:18:43 +00:00
// check Definition
if ( ! PropList | | ! PropList - > GetDef ( ) ) return NULL ;
2010-03-27 16:05:02 +00:00
// Create object
2010-09-08 23:18:43 +00:00
return NewObject ( PropList , pCreator ,
2010-03-28 17:58:21 +00:00
iOwner , NULL ,
x , y , r ,
xdir , ydir , rdir ,
FullCon , iController ) ;
}
2009-04-12 12:04:28 +00:00
2009-08-26 12:17:41 +00:00
C4Object * C4Game : : CreateInfoObject ( C4ObjectInfo * cinf , int32_t iOwner ,
2010-03-28 17:58:21 +00:00
int32_t tx , int32_t ty )
{
2010-03-27 16:05:02 +00:00
C4Def * def ;
// Valid check
if ( ! cinf ) return NULL ;
// Get def
if ( ! ( def = C4Id2Def ( cinf - > id ) ) ) return NULL ;
// Create object
return NewObject ( def , NULL ,
2010-03-28 17:58:21 +00:00
iOwner , cinf ,
tx , ty , 0 ,
Fix0 , Fix0 , Fix0 ,
FullCon , NO_OWNER ) ;
}
2009-05-08 13:28:41 +00:00
2009-04-12 12:04:28 +00:00
C4Object * C4Game : : CreateObjectConstruction ( C4PropList * PropList ,
2010-03-28 17:58:21 +00:00
C4Object * pCreator ,
int32_t iOwner ,
int32_t iX , int32_t iBY ,
int32_t iCon ,
bool fTerrain )
{
2010-03-27 16:05:02 +00:00
C4Def * pDef ;
C4Object * pObj ;
// Get def
if ( ! PropList ) return NULL ;
if ( ! ( pDef = PropList - > GetDef ( ) ) ) return NULL ;
int32_t dx , dy , dwdt , dhgt ;
dwdt = pDef - > Shape . Wdt ; dhgt = pDef - > Shape . Hgt ;
dx = iX - dwdt / 2 ; dy = iBY - dhgt ;
// Terrain
if ( fTerrain )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
// Clear site background (ignored for ultra-large structures)
2009-05-08 13:28:41 +00:00
if ( dwdt * dhgt < 12000 )
Landscape . DigFreeRect ( dx , dy , dwdt , dhgt ) ;
2010-03-27 16:05:02 +00:00
// Raise Terrain
Landscape . RaiseTerrain ( dx , dy + dhgt , dwdt ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2010-03-27 16:05:02 +00:00
// Create object
2010-09-08 23:18:43 +00:00
if ( ! ( pObj = NewObject ( PropList ,
2009-05-08 13:28:41 +00:00
pCreator ,
2010-03-28 17:58:21 +00:00
iOwner , NULL ,
iX , iBY , 0 ,
Fix0 , Fix0 , Fix0 ,
iCon , pCreator ? pCreator - > Controller : NO_OWNER ) ) ) return NULL ;
2009-05-08 13:28:41 +00:00
2010-03-27 16:05:02 +00:00
return pObj ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2010-12-27 19:15:55 +00:00
C4Object * C4Game : : OverlapObject ( int32_t tx , int32_t ty , int32_t wdt , int32_t hgt , int32_t Plane )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
C4Object * cObj ; C4ObjectLink * clnk ;
C4Rect rect1 , rect2 ;
rect1 . x = tx ; rect1 . y = ty ; rect1 . Wdt = wdt ; rect1 . Hgt = hgt ;
2009-06-15 21:47:26 +00:00
C4LArea Area ( & : : Objects . Sectors , tx , ty , wdt , hgt ) ; C4LSector * pSector ;
2009-05-08 13:28:41 +00:00
for ( C4ObjectList * pObjs = Area . FirstObjectShapes ( & pSector ) ; pSector ; pObjs = Area . NextObjectShapes ( pObjs , & pSector ) )
for ( clnk = pObjs - > First ; clnk & & ( cObj = clnk - > Obj ) ; clnk = clnk - > Next )
2010-12-27 19:15:55 +00:00
if ( cObj - > Status & & ! cObj - > Contained )
if ( cObj - > GetPlane ( ) = = Plane )
{
rect2 = cObj - > Shape ; rect2 . x + = cObj - > GetX ( ) ; rect2 . y + = cObj - > GetY ( ) ;
if ( rect1 . Overlap ( rect2 ) ) return cObj ;
}
2010-03-27 16:05:02 +00:00
return NULL ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
C4Object * C4Game : : FindObject ( C4ID id ,
2010-03-28 17:58:21 +00:00
int32_t iX , int32_t iY , int32_t iWdt , int32_t iHgt ,
DWORD ocf ,
C4Object * pFindNext )
{
2009-05-08 13:28:41 +00:00
C4Object * pClosest = NULL ;
int32_t iClosest = 0 , iDistance , iFartherThan = - 1 ;
C4Object * cObj ;
C4ObjectLink * cLnk ;
C4Def * pDef ;
C4Object * pFindNextCpy = pFindNext ;
// check the easy cases first
2010-01-25 03:14:52 +00:00
if ( id ! = C4ID : : None )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! ( pDef = C4Id2Def ( id ) ) ) return NULL ; // no valid def
if ( ! pDef - > Count ) return NULL ; // no instances at all
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Finding next closest: find closest but further away than last closest
if ( pFindNext & & ( iWdt = = - 1 ) & & ( iHgt = = - 1 ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
iFartherThan = ( pFindNext - > GetX ( ) - iX ) * ( pFindNext - > GetX ( ) - iX ) + ( pFindNext - > GetY ( ) - iY ) * ( pFindNext - > GetY ( ) - iY ) ;
pFindNext = NULL ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Scan all objects
for ( cLnk = Objects . First ; cLnk & & ( cObj = cLnk - > Obj ) ; cLnk = cLnk - > Next )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Not skipping to find next
if ( ! pFindNext )
2010-03-28 17:58:21 +00:00
// Status
if ( cObj - > Status )
// ID
if ( ( id = = C4ID : : None ) | | ( cObj - > Def - > id = = id ) )
// OCF (match any specified)
if ( cObj - > OCF & ocf )
2012-04-15 21:32:37 +00:00
// Area
{
// Point
if ( ( iWdt = = 0 ) & & ( iHgt = = 0 ) )
{
if ( Inside < int32_t > ( iX - ( cObj - > GetX ( ) + cObj - > Shape . x ) , 0 , cObj - > Shape . Wdt - 1 ) )
if ( Inside < int32_t > ( iY - ( cObj - > GetY ( ) + cObj - > Shape . y ) , 0 , cObj - > Shape . Hgt - 1 ) )
return cObj ;
continue ;
}
// Closest
if ( ( iWdt = = - 1 ) & & ( iHgt = = - 1 ) )
{
iDistance = ( cObj - > GetX ( ) - iX ) * ( cObj - > GetX ( ) - iX ) + ( cObj - > GetY ( ) - iY ) * ( cObj - > GetY ( ) - iY ) ;
// same distance?
if ( ( iDistance = = iFartherThan ) & & ! pFindNextCpy )
return cObj ;
// nearer than/first closest?
if ( ! pClosest | | ( iDistance < iClosest ) )
if ( iDistance > iFartherThan )
{ pClosest = cObj ; iClosest = iDistance ; }
}
// Range
else if ( Inside < int32_t > ( cObj - > GetX ( ) - iX , 0 , iWdt - 1 ) & & Inside < int32_t > ( cObj - > GetY ( ) - iY , 0 , iHgt - 1 ) )
return cObj ;
}
2009-05-08 13:28:41 +00:00
// Find next mark reached
if ( cObj = = pFindNextCpy ) pFindNext = pFindNextCpy = NULL ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
return pClosest ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-10-16 21:07:43 +00:00
C4Object * C4Game : : FindVisObject ( float tx , float ty , int32_t iPlr , const C4Facet & fctViewportGame , const C4Facet & fctViewportGUI ,
2010-03-28 17:58:21 +00:00
float game_x , float game_y , DWORD category , float gui_x , float gui_y )
2009-10-16 21:07:43 +00:00
{
2009-05-08 13:28:41 +00:00
// FIXME: Use C4FindObject here for optimization
2009-10-16 21:07:43 +00:00
// -- can't really do that, since sectors ignore parallaxity, etc.
// determine layer to search in
C4Object * layer_object = NULL ;
C4Player * plr = : : Players . Get ( iPlr ) ;
2010-03-30 21:08:15 +00:00
if ( plr & & plr - > Cursor ) layer_object = plr - > Cursor - > Layer ;
2010-04-01 21:08:06 +00:00
// scan all object lists separately
2009-10-16 21:07:43 +00:00
C4ObjectList * pLst = & : : Objects . ForeObjects ;
2009-05-08 13:28:41 +00:00
while ( pLst )
2009-10-16 21:07:43 +00:00
{
2009-05-08 13:28:41 +00:00
// Scan all objects in list
2009-10-16 21:07:43 +00:00
C4ObjectLink * cLnk ; C4Object * cObj ;
2009-10-17 15:53:26 +00:00
for ( cLnk = pLst - > First ; cLnk & & ( cObj = cLnk - > Obj ) ; cLnk = cLnk - > Next )
2009-10-16 21:07:43 +00:00
{
2009-05-08 13:28:41 +00:00
// Status
if ( cObj - > Status = = C4OS_NORMAL )
2011-12-29 14:56:51 +00:00
// exclude fore-objects from main list
if ( ( pLst ! = & Objects ) | | ( ~ cObj - > Category & C4D_Foreground ) )
2010-03-28 17:58:21 +00:00
// exclude MouseIgnore-objects
if ( ~ cObj - > Category & C4D_MouseIgnore )
// Category (match any specified)
if ( cObj - > Category & category )
// Container
if ( ! cObj - > Contained )
// Visibility
if ( cObj - > IsVisible ( iPlr , false ) )
// Layer check: Layered objects are invisible to players whose cursor is in another layer
// except for GUI: GUI always visible
{
2010-03-30 21:08:15 +00:00
if ( cObj - > Layer ! = layer_object )
2010-03-28 17:58:21 +00:00
if ( pLst ! = & : : Objects . ForeObjects )
continue ;
// Area
// get object position
float iObjX , iObjY , check_x , check_y ;
if ( pLst = = & : : Objects . ForeObjects )
{
// object position for HUD object
check_x = gui_x ; check_y = gui_y ;
cObj - > GetViewPos ( iObjX , iObjY , - fctViewportGUI . X , - fctViewportGUI . Y , fctViewportGUI ) ;
}
else
{
// object position for game object
check_x = game_x ; check_y = game_y ;
cObj - > GetViewPos ( iObjX , iObjY , tx , ty , fctViewportGame ) ;
}
// Point search
if ( Inside < float > ( check_x - ( iObjX + cObj - > Shape . x ) , 0 , float ( cObj - > Shape . Wdt ) - 1 ) )
if ( Inside < float > ( check_y - ( iObjY + cObj - > Shape . y - cObj - > addtop ( ) ) , 0 , float ( cObj - > Shape . Hgt + cObj - > addtop ( ) - 1 ) ) )
return cObj ;
}
2009-10-16 21:07:43 +00:00
}
2009-05-08 13:28:41 +00:00
// next list
2009-06-15 21:47:26 +00:00
if ( pLst = = & : : Objects . ForeObjects ) pLst = & Objects ;
2009-05-08 13:28:41 +00:00
else pLst = NULL ;
2009-10-16 21:07:43 +00:00
}
2009-05-08 13:28:41 +00:00
// none found
return NULL ;
2009-10-16 21:07:43 +00:00
}
2009-09-03 20:27:23 +00:00
int32_t C4Game : : ObjectCount ( C4ID id )
2010-03-28 17:58:21 +00:00
{
2009-09-03 20:27:23 +00:00
C4Def * pDef ;
// check the easy cases first
2010-01-25 03:14:52 +00:00
if ( id ! = C4ID : : None )
2010-03-28 17:58:21 +00:00
{
2009-09-03 20:27:23 +00:00
if ( ! ( pDef = C4Id2Def ( id ) ) ) return 0 ; // no valid def
return pDef - > Count ;
2010-03-28 17:58:21 +00:00
}
2009-09-03 20:27:23 +00:00
C4Object * cObj ;
C4ObjectLink * clnk ;
int32_t iResult = 0 ;
for ( clnk = Objects . First ; clnk & & ( cObj = clnk - > Obj ) ; clnk = clnk - > Next )
// Status
if ( cObj - > Status )
+ + iResult ;
return iResult ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Deletes removal-assigned data from list.
// Pointer clearance is done by AssignRemoval.
2009-06-12 18:52:21 +00:00
void C4Game : : ObjectRemovalCheck ( ) // Every ::Game.iTick255 by ExecObjects
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
C4Object * cObj ; C4ObjectLink * clnk , * next ;
for ( clnk = Objects . First ; clnk & & ( cObj = clnk - > Obj ) ; clnk = next )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
next = clnk - > Next ;
if ( ! cObj - > Status & & ( cObj - > RemovalDelay = = 0 ) )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
Objects . Remove ( cObj ) ;
delete cObj ;
}
}
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : ExecObjects ( ) // Every Tick1 by Execute
2010-03-28 17:58:21 +00:00
{
2013-05-25 20:38:08 +00:00
if ( Config . General . DebugRec )
AddDbgRec ( RCT_Block , " ObjEx " , 6 ) ;
2009-05-08 13:28:41 +00:00
// Execute objects - reverse order to ensure
2010-03-27 16:05:02 +00:00
C4Object * cObj ; C4ObjectLink * clnk ;
for ( clnk = Objects . Last ; clnk & & ( cObj = clnk - > Obj ) ; clnk = clnk - > Prev )
if ( cObj - > Status )
2009-05-08 13:28:41 +00:00
// Execute object
2010-03-27 16:05:02 +00:00
cObj - > Execute ( ) ;
else
2009-05-08 13:28:41 +00:00
// Status reset: process removal delay
2010-03-27 16:05:02 +00:00
if ( cObj - > RemovalDelay > 0 ) cObj - > RemovalDelay - - ;
2009-05-08 13:28:41 +00:00
2013-05-25 20:38:08 +00:00
if ( Config . General . DebugRec )
AddDbgRec ( RCT_Block , " ObjCC " , 6 ) ;
2009-05-08 13:28:41 +00:00
// Cross check objects
2010-03-27 16:05:02 +00:00
Objects . CrossCheck ( ) ;
2009-05-08 13:28:41 +00:00
2013-05-25 20:38:08 +00:00
if ( Config . General . DebugRec )
AddDbgRec ( RCT_Block , " ObjRs " , 6 ) ;
2009-05-08 13:28:41 +00:00
// Resort
2010-03-27 16:05:02 +00:00
if ( fResortAnyObject )
2010-03-28 17:58:21 +00:00
{
2009-08-15 18:50:32 +00:00
fResortAnyObject = false ;
2009-05-08 13:28:41 +00:00
Objects . ResortUnsorted ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2013-05-25 20:38:08 +00:00
if ( Config . General . DebugRec )
AddDbgRec ( RCT_Block , " ObjRm " , 6 ) ;
2009-05-08 13:28:41 +00:00
// Removal
2010-03-27 16:05:02 +00:00
if ( ! : : Game . iTick255 ) ObjectRemovalCheck ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
C4ID DefFileGetID ( const char * szFilename )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
C4Group hDef ;
2009-05-19 22:34:13 +00:00
C4Def DefCore ;
2010-01-25 03:14:52 +00:00
if ( ! hDef . Open ( szFilename ) ) return C4ID : : None ;
if ( ! DefCore . LoadDefCore ( hDef ) ) { hDef . Close ( ) ; return C4ID : : None ; }
2009-05-08 13:28:41 +00:00
hDef . Close ( ) ;
return DefCore . id ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : DropFile ( const char * szFilename , float iX , float iY )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
C4ID c_id ; C4Def * cdef ;
// Drop def to create object
2011-03-13 15:55:00 +00:00
if ( SEqualNoCase ( GetExtension ( szFilename ) , " ocd " ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Get id from file
2010-01-25 04:00:59 +00:00
if ( ( c_id = DefFileGetID ( szFilename ) ) )
2009-05-08 13:28:41 +00:00
// Get loaded def or try to load def from file
if ( ( cdef = C4Id2Def ( c_id ) )
2010-03-28 17:58:21 +00:00
| | ( : : Definitions . Load ( szFilename , C4D_Load_RX , Config . General . LanguageEx , & Application . SoundSystem ) & & ( cdef = C4Id2Def ( c_id ) ) ) )
{
2009-05-08 13:28:41 +00:00
return DropDef ( c_id , iX , iY ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Failure
2009-05-11 13:09:53 +00:00
Console . Out ( FormatString ( LoadResStr ( " IDS_CNS_DROPNODEF " ) , GetFilename ( szFilename ) ) . getData ( ) ) ;
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 17:58:21 +00:00
return false ;
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : DropDef ( C4ID id , float X , float Y )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Get def
C4Def * pDef ;
2010-01-25 04:00:59 +00:00
if ( ( pDef = C4Id2Def ( id ) ) )
2010-03-28 17:58:21 +00:00
{
2013-09-04 14:53:04 +00:00
: : Control . DoInput ( CID_EMMoveObj , C4ControlEMMoveObject : : CreateObject ( id , ftofix ( X ) , ftofix ( Y ) ) , CDT_Decide ) ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-11 13:09:53 +00:00
else
2010-03-28 17:58:21 +00:00
{
2009-05-11 13:09:53 +00:00
// Failure
2010-01-25 15:57:57 +00:00
Console . Out ( FormatString ( LoadResStr ( " IDS_CNS_DROPNODEF " ) , id . ToString ( ) ) . getData ( ) ) ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 17:58:21 +00:00
return false ;
}
2009-05-08 13:28:41 +00:00
2010-03-28 17:58:21 +00:00
void C4Game : : CastObjects ( C4ID id , C4Object * pCreator , int32_t num , int32_t level , int32_t tx , int32_t ty , int32_t iOwner , int32_t iController )
{
2009-05-08 13:28:41 +00:00
int32_t cnt ;
2010-03-28 17:58:21 +00:00
for ( cnt = 0 ; cnt < num ; cnt + + )
{
2012-10-14 19:02:27 +00:00
// Must do these calculation steps separately, because the order of
// invokations of Random() is not defined if they're used as parameters
int32_t angle = Random ( 360 ) ;
C4Real xdir = C4REAL10 ( Random ( 2 * level + 1 ) - level ) ;
C4Real ydir = C4REAL10 ( Random ( 2 * level + 1 ) - level ) ;
C4Real rdir = itofix ( Random ( 3 ) + 1 ) ;
2009-05-08 13:28:41 +00:00
CreateObject ( id , pCreator , iOwner ,
2012-10-14 19:02:27 +00:00
tx , ty , angle ,
xdir ,
ydir ,
rdir , iController ) ;
2009-05-08 13:28:41 +00:00
}
}
void C4GameSec1Timer : : OnSec1Timer ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// updates the game clock
2010-03-28 17:58:21 +00:00
if ( Game . TimeGo ) { Game . Time + + ; Game . TimeGo = false ; }
2009-05-08 13:28:41 +00:00
Game . FPS = Game . cFPS ; Game . cFPS = 0 ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : Default ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
PointersDenumerated = false ;
2009-08-15 18:50:32 +00:00
IsRunning = false ;
2009-05-08 13:28:41 +00:00
FrameCounter = 0 ;
2009-08-15 18:50:32 +00:00
GameOver = GameOverDlgShown = false ;
2009-05-08 13:28:41 +00:00
ScenarioFilename [ 0 ] = 0 ;
PlayerFilenames [ 0 ] = 0 ;
DefinitionFilenames [ 0 ] = 0 ;
DirectJoinAddress [ 0 ] = 0 ;
pJoinReference = NULL ;
StartupPlayerCount = 0 ;
2010-06-28 23:02:14 +00:00
ScenarioTitle . Ref ( " " ) ;
2009-05-08 13:28:41 +00:00
HaltCount = 0 ;
2009-08-15 18:50:32 +00:00
fReferenceDefinitionOverride = false ;
Evaluated = false ;
2009-05-08 13:28:41 +00:00
TimeGo = false ;
Time = 0 ;
StartTime = 0 ;
InitProgress = 0 ; LastInitProgress = 0 ; LastInitProgressShowTime = 0 ;
FPS = cFPS = 0 ;
2009-08-15 18:50:32 +00:00
fScriptCreatedObjects = false ;
fLobby = fObserve = false ;
2009-05-08 13:28:41 +00:00
iLobbyTimeout = 0 ;
2009-06-12 18:52:21 +00:00
iTick2 = iTick3 = iTick5 = iTick10 = iTick35 = iTick255 = iTick1000 = 0 ;
2009-08-15 18:50:32 +00:00
FullSpeed = false ;
2009-05-08 13:28:41 +00:00
FrameSkip = 1 ; DoSkipFrame = false ;
2010-03-27 16:05:02 +00:00
: : Definitions . Default ( ) ;
: : MaterialMap . Default ( ) ;
Objects . Default ( ) ;
2009-05-08 13:28:41 +00:00
Players . Default ( ) ;
2010-03-27 16:05:02 +00:00
Weather . Default ( ) ;
Landscape . Default ( ) ;
TextureMap . Default ( ) ;
2009-06-05 15:13:33 +00:00
: : DefaultRanks . Default ( ) ;
2010-03-27 16:05:02 +00:00
MassMover . Default ( ) ;
2009-05-08 13:28:41 +00:00
PXS . Default ( ) ;
GraphicsSystem . Default ( ) ;
2010-03-27 16:05:02 +00:00
C4S . Default ( ) ;
2009-06-05 18:12:43 +00:00
: : Messages . Default ( ) ;
2009-05-08 13:28:41 +00:00
MessageInput . Default ( ) ;
2010-12-07 22:43:00 +00:00
//GraphicsResource.Default();
2009-06-30 20:55:06 +00:00
//Control.Default();
2009-05-08 13:28:41 +00:00
MouseControl . Default ( ) ;
PathFinder . Default ( ) ;
TransferZones . Default ( ) ;
GroupSet . Default ( ) ;
pParentGroup = NULL ;
pScenarioSections = pCurrentScenarioSection = NULL ;
* CurrentScenarioSection = 0 ;
pGlobalEffects = NULL ;
2009-08-15 18:50:32 +00:00
fResortAnyObject = false ;
2009-05-08 13:28:41 +00:00
pNetworkStatistics = NULL ;
iMusicLevel = 100 ;
PlayList . Clear ( ) ;
2009-04-21 21:44:56 +00:00
DebugPort = 0 ;
DebugPassword . Clear ( ) ;
DebugHost . Clear ( ) ;
DebugWait = false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : Evaluate ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// League game?
bool fLeague = Network . isEnabled ( ) & & Network . isHost ( ) & & Parameters . isLeague ( ) ;
// Stop record
StdStrBuf RecordName ; BYTE RecordSHA [ SHA_DIGEST_LENGTH ] ;
2010-03-28 17:58:21 +00:00
if ( Control . isRecord ( ) )
2009-05-08 13:28:41 +00:00
Control . StopRecord ( & RecordName , fLeague ? RecordSHA : NULL ) ;
// Send league result
2010-03-28 17:58:21 +00:00
if ( fLeague )
2009-05-08 13:28:41 +00:00
Network . LeagueGameEvaluate ( RecordName . getData ( ) , RecordSHA ) ;
2010-03-27 16:05:02 +00:00
// Players
2009-05-08 13:28:41 +00:00
// saving local players only, because remote players will probably not rejoin after evaluation anyway)
Players . Evaluate ( ) ;
Players . Save ( true ) ;
// Round results
RoundResults . EvaluateGame ( ) ;
// Set game flag
Log ( LoadResStr ( " IDS_PRC_EVALUATED " ) ) ;
2009-08-15 18:50:32 +00:00
Evaluated = true ;
2009-05-08 13:28:41 +00:00
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : DrawCursors ( C4TargetFacet & cgo , int32_t iPlayer )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Draw cursor mark arrow & cursor object name
2010-03-27 16:05:02 +00:00
float cox , coy ;
int32_t cphase ;
C4Object * cursor ;
2009-05-08 13:28:41 +00:00
C4Facet & fctCursor = GraphicsResource . fctCursor ;
for ( C4Player * pPlr = Players . First ; pPlr ; pPlr = pPlr - > Next )
if ( pPlr - > Number = = iPlayer | | iPlayer = = NO_OWNER )
2010-07-30 20:38:21 +00:00
if ( pPlr - > CursorFlash )
2009-05-08 13:28:41 +00:00
if ( pPlr - > Cursor )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
cursor = pPlr - > Cursor ;
cox = cursor - > GetX ( ) - fctCursor . Wdt / 2 - cgo . TargetX ;
coy = cursor - > GetY ( ) - cursor - > Def - > Shape . Hgt / 2 - fctCursor . Hgt - cgo . TargetY ;
if ( Inside < int32_t > ( int32_t ( cox ) , 1 - fctCursor . Wdt , cgo . Wdt ) & & Inside < int32_t > ( int32_t ( coy ) , 1 - fctCursor . Hgt , cgo . Hgt ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
cphase = 0 ; if ( cursor - > Contained ) cphase = 1 ;
fctCursor . Draw ( cgo . Surface , cgo . X + cox , cgo . Y + coy , cphase ) ;
if ( cursor - > Info )
2010-03-28 17:58:21 +00:00
{
2013-10-18 16:49:21 +00:00
int32_t texthgt = : : GraphicsResource . FontRegular . GetLineHeight ( ) ;
2009-05-11 13:09:53 +00:00
StdStrBuf str ;
2009-05-08 13:28:41 +00:00
if ( cursor - > Info - > Rank > 0 )
2010-03-28 17:58:21 +00:00
{
2009-05-11 13:09:53 +00:00
str . Format ( " %s|%s " , cursor - > Info - > sRankName . getData ( ) , cursor - > GetName ( ) ) ;
2009-05-08 13:28:41 +00:00
texthgt + = texthgt ;
2010-03-28 17:58:21 +00:00
}
2009-05-11 13:09:53 +00:00
else str = cursor - > GetName ( ) ;
2009-05-08 13:28:41 +00:00
2011-10-03 14:30:18 +00:00
pDraw - > TextOut ( str . getData ( ) , : : GraphicsResource . FontRegular , 1.0 , cgo . Surface ,
2010-03-28 17:58:21 +00:00
cgo . X + cox + fctCursor . Wdt / 2 ,
cgo . Y + coy - 2 - texthgt ,
0xffff0000 , ACenter ) ;
2009-05-08 13:28:41 +00:00
}
}
2010-03-28 17:58:21 +00:00
}
}
2009-05-08 13:28:41 +00:00
void C4Game : : Ticks ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Frames
FrameCounter + + ; GameGo = FullSpeed ;
// Ticks
if ( + + iTick2 = = 2 ) iTick2 = 0 ;
if ( + + iTick3 = = 3 ) iTick3 = 0 ;
if ( + + iTick5 = = 5 ) iTick5 = 0 ;
if ( + + iTick10 = = 10 ) iTick10 = 0 ;
if ( + + iTick35 = = 35 ) iTick35 = 0 ;
if ( + + iTick255 = = 255 ) iTick255 = 0 ;
if ( + + iTick1000 = = 1000 ) iTick1000 = 0 ;
// FPS / time
cFPS + + ; TimeGo = true ;
// Frame skip
if ( FrameCounter % FrameSkip ) DoSkipFrame = true ;
// Control
Control . Ticks ( ) ;
2010-03-27 16:05:02 +00:00
// Full speed
2010-03-28 17:58:21 +00:00
if ( GameGo ) Application . NextTick ( ) ; // short-circuit the timer
2009-05-08 13:28:41 +00:00
// statistics
if ( pNetworkStatistics ) pNetworkStatistics - > ExecuteFrame ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2011-03-26 22:59:35 +00:00
void C4Game : : CompileFunc ( StdCompiler * pComp , CompileSettings comp , C4ValueNumbers * numbers )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! comp . fScenarioSection & & comp . fExact )
2010-03-28 17:58:21 +00:00
{
2009-06-16 00:38:39 +00:00
pComp - > Name ( " Game " ) ;
2009-05-08 13:28:41 +00:00
pComp - > Value ( mkNamingAdapt ( Time , " Time " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( FrameCounter , " Frame " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( Control . ControlTick , " ControlTick " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( Control . SyncRate , " SyncRate " , C4SyncCheckRate ) ) ;
pComp - > Value ( mkNamingAdapt ( iTick2 , " Tick2 " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( iTick3 , " Tick3 " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( iTick5 , " Tick5 " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( iTick10 , " Tick10 " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( iTick35 , " Tick35 " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( iTick255 , " Tick255 " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( iTick1000 , " Tick1000 " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( StartupPlayerCount , " StartupPlayerCount " , 0 ) ) ;
2011-03-05 02:32:51 +00:00
pComp - > Value ( mkNamingAdapt ( C4PropListNumbered : : EnumerationIndex , " ObjectEnumerationIndex " , 0 ) ) ;
2009-05-08 13:28:41 +00:00
pComp - > Value ( mkNamingAdapt ( Rules , " Rules " , 0 ) ) ;
pComp - > Value ( mkNamingAdapt ( PlayList , " PlayList " , " " ) ) ;
pComp - > Value ( mkNamingAdapt ( mkStringAdaptMA ( CurrentScenarioSection ) , " CurrentScenarioSection " , " " ) ) ;
pComp - > Value ( mkNamingAdapt ( fResortAnyObject , " ResortAnyObj " , false ) ) ;
pComp - > Value ( mkNamingAdapt ( iMusicLevel , " MusicLevel " , 100 ) ) ;
pComp - > Value ( mkNamingAdapt ( NextMission , " NextMission " , StdCopyStrBuf ( ) ) ) ;
pComp - > Value ( mkNamingAdapt ( NextMissionText , " NextMissionText " , StdCopyStrBuf ( ) ) ) ;
pComp - > Value ( mkNamingAdapt ( NextMissionDesc , " NextMissionDesc " , StdCopyStrBuf ( ) ) ) ;
2010-03-27 16:05:02 +00:00
pComp - > NameEnd ( ) ;
2011-09-19 19:48:14 +00:00
// scoreboard compiles into main level [Scoreboard]
pComp - > Value ( mkNamingAdapt ( Scoreboard , " Scoreboard " ) ) ;
// Keyboard status of global keys synchronized for exact (runtime join) only; not for savegames,
// as keys might be released between a savegame save and its resume
//pComp->Value(GlobalPlayerControl);
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
if ( comp . fExact )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
pComp - > Value ( mkNamingAdapt ( Weather , " Weather " ) ) ;
2009-06-16 00:38:39 +00:00
pComp - > Value ( mkNamingAdapt ( Landscape , " Landscape " ) ) ;
pComp - > Value ( mkNamingAdapt ( Landscape . Sky , " Sky " ) ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
if ( comp . fPlayers )
2010-03-28 17:58:21 +00:00
{
2009-06-16 00:38:39 +00:00
assert ( pComp - > isDecompiler ( ) ) ;
2009-05-08 13:28:41 +00:00
// player parsing: Parse all players
// This doesn't create any players, but just parses existing by their ID
// Primary player ininitialization (also setting ID) is done by player info list
// Won't work this way for binary mode!
for ( C4Player * pPlr = Players . First ; pPlr ; pPlr = pPlr - > Next )
2011-03-26 22:59:35 +00:00
pComp - > Value ( mkNamingAdapt ( mkParAdapt ( * pPlr , numbers ) , FormatString ( " Player%d " , pPlr - > ID ) . getData ( ) ) ) ;
2009-05-08 13:28:41 +00:00
}
2011-03-27 14:51:14 +00:00
pComp - > Value ( mkParAdapt ( Objects , ! comp . fExact , numbers ) ) ;
pComp - > Name ( " Script " ) ;
if ( ! comp . fScenarioSection )
{
pComp - > Value ( mkParAdapt ( ScriptEngine , numbers ) ) ;
}
2011-09-19 19:48:14 +00:00
pComp - > Value ( mkParAdapt ( mkNamingPtrAdapt ( pGlobalEffects , " Effects " ) , numbers ) ) ;
2011-03-27 16:14:41 +00:00
pComp - > Value ( mkNamingAdapt ( * numbers , " Values " ) ) ;
2011-03-27 14:51:14 +00:00
pComp - > NameEnd ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2011-09-19 19:00:55 +00:00
bool C4Game : : CompileRuntimeData ( C4Group & hGroup , bool fLoadSection , bool exact , C4ValueNumbers * numbers )
2010-03-28 17:58:21 +00:00
{
2011-03-27 14:51:14 +00:00
: : Objects . Clear ( ! fLoadSection ) ;
GameText . Load ( hGroup , C4CFN_Game ) ;
2011-07-17 19:23:32 +00:00
CompileSettings Settings ( fLoadSection , false , exact ) ;
2011-03-27 14:51:14 +00:00
// C4Game is not defaulted on compilation.
// Loading of runtime data overrides only certain values.
// Doesn't compile players; those will be done later
if ( GameText . GetData ( ) )
{
if ( ! CompileFromBuf_LogWarn < StdCompilerINIRead > (
mkParAdapt ( * this , Settings , numbers ) ,
GameText . GetDataBuf ( ) , C4CFN_Game ) )
return false ;
// Objects
int32_t iObjects = Objects . PostLoad ( fLoadSection , numbers ) ;
if ( iObjects ) { LogF ( LoadResStr ( " IDS_PRC_OBJECTSLOADED " ) , iObjects ) ; }
}
2009-05-08 13:28:41 +00:00
// Music System: Set play list
2011-03-27 14:51:14 +00:00
if ( ! fLoadSection ) Application . MusicSystem . SetPlayList ( PlayList . getData ( ) ) ;
2009-05-08 13:28:41 +00:00
// Success
2010-03-27 16:05:02 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2011-09-19 19:00:55 +00:00
bool C4Game : : SaveData ( C4Group & hGroup , bool fSaveSection , bool fSaveExact , C4ValueNumbers * numbers )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
StdStrBuf Buf ;
2011-05-01 11:50:37 +00:00
// Decompile (without players for scenario sections)
2012-02-13 23:17:07 +00:00
DecompileToBuf_Log < StdCompilerINIWrite > ( mkParAdapt ( * this , CompileSettings ( fSaveSection , ! fSaveSection & & fSaveExact , fSaveExact ) , numbers ) , & Buf , " Game " ) ;
2009-05-08 13:28:41 +00:00
// Empty? All default; just remove from group then
if ( ! Buf . getLength ( ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
hGroup . Delete ( C4CFN_Game ) ;
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Save
2009-08-15 18:50:32 +00:00
return hGroup . Add ( C4CFN_Game , Buf , false , true ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : SaveGameTitle ( C4Group & hGroup )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Game not running
if ( ! FrameCounter )
2010-03-28 17:58:21 +00:00
{
2013-05-25 18:47:17 +00:00
char * bpBytes ;
size_t iSize ;
StdStrBuf realFilename ;
if ( ScenarioFile . FindEntry ( FormatString ( " %s.* " , C4CFN_ScenarioTitle ) . getData ( ) , & realFilename , & iSize ) )
if ( ScenarioFile . LoadEntry ( realFilename . getData ( ) , & bpBytes , & iSize ) )
hGroup . Add ( realFilename . getData ( ) , bpBytes , iSize , false , true ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Fullscreen screenshot
2010-09-28 18:16:33 +00:00
else if ( ! Application . isEditor & & Application . Active )
2010-03-28 17:58:21 +00:00
{
2011-10-03 14:06:41 +00:00
C4Surface * sfcPic ; int32_t iSfcWdt = 200 , iSfcHgt = 150 ;
if ( ! ( sfcPic = new C4Surface ( iSfcWdt , iSfcHgt ) ) ) return false ;
2009-05-08 13:28:41 +00:00
// Fullscreen
2011-10-03 14:30:18 +00:00
pDraw - > Blit ( FullScreen . pSurface ,
2013-10-18 16:49:21 +00:00
0.0f , 0.0f , float ( C4GUI : : GetScreenWdt ( ) ) , float ( C4GUI : : GetScreenHgt ( ) - : : GraphicsResource . FontRegular . GetLineHeight ( ) ) ,
2010-03-28 17:58:21 +00:00
sfcPic , 0 , 0 , iSfcWdt , iSfcHgt ) ;
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool fOkay = true ;
2009-05-08 13:28:41 +00:00
fOkay = sfcPic - > SavePNG ( Config . AtTempPath ( C4CFN_TempTitle ) , false , true , false ) ;
2013-05-25 18:47:17 +00:00
StdStrBuf destFilename = FormatString ( " %s.png " , C4CFN_ScenarioTitle ) ;
2009-08-15 18:50:32 +00:00
delete sfcPic ; if ( ! fOkay ) return false ;
2013-05-25 18:47:17 +00:00
if ( ! hGroup . Move ( Config . AtTempPath ( C4CFN_TempTitle ) , destFilename . getData ( ) ) ) return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2010-02-23 16:53:38 +00:00
bool C4Game : : DoKeyboardInput ( C4KeyCode vk_code , C4KeyEventType eEventType , bool fAlt , bool fCtrl , bool fShift , bool fRepeated , class C4GUI : : Dialog * pForDialog , bool fPlrCtrlOnly , int32_t iStrength )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
# ifdef USE_X11
static std : : map < C4KeyCode , bool > PressedKeys ;
// Keyrepeats are send as down, down, ..., down, up, where all downs are not distinguishable from the first.
if ( eEventType = = KEYEV_Down )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
if ( PressedKeys [ vk_code ] ) fRepeated = true ;
else PressedKeys [ vk_code ] = true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else if ( eEventType = = KEYEV_Up )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
PressedKeys [ vk_code ] = false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
# endif
// compose key
C4KeyCodeEx Key ( vk_code , C4KeyShiftState ( fAlt * KEYS_Alt + fCtrl * KEYS_Control + fShift * KEYS_Shift ) , fRepeated ) ;
// compose keyboard scope
DWORD InScope = 0 ;
if ( fPlrCtrlOnly )
InScope = KEYSCOPE_Control ;
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
if ( IsRunning ) InScope = KEYSCOPE_Generic ;
// if GUI has keyfocus, this overrides regular controls
2010-10-29 23:47:50 +00:00
if ( pGUI - > HasKeyboardFocus ( ) | | pForDialog )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
InScope | = KEYSCOPE_Gui ;
// control to console mode dialog: Make current keyboard target the active dlg,
// so it can process input
if ( pForDialog ) pGUI - > ActivateDialog ( pForDialog ) ;
// any keystroke in GUI resets tooltip times
pGUI - > KeyAny ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 17:58:21 +00:00
{
2010-09-28 18:16:33 +00:00
if ( ! Application . isEditor )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
if ( FullScreen . pMenu & & FullScreen . pMenu - > IsActive ( ) ) // fullscreen menu
InScope | = KEYSCOPE_FullSMenu ;
else if ( Game . C4S . Head . Replay & & C4S . Head . Film ) // film view only
InScope | = KEYSCOPE_FilmView ;
2010-09-29 01:44:05 +00:00
else if ( : : Viewports . GetViewport ( NO_OWNER ) ) // NO_OWNER-viewport-controls
2009-05-08 13:28:41 +00:00
InScope | = KEYSCOPE_FreeView ;
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// regular player viewport controls
InScope | = KEYSCOPE_FullSView ;
// player controls disabled during round over dlg
if ( ! C4GameOverDlg : : IsShown ( ) ) InScope | = KEYSCOPE_Control ;
}
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
// regular player viewport controls
InScope | = KEYSCOPE_Control ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// fullscreen/console (in running game)
if ( IsRunning )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
if ( FullScreen . Active ) InScope | = KEYSCOPE_Fullscreen ;
if ( Console . Active ) InScope | = KEYSCOPE_Console ;
}
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// okay; do input
2010-02-23 16:53:38 +00:00
if ( KeyboardInput . DoInput ( Key , eEventType , InScope , iStrength ) )
2009-05-08 13:28:41 +00:00
return true ;
// unprocessed key
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : CanQuickSave ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Network hosts only
if ( Network . isEnabled ( ) & & ! Network . isHost ( ) )
{ Log ( LoadResStr ( " IDS_GAME_NOCLIENTSAVE " ) ) ; return false ; }
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : QuickSave ( const char * strFilename , const char * strTitle , bool fForceSave )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Check
if ( ! fForceSave ) if ( ! CanQuickSave ( ) ) return false ;
// Create savegame folder
2011-05-09 15:35:44 +00:00
if ( ! Config . General . CreateSaveFolder ( Config . AtUserDataPath ( C4CFN_Savegames ) , LoadResStr ( " IDS_GAME_SAVEGAMESTITLE " ) ) )
2009-08-15 18:50:32 +00:00
{ Log ( LoadResStr ( " IDS_GAME_FAILSAVEGAME " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// Create savegame subfolder(s)
char strSaveFolder [ _MAX_PATH + 1 ] ;
2010-04-28 21:43:25 +00:00
for ( uint32_t i = 0 ; i < SCharCount ( DirectorySeparator , strFilename ) ; i + + )
2010-03-28 17:58:21 +00:00
{
2011-05-09 15:35:44 +00:00
SCopy ( Config . AtUserDataPath ( C4CFN_Savegames ) , strSaveFolder ) ; AppendBackslash ( strSaveFolder ) ;
2009-05-08 13:28:41 +00:00
SCopyUntil ( strFilename , strSaveFolder + SLen ( strSaveFolder ) , DirectorySeparator , _MAX_PATH , i ) ;
if ( ! Config . General . CreateSaveFolder ( strSaveFolder , strTitle ) )
2009-08-15 18:50:32 +00:00
{ Log ( LoadResStr ( " IDS_GAME_FAILSAVEGAME " ) ) ; return false ; }
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Compose savegame filename
StdStrBuf strSavePath ;
2011-05-09 15:35:44 +00:00
strSavePath . Format ( " %s%c%s " , Config . AtUserDataPath ( C4CFN_Savegames ) , DirectorySeparator , strFilename ) ;
2009-05-08 13:28:41 +00:00
// Must not be the scenario file that is currently open
if ( ItemIdentical ( ScenarioFilename , strSavePath . getData ( ) ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
StartSoundEffect ( " Error " ) ;
2010-04-15 22:45:30 +00:00
: : GraphicsSystem . FlashMessage ( LoadResStr ( " IDS_GAME_NOSAVEONCURR " ) ) ;
2009-05-08 13:28:41 +00:00
Log ( LoadResStr ( " IDS_GAME_FAILSAVEGAME " ) ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Wait message
Log ( LoadResStr ( " IDS_HOLD_SAVINGGAME " ) ) ;
GraphicsSystem . MessageBoard . EnsureLastMessage ( ) ;
// Save to target scenario file
C4GameSave * pGameSave ;
pGameSave = new C4GameSaveSavegame ( ) ;
if ( ! pGameSave - > Save ( strSavePath . getData ( ) ) )
2009-08-15 18:50:32 +00:00
{ Log ( LoadResStr ( " IDS_GAME_FAILSAVEGAME " ) ) ; delete pGameSave ; return false ; }
2009-05-08 13:28:41 +00:00
delete pGameSave ;
// Success
Log ( LoadResStr ( " IDS_CNS_GAMESAVED " ) ) ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool LandscapeFree ( int32_t x , int32_t y )
2010-03-28 17:58:21 +00:00
{
2009-08-15 18:50:32 +00:00
if ( ! Inside < int32_t > ( x , 0 , GBackWdt - 1 ) | | ! Inside < int32_t > ( y , 0 , GBackHgt - 1 ) ) return false ;
2010-03-27 16:05:02 +00:00
return ! DensitySolid ( GBackDensity ( x , y ) ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
static void FileMonitorCallback ( const char * file , const char * extrafile )
{
Game . ReloadFile ( file ) ;
}
2009-08-15 18:50:32 +00:00
bool C4Game : : ReloadFile ( const char * szFile )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
// not in network
2010-03-28 17:58:21 +00:00
if ( : : Network . isEnabled ( ) ) return false ;
2010-03-27 16:05:02 +00:00
const char * szRelativePath = Config . AtRelativePath ( szFile ) ;
// a definition? or part of a definition?
C4Def * pDef ;
2010-03-28 17:58:21 +00:00
if ( ( pDef = : : Definitions . GetByPath ( szRelativePath ) ) )
2010-03-27 16:05:02 +00:00
return ReloadDef ( pDef - > id ) ;
// script?
2011-02-06 20:37:19 +00:00
if ( ScriptEngine . ReloadScript ( szRelativePath , & : : Definitions , Config . General . LanguageEx ) )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
return true ;
}
2010-03-28 17:58:21 +00:00
return true ;
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : ReloadDef ( C4ID id )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
bool fSucc ;
2010-03-27 16:05:02 +00:00
// not in network
2010-03-28 17:58:21 +00:00
if ( : : Network . isEnabled ( ) ) return false ;
2009-05-08 13:28:41 +00:00
// syncronize (close menus with dead surfaces, etc.)
// no need to sync back player files, though
2009-08-15 18:50:32 +00:00
Synchronize ( false ) ;
2009-05-08 13:28:41 +00:00
// reload def
C4ObjectLink * clnk ;
2009-06-05 16:46:37 +00:00
C4Def * pDef = : : Definitions . ID2Def ( id ) ;
2009-08-15 18:50:32 +00:00
if ( ! pDef ) return false ;
2009-05-08 13:28:41 +00:00
// Message
2010-01-25 15:57:57 +00:00
LogF ( " Reloading %s from %s " , pDef - > id . ToString ( ) , GetFilename ( pDef - > Filename ) ) ;
2009-05-08 13:28:41 +00:00
// Reload def
2009-06-05 16:46:37 +00:00
if ( : : Definitions . Reload ( pDef , C4D_Load_RX , Config . General . LanguageEx , & Application . SoundSystem ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Success, update all concerned object faces
// may have been done by graphics-update already - but not for objects using graphics of another def
// better update everything :)
for ( clnk = Objects . First ; clnk & & clnk - > Obj ; clnk = clnk - > Next )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
if ( clnk - > Obj - > id = = id )
clnk - > Obj - > UpdateFace ( true ) ;
}
2010-03-28 17:58:21 +00:00
fSucc = true ;
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Failure, remove all objects of this type
for ( clnk = Objects . First ; clnk & & clnk - > Obj ; clnk = clnk - > Next )
if ( clnk - > Obj - > id = = id )
clnk - > Obj - > AssignRemoval ( ) ;
// safety: If a removed def is being profiled, profiling must stop
C4AulProfiler : : Abort ( ) ;
// Kill def
2009-06-05 16:46:37 +00:00
: : Definitions . Remove ( pDef ) ;
2009-05-08 13:28:41 +00:00
// Log
Log ( " Reloading failure. All objects of this type removed. " ) ;
fSucc = false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// update game messages
2009-06-05 18:12:43 +00:00
: : Messages . UpdateDef ( id ) ;
2009-05-08 13:28:41 +00:00
// done
return fSucc ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : ReloadParticle ( const char * szName )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
// not in network
2010-03-28 17:58:21 +00:00
if ( : : Network . isEnabled ( ) ) return false ;
2009-05-08 13:28:41 +00:00
// safety
2009-08-15 18:50:32 +00:00
if ( ! szName ) return false ;
2009-05-08 13:28:41 +00:00
// get particle def
C4ParticleDef * pDef = Particles . GetDef ( szName ) ;
2009-08-15 18:50:32 +00:00
if ( ! pDef ) return false ;
2009-05-08 13:28:41 +00:00
// verbose
2009-05-11 13:09:53 +00:00
LogF ( " Reloading particle %s from %s " , pDef - > Name . getData ( ) , GetFilename ( pDef - > Filename . getData ( ) ) ) ;
2009-05-08 13:28:41 +00:00
// reload it
if ( ! pDef - > Reload ( ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// safer: remove all particles
ParticleSystem . ClearParticles ( ) ;
// clear def
delete pDef ;
// log
2009-05-11 13:09:53 +00:00
LogF ( " Reloading failure. All particles removed. " ) ;
2009-05-08 13:28:41 +00:00
// failure
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// success
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2011-03-26 22:59:35 +00:00
bool C4Game : : InitGame ( C4Group & hGroup , bool fLoadSection , bool fLoadSky , C4ValueNumbers * numbers )
2010-03-28 17:58:21 +00:00
{
2013-10-13 19:44:17 +00:00
// Activate debugger if requested
// needs to happen before any scripts are compiled to bytecode so AB_DEBUG chunks will be inserted
if ( DebugPort )
{
if ( Parameters . isLeague ( ) )
Log ( " Debugger disabled. Not allowed in league. " ) ;
else
if ( ! : : C4AulDebug : : InitDebug ( DebugPassword . getData ( ) , DebugHost . getData ( ) ) )
return false ;
}
2009-05-08 13:28:41 +00:00
if ( ! fLoadSection )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// file monitor
2010-09-28 18:16:33 +00:00
if ( Config . Developer . AutoFileReload & & Application . isEditor & & ! pFileMonitor )
2009-05-08 13:28:41 +00:00
pFileMonitor = new C4FileMonitor ( FileMonitorCallback ) ;
// system scripts
if ( ! InitScriptEngine ( ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_FAIL " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
SetInitProgress ( 8 ) ;
// Scenario components
if ( ! LoadScenarioComponents ( ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_FAIL " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
SetInitProgress ( 9 ) ;
// join local players for regular games
// should be done before record/replay is initialized, so the players are stored in PlayerInfos.txt
// for local savegame resumes, players are joined into PlayerInfos and later associated in InitPlayers
2009-06-05 15:19:46 +00:00
if ( ! : : Network . isEnabled ( ) )
2009-05-08 13:28:41 +00:00
if ( ! PlayerInfos . InitLocal ( ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_FAIL " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// for replays, make sure teams are assigned correctly
if ( C4S . Head . Replay )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
PlayerInfos . RecheckAutoGeneratedTeams ( ) ; // checks that all teams used in playerinfos exist
Teams . RecheckPlayers ( ) ; // syncs player list of teams with teams set in PlayerInfos
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// set up control (inits Record/Replay)
2010-03-28 17:58:21 +00:00
if ( ! InitControl ( ) ) return false ;
2009-05-08 13:28:41 +00:00
// Graphics and fonts (may reinit main font, too)
// redundant call in NETWORK2; but it may do scenario local overloads
Log ( LoadResStr ( " IDS_PRC_GFXRES " ) ) ;
2010-06-27 00:42:48 +00:00
if ( ! GraphicsResource . Init ( ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_FAIL " ) ) ; return false ; }
2010-12-29 16:00:13 +00:00
SetInitProgress ( 25 ) ;
2009-05-08 13:28:41 +00:00
2011-10-13 15:05:40 +00:00
// Sound (first part, some are loaded with the definitions, the (section) local file goes later)
Application . SoundSystem . Init ( ) ;
2009-05-08 13:28:41 +00:00
// Definitions
2009-08-15 18:50:32 +00:00
if ( ! InitDefs ( ) ) return false ;
2010-12-29 16:00:13 +00:00
SetInitProgress ( 55 ) ;
2009-05-08 13:28:41 +00:00
2011-03-13 15:16:45 +00:00
// Scenario scripts (and local system.ocg)
2012-02-16 23:30:00 +00:00
GameScript . Load ( ScenarioFile , C4CFN_Script , Config . General . LanguageEx , & ScenarioLangStringTable ) ;
2013-03-18 23:35:00 +00:00
// Map scripts
MapScript . Load ( ScenarioFile , C4CFN_MapScript , Config . General . LanguageEx , & ScenarioLangStringTable ) ;
2009-05-08 13:28:41 +00:00
// After defs to get overloading priority
2011-09-25 21:24:29 +00:00
if ( ! LoadAdditionalSystemGroup ( ScenarioFile ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_FAIL " ) ) ; return false ; }
2009-07-24 21:50:04 +00:00
SetInitProgress ( 57 ) ;
2009-05-08 13:28:41 +00:00
2009-06-09 23:29:16 +00:00
// Final init for loaded player commands. Before linking scripts, so CON_* constants are registered
PlayerControlDefs . FinalInit ( ) ;
2011-03-30 20:11:47 +00:00
// Now that all controls and assignments are known, resolve user overloads on control assignments
if ( ! InitPlayerControlUserSettings ( ) ) return false ;
2011-03-31 14:26:59 +00:00
// Sort assignments by priority. Should be done last, because the user should not see this order in the control config dialog
2011-09-18 12:04:00 +00:00
PlayerControlUserAssignmentSets . SortAssignments ( ) ;
2011-03-30 20:11:47 +00:00
// (Theoretically, PlayerControlDefaultAssignmentSets could be cleared now. However, the amount of memory used is negligible)
2009-05-08 13:28:41 +00:00
// Link scripts
2009-08-15 18:50:32 +00:00
if ( ! LinkScriptEngine ( ) ) return false ;
2009-07-24 21:50:04 +00:00
SetInitProgress ( 58 ) ;
2009-05-08 13:28:41 +00:00
// Materials
if ( ! InitMaterialTexture ( ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_MATERROR " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
SetInitProgress ( 60 ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-13 15:05:40 +00:00
// Load setion sounds
Application . SoundSystem . LoadEffects ( hGroup ) ;
2009-05-08 13:28:41 +00:00
// determine startup player count
if ( ! FrameCounter ) StartupPlayerCount = PlayerInfos . GetStartupCount ( ) ;
// The Landscape is the last long chunk of loading time, so it's a good place to start the music fadeout
Application . MusicSystem . FadeOut ( 2000 ) ;
// Landscape
Log ( LoadResStr ( " IDS_PRC_LANDSCAPE " ) ) ;
bool fLandscapeLoaded = false ;
2010-03-27 16:05:02 +00:00
if ( ! Landscape . Init ( hGroup , fLoadSection , fLoadSky , fLandscapeLoaded , ! ! C4S . Head . SaveGame ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_ERR_GBACK " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
SetInitProgress ( 88 ) ;
// the savegame flag is set if runtime data is present, in which case this is to be used
// except for scenario sections
if ( fLandscapeLoaded & & ( ! C4S . Head . SaveGame | | fLoadSection ) )
2010-03-27 16:05:02 +00:00
Landscape . ScenarioInit ( ) ;
2009-05-08 13:28:41 +00:00
// clear old landscape data
if ( fLoadSection & & fLandscapeLoaded ) { PXS . Clear ( ) ; MassMover . Clear ( ) ; }
SetInitProgress ( 89 ) ;
// Init main object list
Objects . Init ( Landscape . Width , Landscape . Height ) ;
// Pathfinder
if ( ! fLoadSection ) PathFinder . Init ( & LandscapeFree , & TransferZones ) ;
SetInitProgress ( 90 ) ;
// PXS
if ( hGroup . FindEntry ( C4CFN_PXS ) )
if ( ! PXS . Load ( hGroup ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_ERR_PXS " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
SetInitProgress ( 91 ) ;
// MassMover
if ( hGroup . FindEntry ( C4CFN_MassMover ) )
if ( ! MassMover . Load ( hGroup ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_ERR_MOVER " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
SetInitProgress ( 92 ) ;
// definition value overloads
if ( ! fLoadSection ) InitValueOverloads ( ) ;
2011-03-27 14:51:14 +00:00
// runtime data
2011-09-19 19:00:55 +00:00
if ( ! CompileRuntimeData ( hGroup , fLoadSection , C4S . Head . SaveGame , numbers ) )
2011-03-27 14:51:14 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_FAIL " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
SetInitProgress ( 93 ) ;
// Load round results
2009-09-16 01:29:20 +00:00
if ( ! fLoadSection )
2010-01-25 04:00:59 +00:00
{
2009-09-16 01:29:20 +00:00
if ( hGroup . FindEntry ( C4CFN_RoundResults ) )
{
if ( ! RoundResults . Load ( hGroup , C4CFN_RoundResults ) )
{ LogFatal ( LoadResStr ( " IDS_ERR_ERRORLOADINGROUNDRESULTS " ) ) ; return false ; }
}
else
{
RoundResults . Init ( ) ;
2009-08-26 12:17:41 +00:00
}
2010-01-25 04:00:59 +00:00
}
2009-05-08 13:28:41 +00:00
2010-04-26 17:43:57 +00:00
// Denumerate game data pointers
2011-03-26 22:59:35 +00:00
if ( ! fLoadSection ) ScriptEngine . Denumerate ( numbers ) ;
if ( ! fLoadSection & & pGlobalEffects ) pGlobalEffects - > Denumerate ( numbers ) ;
2011-03-27 16:14:41 +00:00
numbers - > Denumerate ( ) ;
2010-04-26 17:43:57 +00:00
// Check object enumeration
if ( ! CheckObjectEnumeration ( ) ) return false ;
// Okay; everything in denumerated state from now on
PointersDenumerated = true ;
2009-05-08 13:28:41 +00:00
// Environment
if ( ! C4S . Head . NoInitialize & & fLandscapeLoaded )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
Log ( LoadResStr ( " IDS_PRC_ENVIRONMENT " ) ) ;
InitVegetation ( ) ;
InitInEarth ( ) ;
InitAnimals ( ) ;
InitEnvironment ( ) ;
InitRules ( ) ;
InitGoals ( ) ;
Landscape . PostInitMap ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
SetInitProgress ( 94 ) ;
2010-03-27 16:05:02 +00:00
// Weather
if ( fLandscapeLoaded ) Weather . Init ( ! C4S . Head . SaveGame ) ;
2009-05-08 13:28:41 +00:00
SetInitProgress ( 95 ) ;
// FoW-color
FoWColor = C4S . Game . FoWColor ;
SetInitProgress ( 96 ) ;
// close any gfx groups, because they are no longer needed (after sky is initialized)
GraphicsResource . CloseFiles ( ) ;
if ( ! fLoadSection )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Music
Application . MusicSystem . InitForScenario ( ScenarioFile ) ;
if ( Config . Sound . RXMusic )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Play something that is not Frontend.mid
Application . MusicSystem . Play ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
Application . MusicSystem . Stop ( ) ;
SetMusicLevel ( iMusicLevel ) ;
SetInitProgress ( 97 ) ;
}
2010-03-28 17:58:21 +00:00
return true ;
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : InitGameFinal ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Validate object owners & assign loaded info objects
Objects . ValidateOwners ( ) ;
Objects . AssignInfo ( ) ;
Objects . AssignPlrViewRange ( ) ; // update FoW-repellers
// Script constructor call
int32_t iObjCount = Objects . ObjectCount ( ) ;
2011-01-08 16:04:20 +00:00
if ( ! C4S . Head . SaveGame ) : : GameScript . Call ( PSF_Initialize ) ;
2009-08-15 18:50:32 +00:00
if ( Objects . ObjectCount ( ) ! = iObjCount ) fScriptCreatedObjects = true ;
2009-05-08 13:28:41 +00:00
// Player final init
C4Player * pPlr ;
for ( pPlr = Players . First ; pPlr ; pPlr = pPlr - > Next )
pPlr - > FinalInit ( ! C4S . Head . SaveGame ) ;
// Create viewports
for ( pPlr = Players . First ; pPlr ; pPlr = pPlr - > Next )
if ( pPlr - > LocalControl )
2010-09-29 01:44:05 +00:00
: : Viewports . CreateViewport ( pPlr - > Number ) ;
2009-05-08 13:28:41 +00:00
// Check fullscreen viewports
FullScreen . ViewportCheck ( ) ;
// update halt state
Console . UpdateHaltCtrls ( ! ! HaltCount ) ;
// Host: players without connected clients: remove via control queue
if ( Network . isEnabled ( ) & & Network . isHost ( ) )
for ( int32_t cnt = 0 ; cnt < Players . GetCount ( ) ; cnt + + )
if ( Players . GetByIndex ( cnt ) - > AtClient < 0 )
Players . Remove ( Players . GetByIndex ( cnt ) , true , false ) ;
// It should be safe now to reload stuff
if ( pFileMonitor ) pFileMonitor - > StartMonitoring ( ) ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : InitScriptEngine ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// engine functions
2011-03-04 12:49:41 +00:00
InitCoreFunctionMap ( & ScriptEngine ) ;
InitObjectFunctionMap ( & ScriptEngine ) ;
InitGameFunctionMap ( & ScriptEngine ) ;
2013-03-18 23:35:00 +00:00
: : MapScript . InitFunctionMap ( & ScriptEngine ) ;
2009-05-08 13:28:41 +00:00
// system functions: check if system group is open
if ( ! Application . OpenSystemGroup ( ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_ERR_INVALIDSYSGRP " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
C4Group & File = Application . SystemGroup ;
// get scripts
char fn [ _MAX_FNAME + 1 ] = { 0 } ;
File . ResetSearch ( ) ;
2011-03-05 01:45:27 +00:00
while ( File . FindNextEntry ( C4CFN_ScriptFiles , fn , NULL , ! ! fn [ 0 ] ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// host will be destroyed by script engine, so drop the references
2011-10-24 15:02:27 +00:00
C4ScriptHost * scr = new C4ExtraScriptHost ( ) ;
2012-02-17 00:04:05 +00:00
scr - > Reg2List ( & ScriptEngine ) ;
2011-09-29 01:49:21 +00:00
scr - > Load ( File , fn , Config . General . LanguageEx , & MainSysLangStringTable ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// if it's a physical group: watch out for changes
2010-03-28 17:58:21 +00:00
if ( ! File . IsPacked ( ) & & Game . pFileMonitor )
2009-05-08 13:28:41 +00:00
Game . pFileMonitor - > AddDirectory ( File . GetFullName ( ) . getData ( ) ) ;
// load standard clonk names
2011-02-06 20:31:33 +00:00
Names . Load ( File , C4CFN_Names ) ;
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : LinkScriptEngine ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Link script engine (resolve includes/appends, generate code)
2009-06-05 16:46:37 +00:00
ScriptEngine . Link ( & : : Definitions ) ;
2009-05-08 13:28:41 +00:00
// Set name list for globals
ScriptEngine . GlobalNamed . SetNameList ( & ScriptEngine . GlobalNamedNames ) ;
2013-10-13 19:44:17 +00:00
if ( C4AulDebug * pDebug = C4AulDebug : : GetDebugger ( ) )
if ( ! pDebug - > Listen ( DebugPort , ! ! DebugWait ) )
return false ;
2009-04-21 21:44:56 +00:00
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2011-03-26 22:59:35 +00:00
bool C4Game : : InitPlayers ( C4ValueNumbers * numbers )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t iPlrCnt = 0 ;
if ( C4S . Head . NetworkRuntimeJoin )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Load players to restore from scenario
C4PlayerInfoList LocalRestorePlayerInfos ;
LocalRestorePlayerInfos . Load ( ScenarioFile , C4CFN_SavePlayerInfos , & ScenarioLangStringTable ) ;
// -- runtime join player restore
// all restore functions will be executed on RestorePlayerInfos, because the main playerinfos may be more up-to-date
// extract all players to temp store and update filenames to point there
if ( ! LocalRestorePlayerInfos . RecreatePlayerFiles ( ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_ERR_NOPLRFILERECR " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// recreate the files
2011-03-26 22:59:35 +00:00
if ( ! LocalRestorePlayerInfos . RecreatePlayers ( numbers ) )
2010-03-28 17:58:21 +00:00
{ LogFatal ( LoadResStr ( " IDS_ERR_NOPLRNETRECR " ) ) ; return false ; }
}
2009-05-08 13:28:41 +00:00
else if ( RestorePlayerInfos . GetActivePlayerCount ( true ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// -- savegame player restore
// for savegames or regular scenarios with restore infos, the player info list should have been loaded from the savegame
// or got restored from game text in OpenScenario()
// merge restore player info into main player info list now
// -for single-host games, this will move all infos
// -for network games, it will merge according to savegame association done in the lobby
// for all savegames, script players get restored by adding one new script player for earch savegame script player to the host
if ( ! PlayerInfos . RestoreSavegameInfos ( RestorePlayerInfos ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_ERR_NOPLRSAVEINFORECR " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
RestorePlayerInfos . Clear ( ) ;
2012-10-21 20:20:43 +00:00
// try to associate local filenames (non-net+replay) or resources (net) with all player infos
2009-05-08 13:28:41 +00:00
if ( ! PlayerInfos . RecreatePlayerFiles ( ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_ERR_NOPLRFILERECR " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// recreate players by joining all players whose joined-flag is already set
2011-03-26 22:59:35 +00:00
if ( ! PlayerInfos . RecreatePlayers ( numbers ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_ERR_NOPLRSAVERECR " ) ) ; return false ; }
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// any regular non-net non-replay game: Do the normal control queue join
// this includes additional player joins in savegames
if ( ! Network . isEnabled ( ) & & ! Control . NoInput ( ) )
if ( ! PlayerInfos . LocalJoinUnjoinedPlayersInQueue ( ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// error joining local players - either join was done earlier somehow,
// or the player count check will soon end this round
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// non-replay player joins will be done by player info list when go tick is reached
// this is handled by C4Network2Players and needs no further treatment here
// set iPlrCnt for player count check in host/single games
iPlrCnt = PlayerInfos . GetJoinIssuedPlayerCount ( ) ;
// Check valid participating player numbers (host/single only)
if ( ! Network . isEnabled ( ) | | ( Network . isHost ( ) & & ! fLobby ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
# ifndef USE_CONSOLE
// No players in fullscreen
if ( iPlrCnt = = 0 )
2010-09-28 18:16:33 +00:00
if ( ! Application . isEditor & & ! Control . NoInput ( ) )
2010-03-28 17:58:21 +00:00
{
2009-08-15 18:50:32 +00:00
LogFatal ( LoadResStr ( " IDS_CNS_NOFULLSCREENPLRS " ) ) ; return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
# endif
// Too many players
if ( iPlrCnt > Game . Parameters . MaxPlayers )
2010-03-28 17:58:21 +00:00
{
2010-09-28 18:16:33 +00:00
if ( ! Application . isEditor )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
LogFatal ( FormatString ( LoadResStr ( " IDS_PRC_TOOMANYPLRS " ) , Game . Parameters . MaxPlayers ) . getData ( ) ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
Console . Message ( FormatString ( LoadResStr ( " IDS_PRC_TOOMANYPLRS " ) , Game . Parameters . MaxPlayers ) . getData ( ) ) ;
}
}
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Console and no real players: halt
if ( Console . Active )
if ( ! fLobby )
if ( ! ( PlayerInfos . GetActivePlayerCount ( false ) - PlayerInfos . GetActiveScriptPlayerCount ( true , false ) ) )
+ + HaltCount ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : InitControl ( )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
// update random seed
2010-03-28 17:58:21 +00:00
if ( C4S . Head . NetworkGame | | C4S . Head . Replay )
{
2009-05-08 13:28:41 +00:00
RandomSeed = C4S . Head . RandomSeed ;
StartupPlayerCount = C4S . Head . StartupPlayerCount ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Randomize
FixRandom ( RandomSeed ) ;
2010-03-27 16:05:02 +00:00
// Replay?
2009-05-08 13:28:41 +00:00
if ( C4S . Head . Replay )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// no joins
PlayerFilenames [ 0 ] = 0 ;
// start playback
2010-03-28 17:58:21 +00:00
if ( ! Control . InitReplay ( ScenarioFile ) )
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
// no record!
2009-08-15 18:50:32 +00:00
Record = false ;
2010-03-28 17:58:21 +00:00
}
else if ( Network . isEnabled ( ) )
{
2010-03-27 16:05:02 +00:00
// set startup player count
2010-03-28 17:58:21 +00:00
if ( ! C4S . Head . SaveGame & & ! C4S . Head . Replay )
StartupPlayerCount = PlayerInfos . GetPlayerCount ( ) ;
2009-05-08 13:28:41 +00:00
// initialize
2010-03-28 17:58:21 +00:00
if ( ! Control . InitNetwork ( Clients . getLocal ( ) ) )
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
// league? always record
2010-03-28 17:58:21 +00:00
if ( Parameters . isLeague ( ) )
2009-05-08 13:28:41 +00:00
Record = true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Otherwise: local game
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// init
2010-03-28 17:58:21 +00:00
if ( ! Control . InitLocal ( Clients . getLocal ( ) ) )
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// record?
2010-03-28 17:58:21 +00:00
if ( Record )
if ( ! Control . StartRecord ( true , Parameters . doStreaming ( ) ) )
{
2009-05-08 13:28:41 +00:00
// Special: If this happens for a league host, the game must not start.
if ( Network . isEnabled ( ) & & Network . isHost ( ) & & Parameters . isLeague ( ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
LogFatal ( LoadResStr ( " IDS_ERR_NORECORD " ) ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
Log ( LoadResStr ( " IDS_ERR_NORECORD " ) ) ;
}
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
int32_t ListExpandValids ( C4IDList & rlist ,
2010-03-28 17:58:21 +00:00
C4ID * idlist , int32_t maxidlist )
{
2010-03-27 16:05:02 +00:00
int32_t cnt , cnt2 , ccount , cpos ;
for ( cpos = 0 , cnt = 0 ; rlist . GetID ( cnt ) ; cnt + + )
if ( C4Id2Def ( rlist . GetID ( cnt , & ccount ) ) )
for ( cnt2 = 0 ; cnt2 < ccount ; cnt2 + + )
if ( cpos < maxidlist )
{ idlist [ cpos ] = rlist . GetID ( cnt ) ; cpos + + ; }
return cpos ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : PlaceInEarth ( C4ID id )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
int32_t cnt , tx , ty ;
for ( cnt = 0 ; cnt < 35 ; cnt + + ) // cheap trys
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
tx = Random ( GBackWdt ) ; ty = Random ( GBackHgt ) ;
if ( GBackMat ( tx , ty ) = = MEarth )
if ( CreateObject ( id , NULL , NO_OWNER , tx , ty , Random ( 360 ) ) )
return true ;
}
2010-03-28 17:58:21 +00:00
return false ;
}
2009-05-08 13:28:41 +00:00
2012-04-18 13:23:35 +00:00
C4Object * C4Game : : PlaceVegetation ( C4PropList * PropList , int32_t iX , int32_t iY , int32_t iWdt , int32_t iHgt , int32_t iGrowth )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
int32_t cnt , iTx , iTy , iMaterial ;
2009-05-08 13:28:41 +00:00
// Get definition
2012-04-18 13:23:35 +00:00
C4Def * pDef ;
if ( ! PropList | | ! ( pDef = PropList - > GetDef ( ) ) ) return NULL ;
2009-05-08 13:28:41 +00:00
2011-01-03 01:30:04 +00:00
// No growth specified: full growth
2009-05-08 13:28:41 +00:00
if ( iGrowth < = 0 )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
iGrowth = FullCon ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Place by placement type
2012-04-18 13:23:35 +00:00
switch ( PropList - > GetPropertyInt ( P_Placement ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Surface soil
2010-03-28 17:58:21 +00:00
case C4D_Place_Surface :
for ( cnt = 0 ; cnt < 20 ; cnt + + )
{
// Random hit within target area
iTx = iX + Random ( iWdt ) ; iTy = iY + Random ( iHgt ) ;
// Above IFT
while ( ( iTy > 0 ) & & GBackIFT ( iTx , iTy ) ) iTy - - ;
2011-10-12 15:17:04 +00:00
// Still inside bounds
if ( iTy < iY )
continue ;
2010-03-28 17:58:21 +00:00
// Above semi solid
if ( ! AboveSemiSolid ( iTx , iTy ) | | ! Inside < int32_t > ( iTy , 50 , GBackHgt - 50 ) )
continue ;
// Free above
if ( GBackSemiSolid ( iTx , iTy - pDef - > Shape . Hgt ) | | GBackSemiSolid ( iTx , iTy - pDef - > Shape . Hgt / 2 ) )
continue ;
// Free upleft and upright
if ( GBackSemiSolid ( iTx - pDef - > Shape . Wdt / 2 , iTy - pDef - > Shape . Hgt * 2 / 3 ) | | GBackSemiSolid ( iTx + pDef - > Shape . Wdt / 2 , iTy - pDef - > Shape . Hgt * 2 / 3 ) )
continue ;
// Soil check
iTy + = 3 ; // two pix into ground
iMaterial = GBackMat ( iTx , iTy ) ;
if ( iMaterial ! = MNone ) if ( : : MaterialMap . Map [ iMaterial ] . Soil )
2009-05-08 13:28:41 +00:00
{
iTy + = 5 ;
2012-04-18 13:23:35 +00:00
return CreateObjectConstruction ( PropList , NULL , NO_OWNER , iTx , iTy , iGrowth ) ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 17:58:21 +00:00
}
break ;
2009-05-08 13:28:41 +00:00
// Underwater
2010-03-28 17:58:21 +00:00
case C4D_Place_Liquid :
// Random range
iTx = iX + Random ( iWdt ) ; iTy = iY + Random ( iHgt ) ;
// Find liquid
if ( ! FindSurfaceLiquid ( iTx , iTy , pDef - > Shape . Wdt , pDef - > Shape . Hgt ) )
if ( ! FindLiquid ( iTx , iTy , pDef - > Shape . Wdt , pDef - > Shape . Hgt ) )
return NULL ;
// Liquid bottom
if ( ! SemiAboveSolid ( iTx , iTy ) ) return NULL ;
iTy + = 3 ;
// Create object
2012-04-18 13:23:35 +00:00
return CreateObjectConstruction ( PropList , NULL , NO_OWNER , iTx , iTy , iGrowth ) ;
2011-10-02 22:11:00 +00:00
break ;
// Underground/Tunnel
case C4D_Place_Subsurface :
for ( cnt = 0 ; cnt < 5 ; cnt + + )
{
// Random range
iTx = iX + Random ( iWdt ) ; iTy = iY + Random ( iHgt ) ;
// Find tunnel
if ( ! FindTunnel ( iTx , iTy , pDef - > Shape . Wdt , pDef - > Shape . Hgt ) )
continue ;
// Tunnel bottom
if ( ! AboveSemiSolid ( iTx , iTy ) ) continue ;
// Soil check
iTy + = 3 ; // two pix into ground
iMaterial = GBackMat ( iTx , iTy ) ;
if ( iMaterial ! = MNone ) if ( : : MaterialMap . Map [ iMaterial ] . Soil )
{
// Create object
iTy + = 5 ;
2012-04-18 13:23:35 +00:00
return CreateObjectConstruction ( PropList , NULL , NO_OWNER , iTx , iTy , iGrowth ) ;
2011-10-02 22:11:00 +00:00
}
}
// Under- or aboveground
case C4D_Place_BothSurface :
for ( cnt = 0 ; cnt < 20 ; cnt + + )
{
// Random hit within target area
iTx = iX + Random ( iWdt ) ; iTy = iY + Random ( iHgt ) ;
// Above semi solid
if ( ! AboveSemiSolid ( iTx , iTy ) | | ! Inside < int32_t > ( iTy , 50 , GBackHgt - 50 ) )
continue ;
// Free above
if ( GBackSemiSolid ( iTx , iTy - pDef - > Shape . Hgt ) | | GBackSemiSolid ( iTx , iTy - pDef - > Shape . Hgt / 2 ) )
continue ;
// Free upleft and upright
if ( GBackSemiSolid ( iTx - pDef - > Shape . Wdt / 2 , iTy - pDef - > Shape . Hgt * 2 / 3 ) | | GBackSemiSolid ( iTx + pDef - > Shape . Wdt / 2 , iTy - pDef - > Shape . Hgt * 2 / 3 ) )
continue ;
// Soil check
iTy + = 3 ; // two pix into ground
iMaterial = GBackMat ( iTx , iTy ) ;
if ( iMaterial ! = MNone ) if ( : : MaterialMap . Map [ iMaterial ] . Soil )
{
iTy + = 5 ;
2012-04-18 13:23:35 +00:00
return CreateObjectConstruction ( PropList , NULL , NO_OWNER , iTx , iTy , iGrowth ) ;
2011-10-02 22:11:00 +00:00
}
}
2009-05-08 13:28:41 +00:00
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Undefined placement type
return NULL ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2012-04-18 13:23:35 +00:00
C4Object * C4Game : : PlaceAnimal ( C4PropList * PropList )
2010-03-28 17:58:21 +00:00
{
2012-04-18 13:23:35 +00:00
C4Def * pDef ;
if ( ! PropList | | ! ( pDef = PropList - > GetDef ( ) ) ) return NULL ;
2010-03-27 16:05:02 +00:00
int32_t iX , iY ;
2009-05-08 13:28:41 +00:00
// Placement
2012-04-18 13:23:35 +00:00
switch ( PropList - > GetPropertyInt ( P_Placement ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Running free
2010-03-28 17:58:21 +00:00
case C4D_Place_Surface :
iX = Random ( GBackWdt ) ; iY = Random ( GBackHgt ) ;
if ( ! FindSolidGround ( iX , iY , pDef - > Shape . Wdt ) ) return NULL ;
break ;
2009-05-08 13:28:41 +00:00
// In liquid
2010-03-28 17:58:21 +00:00
case C4D_Place_Liquid :
iX = Random ( GBackWdt ) ; iY = Random ( GBackHgt ) ;
if ( ! FindSurfaceLiquid ( iX , iY , pDef - > Shape . Wdt , pDef - > Shape . Hgt ) )
if ( ! FindLiquid ( iX , iY , pDef - > Shape . Wdt , pDef - > Shape . Hgt ) )
2011-09-27 22:48:46 +00:00
return NULL ;
2010-03-28 17:58:21 +00:00
iY + = pDef - > Shape . Hgt / 2 ;
break ;
2009-05-08 13:28:41 +00:00
// Floating in air
2010-03-28 17:58:21 +00:00
case C4D_Place_Air :
iX = Random ( GBackWdt ) ;
for ( iY = 0 ; ( iY < GBackHgt ) & & ! GBackSemiSolid ( iX , iY ) ; iY + + ) { }
if ( iY < = 0 ) return NULL ;
iY = Random ( iY ) ;
break ;
default :
return NULL ;
}
2009-05-08 13:28:41 +00:00
// Create object
2012-04-18 13:23:35 +00:00
return CreateObject ( PropList , NULL , NO_OWNER , iX , iY ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : InitInEarth ( )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
const int32_t maxvid = 100 ;
int32_t cnt , vidnum ;
C4ID vidlist [ maxvid ] ;
// Amount
int32_t amt = ( GBackWdt * GBackHgt / 5000 ) * C4S . Landscape . InEarthLevel . Evaluate ( ) / 100 ;
// List all valid IDs from C4S
vidnum = ListExpandValids ( C4S . Landscape . InEarth , vidlist , maxvid ) ;
// Place
if ( vidnum > 0 )
for ( cnt = 0 ; cnt < amt ; cnt + + )
PlaceInEarth ( vidlist [ Random ( vidnum ) ] ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : InitVegetation ( )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
const int32_t maxvid = 100 ;
int32_t cnt , vidnum ;
C4ID vidlist [ maxvid ] ;
// Amount
int32_t amt = ( GBackWdt / 50 ) * C4S . Landscape . VegLevel . Evaluate ( ) / 100 ;
// Get percentage vidlist from C4S
vidnum = ListExpandValids ( C4S . Landscape . Vegetation , vidlist , maxvid ) ;
// Place vegetation
if ( vidnum > 0 )
for ( cnt = 0 ; cnt < amt ; cnt + + )
2012-04-18 13:23:35 +00:00
PlaceVegetation ( C4Id2Def ( vidlist [ Random ( vidnum ) ] ) , 0 , 0 , GBackWdt , GBackHgt , - 1 ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : InitAnimals ( )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
int32_t cnt , cnt2 ;
C4ID idAnimal ; int32_t iCount ;
// Place animals
for ( cnt = 0 ; ( idAnimal = C4S . Animals . FreeLife . GetID ( cnt , & iCount ) ) ; cnt + + )
for ( cnt2 = 0 ; cnt2 < iCount ; cnt2 + + )
2012-04-18 13:23:35 +00:00
PlaceAnimal ( C4Id2Def ( idAnimal ) ) ;
2009-05-08 13:28:41 +00:00
// Place nests
2010-03-27 16:05:02 +00:00
for ( cnt = 0 ; ( idAnimal = C4S . Animals . EarthNest . GetID ( cnt , & iCount ) ) ; cnt + + )
for ( cnt2 = 0 ; cnt2 < iCount ; cnt2 + + )
PlaceInEarth ( idAnimal ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : LoadScenarioComponents ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Info
2011-02-06 20:31:33 +00:00
Info . Load ( ScenarioFile , C4CFN_Info ) ;
2009-05-08 13:28:41 +00:00
// Overload clonk names from scenario file
if ( ScenarioFile . EntryCount ( C4CFN_Names ) )
2011-02-06 20:31:33 +00:00
Names . Load ( ScenarioFile , C4CFN_Names ) ;
2009-05-08 13:28:41 +00:00
// scenario sections
char fn [ _MAX_FNAME + 1 ] = { 0 } ;
ScenarioFile . ResetSearch ( ) ; * fn = 0 ;
2011-03-05 01:45:27 +00:00
while ( ScenarioFile . FindNextEntry ( C4CFN_ScenarioSections , fn , NULL , ! ! * fn ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// get section name
char SctName [ _MAX_FNAME + 1 ] ;
int32_t iWildcardPos = SCharPos ( ' * ' , C4CFN_ScenarioSections ) ;
SCopy ( fn + iWildcardPos , SctName , _MAX_FNAME ) ;
RemoveExtension ( SctName ) ;
2010-01-25 04:00:59 +00:00
if ( std : : strlen ( SctName ) > C4MaxName | | ! * SctName )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLog ( " invalid section name " ) ;
2009-08-15 18:50:32 +00:00
LogFatal ( FormatString ( LoadResStr ( " IDS_ERR_SCENSECTION " ) , fn ) . getData ( ) ) ; return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// load this section into temp store
C4ScenarioSection * pSection = new C4ScenarioSection ( SctName ) ;
if ( ! pSection - > ScenarioLoad ( fn ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( FormatString ( LoadResStr ( " IDS_ERR_SCENSECTION " ) , fn ) . getData ( ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Success
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2011-03-02 17:13:43 +00:00
bool C4Game : : LoadAdditionalSystemGroup ( C4Group & parent_group )
{
2011-03-13 15:16:45 +00:00
// called for scenario local and definition local System.ocg groups
2009-05-08 13:28:41 +00:00
C4Group SysGroup ;
char fn [ _MAX_FNAME + 1 ] = { 0 } ;
2011-03-02 17:13:43 +00:00
if ( SysGroup . OpenAsChild ( & parent_group , C4CFN_System ) )
2010-03-28 17:58:21 +00:00
{
2011-03-02 17:13:43 +00:00
C4LangStringTable SysGroupString ;
2013-10-29 20:32:21 +00:00
C4Language : : LoadComponentHost ( & SysGroupString , SysGroup , C4CFN_ScriptStringTbl , Config . General . LanguageEx ) ;
2009-12-28 13:36:06 +00:00
// load custom scenario control definitions
if ( SysGroup . FindEntry ( C4CFN_PlayerControls ) )
{
Log ( " [!]Loading local scenario player control definitions... " ) ;
C4PlayerControlFile PlayerControlFile ;
2011-03-02 17:13:43 +00:00
if ( ! PlayerControlFile . Load ( SysGroup , C4CFN_PlayerControls , & SysGroupString ) )
2009-12-28 13:36:06 +00:00
{
// non-fatal error here
Log ( " [!]Error loading scenario defined player controls " ) ;
}
else
{
// local definitions loaded successfully - merge into global definitions
PlayerControlDefs . MergeFrom ( PlayerControlFile . GetControlDefs ( ) ) ;
2011-03-30 20:11:47 +00:00
PlayerControlDefaultAssignmentSets . MergeFrom ( PlayerControlFile . GetAssignmentSets ( ) , C4PlayerControlAssignmentSet : : MM_LowPrio ) ;
PlayerControlDefaultAssignmentSets . ResolveRefs ( & PlayerControlDefs ) ;
2009-12-28 13:36:06 +00:00
}
}
2009-05-08 13:28:41 +00:00
// load all scripts in there
SysGroup . ResetSearch ( ) ;
2011-03-05 01:45:27 +00:00
while ( SysGroup . FindNextEntry ( C4CFN_ScriptFiles , fn , NULL , ! ! fn [ 0 ] ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// host will be destroyed by script engine, so drop the references
2011-10-24 15:02:27 +00:00
C4ScriptHost * scr = new C4ExtraScriptHost ( ) ;
2012-02-17 00:04:05 +00:00
scr - > Reg2List ( & ScriptEngine ) ;
2011-09-29 01:49:21 +00:00
scr - > Load ( SysGroup , fn , Config . General . LanguageEx , & SysGroupString ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// if it's a physical group: watch out for changes
2010-03-28 17:58:21 +00:00
if ( ! SysGroup . IsPacked ( ) & & Game . pFileMonitor )
2009-05-08 13:28:41 +00:00
Game . pFileMonitor - > AddDirectory ( SysGroup . GetFullName ( ) . getData ( ) ) ;
SysGroup . Close ( ) ;
}
2010-03-28 17:58:21 +00:00
return true ;
}
2009-05-08 13:28:41 +00:00
bool C4Game : : InitKeyboard ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
C4CustomKey : : CodeList Keys ;
// clear previous
KeyboardInput . Clear ( ) ;
// globals
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F3 ) , " MusicToggle " , C4KeyScope ( KEYSCOPE_Generic | KEYSCOPE_Gui ) , new C4KeyCB < C4MusicSystem > ( Application . MusicSystem , & C4MusicSystem : : ToggleOnOff ) ) ) ;
2013-09-20 21:50:19 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F9 ) , " Screenshot " , C4KeyScope ( KEYSCOPE_Fullscreen | KEYSCOPE_Gui ) , new C4KeyCBEx < C4GraphicsSystem , bool > ( GraphicsSystem , false , & C4GraphicsSystem : : SaveScreenshotKey ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F9 , KEYS_Control ) , " ScreenshotEx " , KEYSCOPE_Fullscreen , new C4KeyCBEx < C4GraphicsSystem , bool > ( GraphicsSystem , true , & C4GraphicsSystem : : SaveScreenshotKey ) ) ) ;
2013-05-26 11:06:21 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_C , KEYS_Alt ) , " ToggleChat " , C4KeyScope ( KEYSCOPE_Generic | KEYSCOPE_Gui ) , new C4KeyCB < C4Game > ( * this , & C4Game : : ToggleChat ) ) ) ;
2009-05-08 13:28:41 +00:00
// main ingame
2010-03-28 17:58:21 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F1 ) , " ToggleShowHelp " , KEYSCOPE_Generic , new C4KeyCB < C4GraphicsSystem > ( GraphicsSystem , & C4GraphicsSystem : : ToggleShowHelp ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F4 ) , " NetClientListDlgToggle " , KEYSCOPE_Generic , new C4KeyCB < C4Network2 > ( Network , & C4Network2 : : ToggleClientListDlg ) ) ) ;
2010-09-29 01:44:05 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F5 ) , " ZoomIn " , KEYSCOPE_Generic , new C4KeyCB < C4ViewportList > ( : : Viewports , & C4ViewportList : : ViewportZoomIn ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F6 ) , " ZoomOut " , KEYSCOPE_Generic , new C4KeyCB < C4ViewportList > ( : : Viewports , & C4ViewportList : : ViewportZoomOut ) ) ) ;
2009-05-08 13:28:41 +00:00
// messageboard
2010-03-28 17:58:21 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_UP , KEYS_Shift ) , " MsgBoardScrollUp " , KEYSCOPE_Fullscreen , new C4KeyCB < C4MessageBoard > ( GraphicsSystem . MessageBoard , & C4MessageBoard : : ControlScrollUp ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_DOWN , KEYS_Shift ) , " MsgBoardScrollDown " , KEYSCOPE_Fullscreen , new C4KeyCB < C4MessageBoard > ( GraphicsSystem . MessageBoard , & C4MessageBoard : : ControlScrollDown ) ) ) ;
2009-05-08 13:28:41 +00:00
// debug mode & debug displays
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F5 , KEYS_Control ) , " DbgModeToggle " , KEYSCOPE_Generic , new C4KeyCB < C4Game > ( * this , & C4Game : : ToggleDebugMode ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F6 , KEYS_Control ) , " DbgShowVtxToggle " , KEYSCOPE_Generic , new C4KeyCB < C4GraphicsSystem > ( GraphicsSystem , & C4GraphicsSystem : : ToggleShowVertices ) ) ) ;
2010-03-28 17:58:21 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F7 , KEYS_Control ) , " DbgShowActionToggle " , KEYSCOPE_Generic , new C4KeyCB < C4GraphicsSystem > ( GraphicsSystem , & C4GraphicsSystem : : ToggleShowAction ) ) ) ;
2009-05-08 13:28:41 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_F8 , KEYS_Control ) , " DbgShowSolidMaskToggle " , KEYSCOPE_Generic , new C4KeyCB < C4GraphicsSystem > ( GraphicsSystem , & C4GraphicsSystem : : ToggleShowSolidMask ) ) ) ;
// video recording - improve...
2010-03-28 17:58:21 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_ADD , KEYS_Alt ) , " VideoEnlarge " , KEYSCOPE_Generic , new C4KeyCB < C4Video > ( GraphicsSystem . Video , & C4Video : : Enlarge ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_SUBTRACT , KEYS_Alt ) , " VideoReduce " , KEYSCOPE_Generic , new C4KeyCB < C4Video > ( GraphicsSystem . Video , & C4Video : : Reduce ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_MULTIPLY , KEYS_Alt ) , " VideoToggle " , KEYSCOPE_Generic , new C4KeyCB < C4Video > ( GraphicsSystem . Video , & C4Video : : Toggle ) ) ) ;
2009-05-08 13:28:41 +00:00
// playback speed - improve...
2010-03-28 17:58:21 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_ADD , KEYS_Shift ) , " GameSpeedUp " , KEYSCOPE_Generic , new C4KeyCB < C4Game > ( * this , & C4Game : : SpeedUp ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_SUBTRACT , KEYS_Shift ) , " GameSlowDown " , KEYSCOPE_Generic , new C4KeyCB < C4Game > ( * this , & C4Game : : SlowDown ) ) ) ;
2009-05-08 13:28:41 +00:00
// fullscreen menu
Keys . clear ( ) ; Keys . push_back ( C4KeyCodeEx ( K_LEFT ) ) ;
if ( Config . Controls . GamepadGuiControl ) Keys . push_back ( C4KeyCodeEx ( KEY_Gamepad ( 0 , KEY_JOY_Left ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( Keys , " FullscreenMenuLeft " , KEYSCOPE_FullSMenu , new C4KeyCBEx < C4FullScreen , BYTE > ( FullScreen , COM_MenuLeft , & C4FullScreen : : MenuKeyControl ) ) ) ;
Keys . clear ( ) ; Keys . push_back ( C4KeyCodeEx ( K_RIGHT ) ) ;
if ( Config . Controls . GamepadGuiControl ) Keys . push_back ( C4KeyCodeEx ( KEY_Gamepad ( 0 , KEY_JOY_Right ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( Keys , " FullscreenMenuRight " , KEYSCOPE_FullSMenu , new C4KeyCBEx < C4FullScreen , BYTE > ( FullScreen , COM_MenuRight , & C4FullScreen : : MenuKeyControl ) ) ) ;
Keys . clear ( ) ; Keys . push_back ( C4KeyCodeEx ( K_UP ) ) ;
if ( Config . Controls . GamepadGuiControl ) Keys . push_back ( C4KeyCodeEx ( KEY_Gamepad ( 0 , KEY_JOY_Up ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( Keys , " FullscreenMenuUp " , KEYSCOPE_FullSMenu , new C4KeyCBEx < C4FullScreen , BYTE > ( FullScreen , COM_MenuUp , & C4FullScreen : : MenuKeyControl ) ) ) ;
Keys . clear ( ) ; Keys . push_back ( C4KeyCodeEx ( K_DOWN ) ) ;
if ( Config . Controls . GamepadGuiControl ) Keys . push_back ( C4KeyCodeEx ( KEY_Gamepad ( 0 , KEY_JOY_Down ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( Keys , " FullscreenMenuDown " , KEYSCOPE_FullSMenu , new C4KeyCBEx < C4FullScreen , BYTE > ( FullScreen , COM_MenuDown , & C4FullScreen : : MenuKeyControl ) ) ) ;
Keys . clear ( ) ; Keys . push_back ( C4KeyCodeEx ( K_SPACE ) ) ; Keys . push_back ( C4KeyCodeEx ( K_RETURN ) ) ;
if ( Config . Controls . GamepadGuiControl ) Keys . push_back ( C4KeyCodeEx ( KEY_Gamepad ( 0 , KEY_JOY_AnyLowButton ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( Keys , " FullscreenMenuOK " , KEYSCOPE_FullSMenu , new C4KeyCBEx < C4FullScreen , BYTE > ( FullScreen , COM_MenuEnter , & C4FullScreen : : MenuKeyControl ) ) ) ; // name used by PlrControlKeyName
Keys . clear ( ) ; Keys . push_back ( C4KeyCodeEx ( K_ESCAPE ) ) ;
if ( Config . Controls . GamepadGuiControl ) Keys . push_back ( C4KeyCodeEx ( KEY_Gamepad ( 0 , KEY_JOY_AnyHighButton ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( Keys , " FullscreenMenuCancel " , KEYSCOPE_FullSMenu , new C4KeyCBEx < C4FullScreen , BYTE > ( FullScreen , COM_MenuClose , & C4FullScreen : : MenuKeyControl ) ) ) ; // name used by PlrControlKeyName
Keys . clear ( ) ; Keys . push_back ( C4KeyCodeEx ( K_SPACE ) ) ;
if ( Config . Controls . GamepadGuiControl ) Keys . push_back ( C4KeyCodeEx ( KEY_Gamepad ( 0 , KEY_JOY_AnyButton ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( Keys , " FullscreenMenuOpen " , KEYSCOPE_FreeView , new C4KeyCB < C4FullScreen > ( FullScreen , & C4FullScreen : : ActivateMenuMain ) ) ) ; // name used by C4MainMenu!
2010-09-29 01:44:05 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_RIGHT ) , " FilmNextPlayer " , KEYSCOPE_FilmView , new C4KeyCB < C4ViewportList > ( : : Viewports , & C4ViewportList : : ViewportNextPlayer ) ) ) ;
2009-05-08 13:28:41 +00:00
// chat
Keys . clear ( ) ;
Keys . push_back ( C4KeyCodeEx ( K_RETURN ) ) ;
Keys . push_back ( C4KeyCodeEx ( K_F2 ) ) ; // alternate chat key, if RETURN is blocked by player control
KeyboardInput . RegisterKey ( new C4CustomKey ( Keys , " ChatOpen " , KEYSCOPE_Generic , new C4KeyCBEx < C4MessageInput , bool > ( MessageInput , false , & C4MessageInput : : KeyStartTypeIn ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_RETURN , KEYS_Shift ) , " ChatOpen2Allies " , KEYSCOPE_Generic , new C4KeyCBEx < C4MessageInput , bool > ( MessageInput , true , & C4MessageInput : : KeyStartTypeIn ) ) ) ;
2010-09-29 01:44:05 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_LEFT ) , " FreeViewScrollLeft " , KEYSCOPE_FreeView , new C4KeyCBEx < C4ViewportList , C4Vec2D > ( : : Viewports , C4Vec2D ( - 5 , 0 ) , & C4ViewportList : : FreeScroll ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_RIGHT ) , " FreeViewScrollRight " , KEYSCOPE_FreeView , new C4KeyCBEx < C4ViewportList , C4Vec2D > ( : : Viewports , C4Vec2D ( + 5 , 0 ) , & C4ViewportList : : FreeScroll ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_UP ) , " FreeViewScrollUp " , KEYSCOPE_FreeView , new C4KeyCBEx < C4ViewportList , C4Vec2D > ( : : Viewports , C4Vec2D ( 0 , - 5 ) , & C4ViewportList : : FreeScroll ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_DOWN ) , " FreeViewScrollDown " , KEYSCOPE_FreeView , new C4KeyCBEx < C4ViewportList , C4Vec2D > ( : : Viewports , C4Vec2D ( 0 , + 5 ) , & C4ViewportList : : FreeScroll ) ) ) ;
2009-05-08 13:28:41 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_TAB ) , " ScoreboardToggle " , KEYSCOPE_Generic , new C4KeyCB < C4Scoreboard > ( Scoreboard , & C4Scoreboard : : KeyUserShow ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_ESCAPE ) , " GameAbort " , KEYSCOPE_Fullscreen , new C4KeyCB < C4FullScreen > ( FullScreen , & C4FullScreen : : ShowAbortDlg ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_PAUSE ) , " FullscreenPauseToggle " , KEYSCOPE_Fullscreen , new C4KeyCB < C4Game > ( Game , & C4Game : : TogglePause ) ) ) ;
// console keys
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_PAUSE ) , " ConsolePauseToggle " , KEYSCOPE_Console , new C4KeyCB < C4Console > ( Console , & C4Console : : TogglePause ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_SPACE ) , " EditCursorModeToggle " , KEYSCOPE_Console , new C4KeyCB < C4EditCursor > ( Console . EditCursor , & C4EditCursor : : ToggleMode ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_ADD ) , " ToolsDlgGradeUp " , KEYSCOPE_Console , new C4KeyCBEx < C4ToolsDlg , int32_t > ( Console . ToolsDlg , + 5 , & C4ToolsDlg : : ChangeGrade ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_SUBTRACT ) , " ToolsDlgGradeDown " , KEYSCOPE_Console , new C4KeyCBEx < C4ToolsDlg , int32_t > ( Console . ToolsDlg , - 5 , & C4ToolsDlg : : ChangeGrade ) ) ) ;
2013-05-26 11:06:21 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_M , KEYS_Control ) , " ToolsDlgPopMaterial " , KEYSCOPE_Console , new C4KeyCB < C4ToolsDlg > ( Console . ToolsDlg , & C4ToolsDlg : : PopMaterial ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_T , KEYS_Control ) , " ToolsDlgPopTextures " , KEYSCOPE_Console , new C4KeyCB < C4ToolsDlg > ( Console . ToolsDlg , & C4ToolsDlg : : PopTextures ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_I , KEYS_Control ) , " ToolsDlgIFTToggle " , KEYSCOPE_Console , new C4KeyCB < C4ToolsDlg > ( Console . ToolsDlg , & C4ToolsDlg : : ToggleIFT ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_W , KEYS_Control ) , " ToolsDlgToolToggle " , KEYSCOPE_Console , new C4KeyCB < C4ToolsDlg > ( Console . ToolsDlg , & C4ToolsDlg : : ToggleTool ) ) ) ;
2009-05-08 13:28:41 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( K_DELETE ) , " EditCursorDelete " , KEYSCOPE_Console , new C4KeyCB < C4EditCursor > ( Console . EditCursor , & C4EditCursor : : Delete ) ) ) ;
// no default keys assigned
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( KEY_Default ) , " ChartToggle " , C4KeyScope ( KEYSCOPE_Generic | KEYSCOPE_Gui ) , new C4KeyCB < C4Game > ( * this , & C4Game : : ToggleChart ) ) ) ;
2010-09-29 01:44:05 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( KEY_Default ) , " NetObsNextPlayer " , KEYSCOPE_FreeView , new C4KeyCB < C4ViewportList > ( : : Viewports , & C4ViewportList : : ViewportNextPlayer ) ) ) ;
2009-05-08 13:28:41 +00:00
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( KEY_Default ) , " CtrlRateDown " , KEYSCOPE_Generic , new C4KeyCBEx < C4GameControl , int32_t > ( Control , - 1 , & C4GameControl : : KeyAdjustControlRate ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( KEY_Default ) , " CtrlRateUp " , KEYSCOPE_Generic , new C4KeyCBEx < C4GameControl , int32_t > ( Control , + 1 , & C4GameControl : : KeyAdjustControlRate ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( KEY_Default ) , " NetAllowJoinToggle " , KEYSCOPE_Generic , new C4KeyCB < C4Network2 > ( Network , & C4Network2 : : ToggleAllowJoin ) ) ) ;
KeyboardInput . RegisterKey ( new C4CustomKey ( C4KeyCodeEx ( KEY_Default ) , " NetStatsToggle " , KEYSCOPE_Generic , new C4KeyCB < C4GraphicsSystem > ( GraphicsSystem , & C4GraphicsSystem : : ToggleShowNetStatus ) ) ) ;
// load any custom keysboard overloads
KeyboardInput . LoadCustomConfig ( ) ;
// done, success
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-05-26 06:10:38 +00:00
void C4Game : : UpdateLanguage ( )
2010-03-28 17:58:21 +00:00
{
2011-03-13 15:16:45 +00:00
// Reload System.ocg string table
2013-10-29 20:32:21 +00:00
C4Language : : LoadComponentHost ( & MainSysLangStringTable , Application . SystemGroup , C4CFN_ScriptStringTbl , Config . General . LanguageEx ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-26 06:10:38 +00:00
bool C4Game : : InitPlayerControlSettings ( )
2010-03-28 17:58:21 +00:00
{
2011-03-30 20:11:47 +00:00
// Load controls and default control sets
2009-05-26 06:10:38 +00:00
C4PlayerControlFile PlayerControlFile ;
if ( ! PlayerControlFile . Load ( Application . SystemGroup , C4CFN_PlayerControls , & MainSysLangStringTable ) ) { LogFatal ( " [!]Error loading player controls " ) ; return false ; }
PlayerControlDefs = PlayerControlFile . GetControlDefs ( ) ;
2011-03-30 20:11:47 +00:00
PlayerControlDefaultAssignmentSets . Clear ( ) ;
PlayerControlDefaultAssignmentSets . MergeFrom ( PlayerControlFile . GetAssignmentSets ( ) , C4PlayerControlAssignmentSet : : MM_Normal ) ;
PlayerControlDefaultAssignmentSets . ResolveRefs ( & PlayerControlDefs ) ;
// Merge w/ config settings into user control sets
// User settings will be cleared and re-merged again later after scenario/definition control overloads, but initialization
// is needed already for config dialogs
if ( ! InitPlayerControlUserSettings ( ) ) return false ;
return true ;
}
bool C4Game : : InitPlayerControlUserSettings ( )
{
// Merge config control settings with user settings
PlayerControlUserAssignmentSets . Clear ( ) ;
PlayerControlUserAssignmentSets . MergeFrom ( PlayerControlDefaultAssignmentSets , C4PlayerControlAssignmentSet : : MM_Inherit ) ;
PlayerControlUserAssignmentSets . MergeFrom ( Config . Controls . UserSets , C4PlayerControlAssignmentSet : : MM_ConfigOverload ) ;
PlayerControlUserAssignmentSets . ResolveRefs ( & PlayerControlDefs ) ;
2009-05-26 06:10:38 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-26 06:10:38 +00:00
2009-05-08 13:28:41 +00:00
C4Player * C4Game : : JoinPlayer ( const char * szFilename , int32_t iAtClient , const char * szAtClientName , C4PlayerInfo * pInfo )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
assert ( pInfo ) ;
C4Player * pPlr ;
// Join
2011-03-26 22:59:35 +00:00
if ( ! ( pPlr = Players . Join ( szFilename , true , iAtClient , szAtClientName , pInfo , NULL ) ) ) return NULL ;
2009-05-08 13:28:41 +00:00
// Player final init
2009-08-15 18:50:32 +00:00
pPlr - > FinalInit ( true ) ;
2009-05-08 13:28:41 +00:00
// Create player viewport
2010-09-29 01:44:05 +00:00
if ( pPlr - > LocalControl ) : : Viewports . CreateViewport ( pPlr - > Number ) ;
2009-05-08 13:28:41 +00:00
// Check fullscreen viewports
FullScreen . ViewportCheck ( ) ;
// Update menus
Console . UpdateMenus ( ) ;
// Append player name to list of session player names (no duplicates)
if ( ! SIsModule ( PlayerNames . getData ( ) , pPlr - > GetName ( ) ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
if ( PlayerNames ) PlayerNames + = " ; " ;
PlayerNames + = pPlr - > GetName ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Success
return pPlr ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : FixRandom ( int32_t iSeed )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
//sprintf(OSTR,"Fixing random to %i",iSeed); Log(OSTR);
FixedRandom ( iSeed ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : DoGameOver ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Duplication safety
2009-08-15 18:50:32 +00:00
if ( GameOver ) return false ;
2009-05-08 13:28:41 +00:00
// Flag, log, call
2009-08-15 18:50:32 +00:00
GameOver = true ;
2009-05-08 13:28:41 +00:00
Log ( LoadResStr ( " IDS_PRC_GAMEOVER " ) ) ;
2011-01-08 16:04:20 +00:00
: : GameScript . GRBroadcast ( PSF_OnGameOver ) ;
2010-03-27 16:05:02 +00:00
// Flag all surviving players as winners
2010-03-28 17:58:21 +00:00
for ( C4Player * pPlayer = Players . First ; pPlayer ; pPlayer = pPlayer - > Next )
if ( ! pPlayer - > Eliminated )
2010-03-27 16:05:02 +00:00
pPlayer - > EvaluateLeague ( false , true ) ;
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : ShowGameOverDlg ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
if ( GameOverDlgShown ) return ;
// flag, show
GameOverDlgShown = true ;
# ifdef USE_CONSOLE
// console engine quits here directly
Application . QuitGame ( ) ;
# else
2010-10-29 23:47:50 +00:00
if ( ! Application . isEditor )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
C4GameOverDlg * pDlg = new C4GameOverDlg ( ) ;
pDlg - > SetDelOnClose ( ) ;
if ( ! pDlg - > Show ( pGUI , true ) ) { delete pDlg ; Application . QuitGame ( ) ; }
}
2010-03-28 17:58:21 +00:00
# endif
}
2009-05-08 13:28:41 +00:00
void C4Game : : SyncClearance ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
PXS . SyncClearance ( ) ;
Objects . SyncClearance ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
void C4Game : : Synchronize ( bool fSavePlayerFiles )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Log
LogSilentF ( " Network: Synchronization (Frame %i) [PlrSave: %d] " , FrameCounter , fSavePlayerFiles ) ;
// callback to control (to start record)
Control . OnGameSynchronizing ( ) ;
// Fix random
FixRandom ( RandomSeed ) ;
// Synchronize members
2009-06-05 16:46:37 +00:00
: : Definitions . Synchronize ( ) ;
2009-05-08 13:28:41 +00:00
Landscape . Synchronize ( ) ;
MassMover . Synchronize ( ) ;
PXS . Synchronize ( ) ;
Objects . Synchronize ( ) ;
// synchronize local player files if desired
// this will reset any InActionTimes!
// (not in replay mode)
if ( fSavePlayerFiles & & ! Control . isReplay ( ) ) Players . SynchronizeLocalFiles ( ) ;
// callback to network
2010-03-28 17:58:21 +00:00
if ( Network . isEnabled ( ) ) Network . OnGameSynchronized ( ) ;
2009-05-08 13:28:41 +00:00
// TransferZone synchronization: Must do this after dynamic creation to avoid synchronization loss
// if UpdateTransferZone-callbacks do sync-relevant changes
TransferZones . Synchronize ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2009-08-15 18:50:32 +00:00
bool C4Game : : InitNetworkFromAddress ( const char * szAddress )
2009-05-08 13:28:41 +00:00
{
StdCopyStrBuf strRefQueryFailed ( LoadResStr ( " IDS_NET_REFQUERY_FAILED " ) ) ;
// Query reference
C4Network2RefClient RefClient ;
2010-03-28 17:58:21 +00:00
if ( ! RefClient . Init ( ) | |
! RefClient . SetServer ( szAddress ) | |
! RefClient . QueryReferences ( ) )
{ LogFatal ( FormatString ( strRefQueryFailed . getData ( ) , RefClient . GetError ( ) ) . getData ( ) ) ; return false ; }
2010-03-27 16:05:02 +00:00
// We have to wait for the answer
StdStrBuf Message = FormatString ( LoadResStr ( " IDS_NET_REFQUERY_QUERYMSG " ) , szAddress ) ;
Log ( Message . getData ( ) ) ;
// Set up wait dialog
2009-05-08 13:28:41 +00:00
C4GUI : : MessageDialog * pDlg = NULL ;
2010-10-29 23:47:50 +00:00
if ( ! Application . isEditor )
2009-05-08 13:28:41 +00:00
{
// create & show
pDlg = new C4GUI : : MessageDialog ( Message . getData ( ) , LoadResStr ( " IDS_NET_REFQUERY_QUERYTITLE " ) ,
2010-03-28 17:58:21 +00:00
C4GUI : : MessageDialog : : btnAbort , C4GUI : : Ico_NetWait , C4GUI : : MessageDialog : : dsMedium ) ;
if ( ! pDlg | | ! pDlg - > Show ( : : pGUI , true ) ) return false ;
2009-05-08 13:28:41 +00:00
}
// Wait for response
2010-03-28 17:58:21 +00:00
while ( RefClient . isBusy ( ) )
2010-03-27 16:05:02 +00:00
{
// Execute GUI
2010-03-28 17:58:21 +00:00
if ( ! Application . ScheduleProcs ( 100 ) | |
( pDlg & & pDlg - > IsAborted ( ) ) )
2010-03-27 16:05:02 +00:00
{
2010-10-29 23:47:50 +00:00
delete pDlg ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-27 16:05:02 +00:00
}
// Check if reference is received
2010-03-28 17:58:21 +00:00
if ( ! RefClient . Execute ( 0 ) )
2010-03-27 16:05:02 +00:00
break ;
}
// Close dialog
2010-10-29 23:47:50 +00:00
delete pDlg ;
2009-05-08 13:28:41 +00:00
// Error?
2010-03-28 17:58:21 +00:00
if ( ! RefClient . isSuccess ( ) )
2009-08-15 18:50:32 +00:00
{ LogFatal ( FormatString ( strRefQueryFailed . getData ( ) , RefClient . GetError ( ) ) . getData ( ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// Get references
C4Network2Reference * * ppRefs = NULL ; int32_t iRefCount ;
2010-03-28 17:58:21 +00:00
if ( ! RefClient . GetReferences ( ppRefs , iRefCount ) | | iRefCount < = 0 )
2009-08-15 18:50:32 +00:00
{ LogFatal ( FormatString ( strRefQueryFailed . getData ( ) , LoadResStr ( " IDS_NET_REFQUERY_NOREF " ) ) . getData ( ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// Connect to first reference
2009-08-15 18:50:32 +00:00
bool fSuccess = InitNetworkFromReference ( * ppRefs [ 0 ] ) ;
2009-05-08 13:28:41 +00:00
// Remove references
2010-03-28 17:58:21 +00:00
for ( int i = 0 ; i < iRefCount ; i + + )
2009-05-08 13:28:41 +00:00
delete ppRefs [ i ] ;
delete [ ] ppRefs ;
return fSuccess ;
}
2009-08-15 18:50:32 +00:00
bool C4Game : : InitNetworkFromReference ( const C4Network2Reference & Reference )
2009-05-08 13:28:41 +00:00
{
// Find host data
C4Client * pHostData = Reference . Parameters . Clients . getClientByID ( C4ClientIDHost ) ;
2010-03-28 17:58:21 +00:00
if ( ! pHostData ) { LogFatal ( LoadResStr ( " IDS_NET_INVALIDREF " ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// Save scenario title
ScenarioTitle = Reference . getTitle ( ) ;
// Log
LogF ( LoadResStr ( " IDS_NET_JOINGAMEBY " ) , pHostData - > getName ( ) ) ;
// Init clients
2010-03-28 17:58:21 +00:00
if ( ! Clients . Init ( ) )
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
// Connect
2010-03-28 17:58:21 +00:00
if ( Network . InitClient ( Reference , false ) ! = C4Network2 : : IR_Success )
{
2009-05-08 13:28:41 +00:00
LogFatal ( FormatString ( LoadResStr ( " IDS_NET_NOHOSTCON " ) , pHostData - > getName ( ) ) . getData ( ) ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// init control
2010-03-28 17:58:21 +00:00
if ( ! Control . InitNetwork ( Clients . getLocal ( ) ) ) return false ;
2009-05-08 13:28:41 +00:00
// init local player info list
Network . Players . Init ( ) ;
2009-08-15 18:50:32 +00:00
return true ;
2009-05-08 13:28:41 +00:00
}
2009-08-15 18:50:32 +00:00
bool C4Game : : InitNetworkHost ( )
2009-05-08 13:28:41 +00:00
{
// Network not active?
2010-03-28 17:58:21 +00:00
if ( ! NetworkActive )
{
2009-05-08 13:28:41 +00:00
// Clear client list
2010-03-28 17:58:21 +00:00
if ( ! C4S . Head . Replay )
2010-03-27 16:05:02 +00:00
Clients . Init ( ) ;
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// network not active?
2010-03-28 17:58:21 +00:00
if ( C4S . Head . NetworkGame )
2009-05-08 13:28:41 +00:00
{ LogFatal ( LoadResStr ( " IDS_NET_NODIRECTSTART " ) ) ; return Clients . Init ( ) ; }
// replay?
2010-03-28 17:58:21 +00:00
if ( C4S . Head . Replay )
2009-08-15 18:50:32 +00:00
{ LogFatal ( LoadResStr ( " IDS_PRC_NONETREPLAY " ) ) ; return true ; }
2009-05-08 13:28:41 +00:00
// clear client list
2010-03-28 17:58:21 +00:00
if ( ! Clients . Init ( ) )
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
// init network as host
2010-03-28 17:58:21 +00:00
if ( ! Network . InitHost ( fLobby ) ) return false ;
2009-05-08 13:28:41 +00:00
// init control
2010-03-28 17:58:21 +00:00
if ( ! Control . InitNetwork ( Clients . getLocal ( ) ) ) return false ;
2009-05-08 13:28:41 +00:00
// init local player info list
Network . Players . Init ( ) ;
// allow connect
Network . AllowJoin ( true ) ;
// do lobby (if desired)
2010-03-28 17:58:21 +00:00
if ( fLobby )
2009-05-08 13:28:41 +00:00
{
2010-03-28 17:58:21 +00:00
if ( ! Network . DoLobby ( ) ) return false ;
2009-05-08 13:28:41 +00:00
}
else
{
// otherwise: start manually
2010-03-28 17:58:21 +00:00
if ( ! Network . Start ( ) ) return false ;
2009-05-08 13:28:41 +00:00
}
// ok
2009-08-15 18:50:32 +00:00
return true ;
2009-05-08 13:28:41 +00:00
}
2009-08-15 18:50:32 +00:00
bool C4Game : : CheckObjectEnumeration ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Check valid & maximum number & duplicate numbers
int32_t iMax = 0 ;
2010-03-27 16:05:02 +00:00
C4Object * cObj ; C4ObjectLink * clnk ;
C4Object * cObj2 ; C4ObjectLink * clnk2 ;
2009-05-08 13:28:41 +00:00
clnk = Objects . First ; if ( ! clnk ) clnk = Objects . InactiveObjects . First ;
while ( clnk )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// Invalid number
cObj = clnk - > Obj ;
if ( cObj - > Number < 1 )
2010-03-28 17:58:21 +00:00
{
2010-01-25 15:57:57 +00:00
LogFatal ( FormatString ( " Invalid object enumeration number (%d) of object %s (x=%d) " , cObj - > Number , cObj - > id . ToString ( ) , cObj - > GetX ( ) ) . getData ( ) ) ; return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Max
if ( cObj - > Number > iMax ) iMax = cObj - > Number ;
// Duplicate
for ( clnk2 = Objects . First ; clnk2 & & ( cObj2 = clnk2 - > Obj ) ; clnk2 = clnk2 - > Next )
if ( cObj2 ! = cObj )
if ( cObj - > Number = = cObj2 - > Number )
2009-08-15 18:50:32 +00:00
{ LogFatal ( FormatString ( " Duplicate object enumeration number %d (%s and %s) " , cObj2 - > Number , cObj - > GetName ( ) , cObj2 - > GetName ( ) ) . getData ( ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
for ( clnk2 = Objects . InactiveObjects . First ; clnk2 & & ( cObj2 = clnk2 - > Obj ) ; clnk2 = clnk2 - > Next )
if ( cObj2 ! = cObj )
if ( cObj - > Number = = cObj2 - > Number )
2009-08-15 18:50:32 +00:00
{ LogFatal ( FormatString ( " Duplicate object enumeration number %d (%s and %s(i)) " , cObj2 - > Number , cObj - > GetName ( ) , cObj2 - > GetName ( ) ) . getData ( ) ) ; return false ; }
2009-05-08 13:28:41 +00:00
// next
if ( ! clnk - > Next )
2010-03-28 17:58:21 +00:00
if ( clnk = = Objects . Last ) clnk = Objects . InactiveObjects . First ; else clnk = NULL ;
2009-05-08 13:28:41 +00:00
else
clnk = clnk - > Next ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// Adjust enumeration index
2011-03-27 22:15:06 +00:00
C4PropListNumbered : : SetEnumerationIndex ( iMax ) ;
2009-05-08 13:28:41 +00:00
// Done
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : InitValueOverloads ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
C4ID idOvrl ; C4Def * pDef ;
// set new values
2010-01-25 04:00:59 +00:00
for ( int32_t cnt = 0 ; ( idOvrl = C4S . Game . Realism . ValueOverloads . GetID ( cnt ) ) ; cnt + + )
if ( ( pDef = : : Definitions . ID2Def ( idOvrl ) ) )
2009-05-08 13:28:41 +00:00
pDef - > Value = C4S . Game . Realism . ValueOverloads . GetIDCount ( idOvrl ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : InitEnvironment ( )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
// Place environment objects
int32_t cnt , cnt2 ;
C4ID idType ; int32_t iCount ;
for ( cnt = 0 ; ( idType = C4S . Environment . Objects . GetID ( cnt , & iCount ) ) ; cnt + + )
for ( cnt2 = 0 ; cnt2 < iCount ; cnt2 + + )
CreateObject ( idType , NULL ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : InitRules ( )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
// Place rule objects
int32_t cnt , cnt2 ;
C4ID idType ; int32_t iCount ;
for ( cnt = 0 ; ( idType = Parameters . Rules . GetID ( cnt , & iCount ) ) ; cnt + + )
for ( cnt2 = 0 ; cnt2 < Max < int32_t > ( iCount , 1 ) ; cnt2 + + )
CreateObject ( idType , NULL ) ;
2009-05-08 13:28:41 +00:00
// Update rule flags
UpdateRules ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : InitGoals ( )
2010-03-28 17:58:21 +00:00
{
2010-03-27 16:05:02 +00:00
// Place goal objects
int32_t cnt , cnt2 ;
C4ID idType ; int32_t iCount ;
for ( cnt = 0 ; ( idType = Parameters . Goals . GetID ( cnt , & iCount ) ) ; cnt + + )
for ( cnt2 = 0 ; cnt2 < iCount ; cnt2 + + )
CreateObject ( idType , NULL ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : UpdateRules ( )
2010-03-28 17:58:21 +00:00
{
2009-06-12 18:52:21 +00:00
if ( : : Game . iTick255 ) return ;
2009-05-08 13:28:41 +00:00
Rules = 0 ;
2010-01-25 03:14:52 +00:00
if ( ObjectCount ( C4ID : : CnMaterial ) ) Rules | = C4RULE_ConstructionNeedsMaterial ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : SetInitProgress ( float fToProgress )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// set new progress
InitProgress = int32_t ( fToProgress ) ;
// if progress is more than one percent, display it
if ( InitProgress > LastInitProgress )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
LastInitProgress = InitProgress ;
2011-03-13 16:25:35 +00:00
LastInitProgressShowTime = GetTime ( ) ;
2009-05-08 13:28:41 +00:00
GraphicsSystem . MessageBoard . LogNotify ( ) ;
2010-03-28 17:58:21 +00:00
}
2010-03-05 00:13:06 +00:00
// Cheap hack to get the Console window updated while loading
Application . FlushMessages ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : OnResolutionChanged ( unsigned int iXRes , unsigned int iYRes )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// update anything that's dependant on screen resolution
2010-10-29 23:47:50 +00:00
pGUI - > SetBounds ( C4Rect ( 0 , 0 , iXRes , iYRes ) ) ;
2009-05-08 13:28:41 +00:00
if ( FullScreen . Active )
InitFullscreenComponents ( ! ! IsRunning ) ;
// note that this may fail if the gfx groups are closed already (runtime resolution change)
// doesn't matter; old gfx are kept in this case
GraphicsResource . ReloadResolutionDependantFiles ( ) ;
2010-09-29 01:44:05 +00:00
: : Viewports . RecalculateViewports ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2012-10-08 22:54:34 +00:00
void C4Game : : OnKeyboardLayoutChanged ( )
{
// Layout changed: Re-resolve keys
PlayerControlDefaultAssignmentSets . ResolveRefs ( & PlayerControlDefs ) ;
PlayerControlUserAssignmentSets . ResolveRefs ( & PlayerControlDefs ) ;
}
2009-08-15 18:50:32 +00:00
bool C4Game : : LoadScenarioSection ( const char * szSection , DWORD dwFlags )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// note on scenario section saving:
// if a scenario section overwrites a value that had used the default values in the main scenario section,
// returning to the main section with an unsaved landscape (and thus an unsaved scenario core),
// would leave those values in the altered state of the previous section
// scenario designers should regard this and always define any values, that are defined in subsections as well
C4Group hGroup , * pGrp ;
// find section to load
C4ScenarioSection * pLoadSect = pScenarioSections ;
2010-03-28 17:58:21 +00:00
while ( pLoadSect ) if ( SEqualNoCase ( pLoadSect - > szName , szSection ) ) break ; else pLoadSect = pLoadSect - > pNext ;
2009-05-08 13:28:41 +00:00
if ( ! pLoadSect )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLogF ( " LoadScenarioSection: scenario section %s not found! " , szSection ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// don't load if it's current
if ( pLoadSect = = pCurrentScenarioSection )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLogF ( " LoadScenarioSection: section %s is already current " , szSection ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// if current section was the loaded section (maybe main, but need not for resumed savegames)
if ( ! pCurrentScenarioSection )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
pCurrentScenarioSection = new C4ScenarioSection ( CurrentScenarioSection ) ;
if ( ! * CurrentScenarioSection ) SCopy ( C4ScenSect_Main , CurrentScenarioSection , C4MaxName ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// save current section state
if ( dwFlags & ( C4S_SAVE_LANDSCAPE | C4S_SAVE_OBJECTS ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// ensure that the section file does point to temp store
if ( ! pCurrentScenarioSection - > EnsureTempStore ( ! ( dwFlags & C4S_SAVE_LANDSCAPE ) , ! ( dwFlags & C4S_SAVE_OBJECTS ) ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLogF ( " LoadScenarioSection(%s): could not extract section files of current section %s " , szSection , pCurrentScenarioSection - > szName ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// open current group
if ( ! ( pGrp = pCurrentScenarioSection - > GetGroupfile ( hGroup ) ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLog ( " LoadScenarioSection: error opening current group file " ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// store landscape, if desired (w/o material enumeration - that's assumed to stay consistent during the game)
if ( dwFlags & C4S_SAVE_LANDSCAPE )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// storing the landscape implies storing the scenario core
// otherwise, the ExactLandscape-flag would be lost
// maybe imply exact landscapes by the existance of Landscape.png-files?
C4Scenario rC4S = C4S ;
rC4S . SetExactLandscape ( ) ;
if ( ! rC4S . Save ( * pGrp , true ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLog ( " LoadScenarioSection: Error saving C4S " ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// landscape
{
C4DebugRecOff DBGRECOFF ;
if ( ! Landscape . Save ( * pGrp ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLog ( " LoadScenarioSection: Error saving Landscape " ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
}
// PXS
if ( ! PXS . Save ( * pGrp ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLog ( " LoadScenarioSection: Error saving PXS " ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// MassMover (create copy, may not modify running data)
C4MassMoverSet MassMoverSet ;
MassMoverSet . Copy ( MassMover ) ;
if ( ! MassMoverSet . Save ( * pGrp ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLog ( " LoadScenarioSection: Error saving MassMover " ) ;
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// store objects
if ( dwFlags & C4S_SAVE_OBJECTS )
2010-03-28 17:58:21 +00:00
{
2011-03-26 22:59:35 +00:00
C4ValueNumbers numbers ;
2009-05-08 13:28:41 +00:00
// objects: do not save info objects or inactive objects
2011-09-19 19:00:55 +00:00
if ( ! SaveData ( * pGrp , true , false , & numbers ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLog ( " LoadScenarioSection: Error saving objects " ) ;
2009-08-15 18:50:32 +00:00
return false ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// close current group
if ( hGroup . IsOpen ( ) ) hGroup . Close ( ) ;
// mark modified
pCurrentScenarioSection - > fModified = true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// open section group
if ( ! ( pGrp = pLoadSect - > GetGroupfile ( hGroup ) ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLog ( " LoadScenarioSection: error opening group file " ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// remove all objects (except inactive)
// do correct removal calls, because this will stop fire sounds, etc.
C4ObjectLink * clnk ;
for ( clnk = Objects . First ; clnk ; clnk = clnk - > Next ) clnk - > Obj - > AssignRemoval ( ) ;
for ( clnk = Objects . First ; clnk ; clnk = clnk - > Next )
if ( clnk - > Obj - > Status )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLogF ( " LoadScenarioSection: WARNING: Object %d created in destruction process! " , ( int ) clnk - > Obj - > Number ) ;
ClearPointers ( clnk - > Obj ) ;
//clnk->Obj->AssignRemoval(); - this could create additional objects in endless recursion...
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
DeleteObjects ( false ) ;
// remove global effects
if ( pGlobalEffects ) if ( ~ dwFlags | C4S_KEEP_EFFECTS )
{
2010-03-28 17:58:21 +00:00
pGlobalEffects - > ClearAll ( NULL , C4FxCall_RemoveClear ) ;
// scenario section call might have been done from a global effect
// rely on dead effect removal for actually removing the effects; do not clear the array here!
//delete pGlobalEffects; pGlobalEffects=NULL;
2009-05-08 13:28:41 +00:00
}
// del particles as well
Particles . ClearParticles ( ) ;
// clear transfer zones
TransferZones . Clear ( ) ;
// backup old sky
char szOldSky [ C4MaxDefString + 1 ] ;
SCopy ( C4S . Landscape . SkyDef , szOldSky , C4MaxDefString ) ;
// overload scenario values (fails if no scenario core is present; that's OK)
2010-03-27 16:05:02 +00:00
C4S . Load ( * pGrp , true ) ;
2009-05-08 13:28:41 +00:00
// determine whether a new sky has to be loaded
bool fLoadNewSky = ! SEqualNoCase ( szOldSky , C4S . Landscape . SkyDef ) | | pGrp - > FindEntry ( C4CFN_Sky " .* " ) ;
// re-init game in new section
2011-03-26 22:59:35 +00:00
C4ValueNumbers numbers ;
if ( ! InitGame ( * pGrp , true , fLoadNewSky , & numbers ) )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
DebugLog ( " LoadScenarioSection: Error reiniting game " ) ;
2009-08-15 18:50:32 +00:00
return false ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// set new current section
pCurrentScenarioSection = pLoadSect ;
SCopy ( pCurrentScenarioSection - > szName , CurrentScenarioSection ) ;
// resize viewports
2010-09-29 01:44:05 +00:00
: : Viewports . RecalculateViewports ( ) ;
2009-05-08 13:28:41 +00:00
// done, success
2009-08-15 18:50:32 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : ToggleDebugMode ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// debug mode not allowed
if ( ! Parameters . AllowDebug & & ! DebugMode ) { GraphicsSystem . FlashMessage ( LoadResStr ( " IDS_MSG_DEBUGMODENOTALLOWED " ) ) ; return false ; }
Toggle ( DebugMode ) ;
if ( ! DebugMode ) GraphicsSystem . DeactivateDebugOutput ( ) ;
GraphicsSystem . FlashMessageOnOff ( LoadResStr ( " IDS_CTL_DEBUGMODE " ) , DebugMode ) ;
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : ActivateMenu ( const char * szCommand )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// no new menu during round evaluation
if ( C4GameOverDlg : : IsShown ( ) ) return false ;
// forward to primary player
2009-06-12 23:09:32 +00:00
C4Player * pPlr = : : Players . GetLocalByIndex ( 0 ) ;
2009-05-08 13:28:41 +00:00
if ( ! pPlr ) return false ;
2010-03-27 16:05:02 +00:00
pPlr - > Menu . ActivateCommand ( pPlr - > Number , szCommand ) ;
2009-05-08 13:28:41 +00:00
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : ToggleChart ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
C4ChartDialog : : Toggle ( ) ;
return true ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
void C4Game : : Abort ( bool fApproved )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// league needs approval
2010-03-28 17:58:21 +00:00
if ( Network . isEnabled ( ) & & Parameters . isLeague ( ) & & ! fApproved )
{
if ( Control . isCtrlHost ( ) & & ! Game . GameOver )
2009-05-08 13:28:41 +00:00
{
Network . Vote ( VT_Cancel ) ;
return ;
2010-03-28 17:58:21 +00:00
}
if ( ! Control . isCtrlHost ( ) & & ! Game . GameOver & & : : Players . GetLocalByIndex ( 0 ) )
{
2009-05-08 13:28:41 +00:00
Network . Vote ( VT_Kick , true , Control . ClientID ( ) ) ;
return ;
}
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
// hard-abort: eval league and quit
// manually evaluate league
Players . RemoveLocal ( true , true ) ;
Players . RemoveAtRemoteClient ( true , true ) ;
// normal quit
Application . QuitGame ( ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
2012-01-10 21:40:46 +00:00
bool GetTextSpecFacet ( const char * szSpec , C4Facet & fct )
2010-01-30 09:17:40 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
2010-01-30 09:17:40 +00:00
assert ( szSpec & & * szSpec ) ;
2009-05-08 13:28:41 +00:00
if ( ! szSpec ) return false ;
2010-01-30 09:17:40 +00:00
// Special icon?
if ( SEqual2 ( szSpec , " @Ico: " ) )
{
szSpec + = 5 ;
if ( SEqual2 ( szSpec , " Locked " ) )
2012-01-10 21:40:46 +00:00
fct = C4GUI : : Icon : : GetIconFacet ( C4GUI : : Ico_Ex_LockedFrontal ) ;
2010-01-30 09:17:40 +00:00
else if ( SEqual2 ( szSpec , " League " ) )
2012-01-10 21:40:46 +00:00
fct = C4GUI : : Icon : : GetIconFacet ( C4GUI : : Ico_Ex_League ) ;
2010-01-30 09:17:40 +00:00
else if ( SEqual2 ( szSpec , " GameRunning " ) )
2012-01-10 21:40:46 +00:00
fct = C4GUI : : Icon : : GetIconFacet ( C4GUI : : Ico_GameRunning ) ;
2010-01-30 09:17:40 +00:00
else if ( SEqual2 ( szSpec , " Lobby " ) )
2012-01-10 21:40:46 +00:00
fct = C4GUI : : Icon : : GetIconFacet ( C4GUI : : Ico_Lobby ) ;
2010-01-30 09:17:40 +00:00
else if ( SEqual2 ( szSpec , " RuntimeJoin " ) )
2012-01-10 21:40:46 +00:00
fct = C4GUI : : Icon : : GetIconFacet ( C4GUI : : Ico_RuntimeJoin ) ;
else
return false ;
return true ;
}
return false ;
}
bool C4Game : : DrawTextSpecImage ( C4Facet & fctTarget , const char * szSpec , C4DrawTransform * pTransform , uint32_t dwClr )
{
// safety
assert ( szSpec & & * szSpec ) ;
if ( ! szSpec ) return false ;
C4Facet fctSource ;
if ( GetTextSpecFacet ( szSpec , fctSource ) )
{
fctSource . DrawXT ( fctTarget . Surface , fctTarget . X , fctTarget . Y , fctTarget . Wdt , fctTarget . Hgt , 0 , 0 , pTransform ) ;
return true ;
2010-01-30 09:17:40 +00:00
}
else
{
2012-01-10 21:40:46 +00:00
C4Def * pDef = C4Id2Def ( C4ID ( szSpec ) ) ;
if ( ! pDef ) return false ;
pDef - > Draw ( fctTarget , false , dwClr , NULL , 0 , 0 , pTransform ) ;
return true ;
}
}
float C4Game : : GetTextSpecImageAspect ( const char * szSpec )
{
// safety
assert ( szSpec & & * szSpec ) ;
if ( ! szSpec ) return - 1.0f ;
C4Facet fctSource ;
if ( GetTextSpecFacet ( szSpec , fctSource ) )
{
return static_cast < float > ( fctSource . Wdt ) / static_cast < float > ( fctSource . Hgt ) ;
}
else
{
C4Def * pDef = C4Id2Def ( C4ID ( szSpec ) ) ;
if ( ! pDef ) return - 1.0f ;
C4DefGraphics * pGfx = & pDef - > Graphics ;
if ( pGfx - > Type = = C4DefGraphics : : TYPE_Bitmap )
2010-01-30 09:17:40 +00:00
{
2012-01-10 21:40:46 +00:00
return static_cast < float > ( pDef - > PictureRect . Wdt ) / static_cast < float > ( pDef - > PictureRect . Hgt ) ;
2010-01-30 09:17:40 +00:00
}
else
{
2012-01-10 21:40:46 +00:00
const StdMesh & mesh = * pGfx - > Mesh ;
const StdMeshBox & box = mesh . GetBoundingBox ( ) ;
// Note the bounding box is in OGRE frame of reference
return ( box . y2 - box . y1 ) / ( box . z2 - box . z1 ) ;
2009-05-08 13:28:41 +00:00
}
2010-02-07 18:17:47 +00:00
2012-01-10 21:40:46 +00:00
return - 1.0f ;
}
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : SpeedUp ( )
{
// As these functions work stepwise, there's the old maximum speed of 50.
// Use /fast to set to even higher speeds.
FrameSkip = BoundBy < int32_t > ( FrameSkip + 1 , 1 , 50 ) ;
2009-08-15 18:50:32 +00:00
FullSpeed = true ;
2009-05-11 13:09:53 +00:00
GraphicsSystem . FlashMessage ( FormatString ( LoadResStr ( " IDS_MSG_SPEED " ) , FrameSkip ) . getData ( ) ) ;
2009-05-08 13:28:41 +00:00
return true ;
}
bool C4Game : : SlowDown ( )
{
FrameSkip = BoundBy < int32_t > ( FrameSkip - 1 , 1 , 50 ) ;
if ( FrameSkip = = 1 )
2009-08-15 18:50:32 +00:00
FullSpeed = false ;
2009-05-11 13:09:53 +00:00
GraphicsSystem . FlashMessage ( FormatString ( LoadResStr ( " IDS_MSG_SPEED " ) , FrameSkip ) . getData ( ) ) ;
2009-05-08 13:28:41 +00:00
return true ;
}
void C4Game : : SetMusicLevel ( int32_t iToLvl )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
// change game music volume; multiplied by config volume for real volume
iMusicLevel = BoundBy < int32_t > ( iToLvl , 0 , 100 ) ;
Application . MusicSystem . SetVolume ( Config . Sound . MusicVolume * iMusicLevel / 100 ) ;
2010-03-28 17:58:21 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4Game : : ToggleChat ( )
2010-03-28 17:58:21 +00:00
{
2009-05-08 13:28:41 +00:00
return C4ChatDlg : : ToggleChat ( ) ;
2010-03-28 17:58:21 +00:00
}