OpenClonk
C4Game.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Main class to run the game */
19 
20 #include "C4Include.h"
22 #include "game/C4Game.h"
23 
24 #include "C4Version.h"
25 #include "control/C4GameControl.h"
27 #include "control/C4GameSave.h"
29 #include "control/C4PlayerInfo.h"
30 #include "control/C4Record.h"
31 #include "control/C4RoundResults.h"
32 #include "editor/C4Console.h"
33 #include "game/C4Application.h"
34 #include "game/C4FullScreen.h"
35 #include "game/C4GraphicsSystem.h"
36 #include "game/C4Viewport.h"
38 #include "gui/C4ChatDlg.h"
39 #include "gui/C4GameLobby.h"
40 #include "gui/C4GameMessage.h"
41 #include "gui/C4GameOverDlg.h"
42 #include "gui/C4LoaderScreen.h"
43 #include "gui/C4MessageInput.h"
44 #include "gui/C4MouseControl.h"
45 #include "gui/C4ScriptGuiWindow.h"
46 #include "gui/C4Startup.h"
47 #include "landscape/C4Landscape.h"
48 #include "landscape/C4MapScript.h"
49 #include "landscape/C4MassMover.h"
50 #include "landscape/C4Material.h"
51 #include "landscape/C4PXS.h"
52 #include "landscape/C4Particles.h"
53 #include "landscape/C4Sky.h"
54 #include "landscape/C4SolidMask.h"
55 #include "landscape/C4Texture.h"
56 #include "landscape/C4Weather.h"
57 #include "landscape/fow/C4FoW.h"
58 #include "lib/C4Random.h"
59 #include "lib/C4Stat.h"
60 #include "lib/StdMesh.h"
61 #include "network/C4League.h"
65 #include "object/C4Command.h"
66 #include "object/C4Def.h"
67 #include "object/C4DefList.h"
68 #include "object/C4GameObjects.h"
69 #include "object/C4Object.h"
70 #include "object/C4ObjectCom.h"
71 #include "object/C4ObjectInfo.h"
72 #include "object/C4ObjectMenu.h"
73 #include "platform/C4FileMonitor.h"
74 #include "player/C4Player.h"
75 #include "player/C4PlayerList.h"
76 #include "player/C4RankSystem.h"
77 #include "script/C4AulDebug.h"
78 #include "script/C4AulExec.h"
79 #include "script/C4Effect.h"
80 
81 #include <unordered_map>
82 
84 {
85 public:
87  ~C4GameSec1Timer() override { Application.Remove(this); }
88  void OnSec1Timer() override;
89 };
90 
91 static C4GameParameters GameParameters;
92 static C4ScenarioParameterDefs GameScenarioParameterDefs;
93 static C4ScenarioParameters GameStartupScenarioParameters;
94 static C4RoundResults GameRoundResults;
95 static C4Value GameGlobalSoundModifier;
96 
98  ScenarioParameterDefs(GameScenarioParameterDefs),
99  Parameters(GameParameters),
100  StartupScenarioParameters(GameStartupScenarioParameters),
101  Clients(Parameters.Clients),
102  Teams(Parameters.Teams),
103  PlayerInfos(Parameters.PlayerInfos),
104  RestorePlayerInfos(Parameters.RestorePlayerInfos),
105  RoundResults(GameRoundResults),
106  Input(Control.Input),
107  KeyboardInput(C4KeyboardInput_Init()),
108  pSec1Timer(new C4GameSec1Timer()),
109  GlobalSoundModifier(GameGlobalSoundModifier)
110 {
111  Default();
112 }
113 
115 {
116  // make sure no startup gfx remain loaded
118 }
119 
121 {
122  int32_t def_count = 0;
123  Log(LoadResStr("IDS_PRC_INITDEFS"));
124  int def_res_count = 0;
125  C4GameRes *def;
126  for (def = Parameters.GameRes.iterRes(nullptr, NRT_Definitions); def; def = Parameters.GameRes.iterRes(def, NRT_Definitions))
127  {
128  ++def_res_count;
129  }
130  int i = 0;
131  // Load specified defs
132  for (def = Parameters.GameRes.iterRes(nullptr, NRT_Definitions); def; def = Parameters.GameRes.iterRes(def, NRT_Definitions))
133  {
134  int min_progress = 25 + (25 * i) / def_res_count;
135  int max_progress = 25 + (25 * (i + 1)) / def_res_count;
136  ++i;
137  def_count += ::Definitions.Load(def->getFile(),C4D_Load_RX, Config.General.LanguageEx,&Application.SoundSystem, true, min_progress, max_progress);
138 
139  // Def load failure
140  if (::Definitions.LoadFailure)
141  {
142  return false;
143  }
144  }
145 
146  // Load for scenario file - ignore sys group here, because it has been loaded already
147  def_count += ::Definitions.Load(ScenarioFile, C4D_Load_RX, Config.General.LanguageEx,&Application.SoundSystem, true, true, 35, 40, false);
148 
149  // Absolutely no defs: we don't like that
150  if (!def_count)
151  {
152  LogFatal(LoadResStr("IDS_PRC_NODEFS"));
153  return false;
154  }
155 
156  // Check def engine version (should be done immediately on def load)
157  def_count = ::Definitions.CheckEngineVersion(C4XVER1, C4XVER2);
158  if (def_count > 0)
159  {
160  LogF(LoadResStr("IDS_PRC_DEFSINVC4X"),def_count);
161  }
162 
163  // Check for unmet requirements
165 
166  // build quick access table
168 
169  // handle skeleton appends and includes
171 
172  // Done
173  return true;
174 }
175 
176 
178 {
179 
180  // Scenario from record stream
181  if (RecordStream.getSize())
182  {
183  StdStrBuf RecordFile;
184  if (!C4Playback::StreamToRecord(RecordStream.getData(), &RecordFile))
185  {
186  LogFatal("[!] Could not process record stream data!");
187  return false;
188  }
189  SCopy(RecordFile.getData(), ScenarioFilename, _MAX_PATH);
190  }
191 
192  // Scenario filename check & log
193  if (!ScenarioFilename[0])
194  {
195  LogFatal(LoadResStr("IDS_PRC_NOC4S"));
196  return false;
197  }
198  LogF(LoadResStr("IDS_PRC_LOADC4S"),ScenarioFilename);
199 
200  // get parent folder, if it's ocf
202 
203  // open scenario
204  if (pParentGroup)
205  {
206  // open from parent group
208  {
209  LogF("%s: %s", LoadResStr("IDS_PRC_FILENOTFOUND"), (const char *)ScenarioFilename);
210  return false;
211  }
212  }
213  else
214  {
215  // open directly
217  {
218  LogF("%s: %s", LoadResStr("IDS_PRC_FILENOTFOUND"), (const char *)ScenarioFilename);
219  return false;
220  }
221  }
222 
223  // Remember full (absolute) path
225 
226  // add scenario to group
228 
229  // Read scenario core
230  if (!C4S.Load(ScenarioFile))
231  {
232  LogFatal(LoadResStr("IDS_PRC_FILEINVALID"));
233  return false;
234  }
235 
236  // Check minimum engine version
237  if (CompareVersion(C4S.Head.C4XVer[0],C4S.Head.C4XVer[1]) > 0)
238  {
239  LogFatal(FormatString(LoadResStr("IDS_PRC_NOREQC4X"), C4S.Head.C4XVer[0],C4S.Head.C4XVer[1]).getData());
240  return false;
241  }
242 
243  // Add scenario origin to group set
245  {
247  }
248 
249  // Scenario definition preset
250  StdStrBuf sDefinitionFilenames;
251  if (!C4S.Definitions.AllowUserChange && C4S.Definitions.GetModules(&sDefinitionFilenames))
252  {
253  SCopy(sDefinitionFilenames.getData(), DefinitionFilenames, (sizeof DefinitionFilenames)-1);
254  if (DefinitionFilenames[0])
255  {
256  Log(LoadResStr("IDS_PRC_SCEOWNDEFS"));
257  }
258  else
259  {
260  Log(LoadResStr("IDS_PRC_LOCALONLY"));
261  }
262  }
263 
264  // Check mission access
265 #ifndef USE_CONSOLE
266 #ifndef _DEBUG
267  if (C4S.Head.MissionAccess[0]
270  {
271  LogFatal(LoadResStr("IDS_PRC_NOMISSIONACCESS"));
272  return false;
273  }
274 #endif
275 #endif
276 
277  // Title
280  {
282  }
283 
284  // String tables
286 
287  // Custom scenario parameter definitions. Load even as network client to get localized option names
289 
290  // Load parameters (not as network client, because then team info has already been sent by host)
291  if (!Network.isEnabled() || Network.isHost())
292  {
294  {
295  return false;
296  }
297  }
298 
299  SetInitProgress(4);
300 
301  // If scenario is a directory: Watch for changes
303  {
304  Game.pFileMonitor->AddDirectory(ScenarioFile.GetFullName().getData());
305  }
306 
307  return true;
308 }
309 
311 {
312  // close scenario
315  pParentGroup = nullptr;
316  // remove if temporary
317  if (TempScenarioFile)
318  {
321  }
322  // clear scenario section
323  // this removes any temp files, which may yet need to be used by any future features
324  // so better don't do this too early (like, in C4Game::Clear)
325  if (pScenarioSections)
326  {
327  delete pScenarioSections;
329  }
330 }
331 
332 
334 {
335  // init extra root group
336  // this loads font definitions in this group as well
337  // the function may return false, if no extra group is present - that is OK
338  Extra.InitGroup();
339 
340  // Randomize
341  RandomSeed = time(nullptr);
343 
344  // Timer flags
345  GameGo = false;
346 
347  // init message input (default commands)
348  MessageInput.Init();
349  Game.SetInitProgress(31.0f);
350 
351  // init keyboard input (default keys, plus overloads)
352  if (!InitKeyboard())
353  {
354  LogFatal(LoadResStr("IDS_ERR_NOKEYBOARD"));
355  return false;
356  }
357 
358  // Load string table
359  UpdateLanguage();
360 
361  // Player keyboard input: Key definitions and default sets
363  {
364  return false;
365  }
366  Game.SetInitProgress(32.0f);
367 
368  // Rank system
369  ::DefaultRanks.Init(Config.GetSubkeyPath("ClonkRanks"), LoadResStr("IDS_GAME_DEFRANKS"), 1000);
370  Game.SetInitProgress(33.0f);
371 
372  // Graphics system (required for GUI)
373  if (!GraphicsSystem.Init())
374  {
375  LogFatal(LoadResStr("IDS_ERR_NOGFXSYS"));
376  return false;
377  }
378 
379  // load GUI
380 #ifndef USE_CONSOLE
381  C4Rect r;
382  if (Application.isEditor)
383  {
384  Console.GetSize(&r);
385  }
386  else
387  {
388  FullScreen.GetSize(&r);
389  }
390  pGUI->Init(0, 0, r.Wdt, r.Hgt);
391 #endif
392 
393  fPreinited = true;
394  return true;
395 }
396 
398 {
399  C4ValueNumbers numbers;
400  IsRunning = false;
401 
402  InitProgress = 0;
403  LastInitProgress = 0;
404  SetInitProgress(0);
405 
406  // reinit keyboard to reflect any config changes that might have been done
407  // this is a good time to do it, because no GUI dialogs are opened
408  if (!InitKeyboard())
409  {
410  LogFatal(LoadResStr("IDS_ERR_NOKEYBOARD"));
411  }
412 
413  // start log pos (used by startup)
415  fQuitWithError = false;
416  C4GameLobby::UserAbort = false;
417 
418  // Store a start time that identifies this game on this host
419  StartTime = time(nullptr);
420 
421  // Get PlayerFilenames from Config, if ParseCommandLine did not fill some in
422  // Must be done here, because InitGame calls PlayerInfos.InitLocal
423  if (!*PlayerFilenames)
424  {
426  }
427 
428  // Join a game?
430  {
431 
433  {
434  // init extra; needed for loader screen
435  Log(LoadResStr("IDS_PRC_INITEXTRA"));
436  if (!Extra.Init())
437  {
438  LogFatal(LoadResStr("IDS_PRC_ERREXTRA"));
439  return false;
440  }
441 
442  // init loader
444  {
445  LogFatal(LoadResStr("IDS_PRC_ERRLOADER"));
446  return false;
447  }
448  }
449 
450  SetInitProgress(5);
451 
452  // Initialize network
453  if (pJoinReference)
454  {
455  // By reference
456  bool success = InitNetworkFromReference(*pJoinReference);
457  pJoinReference.reset();
458  if (!success)
459  {
460  return false;
461  }
462  }
464  {
465  // By reference serialized to temp file
467  {
468  return false;
469  }
470  }
471  else
472  {
473  // By address
475  {
476  return false;
477  }
478  }
479 
480  // check wether console mode is allowed
482  {
483  LogFatal(LoadResStr("IDS_TEXT_JOININCONSOLEMODENOTALLOW"));
484  return false;
485  }
486 
487  // do lobby (if desired)
488  if (Network.isLobbyActive())
489  {
490  if (!Network.DoLobby())
491  {
492  return false;
493  }
494  }
495 
496  // get scenario
497  char scenario_filename[_MAX_PATH_LEN];
498  SetInitProgress(6);
499  if (!Network.RetrieveScenario(scenario_filename))
500  {
501  return false;
502  }
503 
504  // open new scenario
505  SCopy(scenario_filename, ScenarioFilename, _MAX_PATH);
506  if (!OpenScenario())
507  {
508  return false;
509  }
511 
512  // get everything else
514  {
515  return false;
516  }
517 
518  // Check network game data scenario type (safety)
519  if (!C4S.Head.NetworkGame)
520  {
521  LogFatal(LoadResStr("IDS_NET_NONETGAME"));
522  return false;
523  }
524 
525  SetInitProgress(7);
526 
527  }
528  // Local game or host?
529  else
530  {
531  // Open scenario
532  if (!OpenScenario())
533  {
534  LogFatal(LoadResStr("IDS_PRC_FAIL"));
535  return false;
536  }
537 
538  // init extra; needed for loader screen
539  Log(LoadResStr("IDS_PRC_INITEXTRA"));
540  if (!Extra.Init())
541  {
542  LogFatal(LoadResStr("IDS_PRC_ERREXTRA"));
543  return false;
544  }
545 
546  // init loader
548  {
549  LogFatal(LoadResStr("IDS_PRC_ERRLOADER"));
550  return false;
551  }
552 
553  // Init network
554  if (!InitNetworkHost())
555  {
556  return false;
557  }
558  SetInitProgress(7);
559  }
560 
561  // now free all startup gfx to make room for game gfx
563 
564  // Init debugmode
567  {
568  DebugMode = true;
569  }
570  if (!Parameters.AllowDebug)
571  {
572  DebugMode = false;
573  }
574 
575  // Init game
576  if (!InitGame(ScenarioFile, IM_Normal, true, &numbers))
577  {
578  return false;
579  }
580 
581  // Network final init
582  if (Network.isEnabled())
583  {
584  if (!Network.FinalInit())
585  {
586  return false;
587  }
588  }
589  // non-net may have to synchronize now to keep in sync with replays
590  // also needs to synchronize to update transfer zones
591  else
592  {
593  // - would kill DebugRec-sync for runtime debugrec starts
594  C4DebugRecOff DBGRECOFF(!!C4S.Head.SaveGame);
595  SyncClearance();
596  Synchronize(false);
597  }
598 
599  // Init players
600  if (!InitPlayers(&numbers))
601  {
602  return false;
603  }
604  SetInitProgress(98);
605 
606  // Final init
607  if (!InitGameFinal(IM_Normal))
608  {
609  return false;
610  }
611  SetInitProgress(99);
612 
613  // Sound modifier from savegames
615  {
617  }
618 
619  // Message board and upper board
620  if (!Application.isEditor)
621  {
623  }
624 
625  // Default fullscreen menu, in case any old surfaces are left (extra safety)
627 
628  // start statistics (always for now. Make this a config?)
629  pNetworkStatistics = std::make_unique<C4Network2Stats>();
630 
631  // clear loader screen
633  {
635  GraphicsSystem.pLoaderScreen = nullptr;
636  }
637 
638  // game running now!
639  IsRunning = true;
640 
641  // Start message
642  Log(LoadResStr(C4S.Head.NetworkGame ? "IDS_PRC_JOIN" : C4S.Head.SaveGame ? "IDS_PRC_RESUME" : "IDS_PRC_START"));
643 
644  // set non-exclusive GUI
645  pGUI->SetExclusive(false);
646 
647  // after GUI is made non-exclusive, recheck the scoreboard
648  Scoreboard.DoDlgShow(0, false);
649  SetInitProgress(100);
650 
651  // and redraw background
653 
654  // Notify editor
655  Console.InitGame();
656 
657  return true;
658 }
659 
660 void C4Game::SetScenarioFilename(const char * scenario_filename)
661 {
662  SCopy(scenario_filename, ScenarioFilename, _MAX_PATH);
663  if (SEqualNoCase(GetFilename(scenario_filename), "scenario.txt"))
664  {
666  {
667  *(GetFilename(ScenarioFilename) - 1) = 0;
668  }
669  }
670 }
671 
673 {
674  pFileMonitor.reset();
675 
676  // fade out music
678 
679  // game no longer running
680  IsRunning = false;
681  PointersDenumerated = false;
682 
684  // C4ST_RESET
685 
686  // Evaluation
687  if (GameOver)
688  {
689  if (!Evaluated)
690  {
691  Evaluate();
692  }
693  }
694 
695  // stop statistics
696  pNetworkStatistics.reset();
698 
699  // next mission (shoud have been transferred to C4Application now if next mission was desired)
700  NextMission.Clear();
703 
704  // Clear control
705  Network.Clear();
706  Control.Clear();
712 
713  // Clear game info
714  Scoreboard.Clear();
715  Players.Clear();
716  Parameters.Clear();
718  C4S.Clear();
721  Info.Clear();
722  Title.Clear();
723  Names.Clear();
724  GameText.Clear();
727 
728 #ifdef WITH_QT_EDITOR
729  // clear console pointers held into script engine
731  ::Console.ClearGamePointers();
732 #endif
733  // notify editor
734  Console.CloseGame();
735 
736  // Clear the particles before cleaning up the objects.
737  Particles.Clear();
738  // Clear the script GUI before cleaning up the objects.
739  // This prevents unnecessary ClearPointers callbacks when deleting the objects.
740  ScriptGuiRoot.reset();
741 
742  DeleteObjects(true);
743 
744  // exit gui
745  pGUI->Clear();
746 
747  // Clear landscape
748  Weather.Clear();
749  Landscape.Clear();
750  PXS.Clear();
752  TextureMap.Clear(); // texture map *MUST* be cleared after the materials, because of the patterns!
753  PathFinder.Clear();
755 
756  ::Messages.Clear();
758  SetGlobalSoundModifier(nullptr); // must be called before script engine clear
759  Application.SoundSystem.Modifiers.Clear(); // free some prop list pointers
760 
761  // Clear script engine
762  ::MapScript.Clear();
765  C4PropListNumbered::ClearShelve(); // may be nonempty if there was a fatal error during section load
767  pScenarioObjectsScript = nullptr;
768 
769  // delete any remaining prop lists from circular chains
772 
773  // Clear translation tables
776 
777  // Cleanup remaining open scenario files
778  CloseScenario();
779  GroupSet.Clear();
781  Application.SoundSystem.Clear(); // will be re-inited by application pre-init if running from startup system
782 
783  // Clear remaining graphics
784 #ifndef USE_CONSOLE
786 #endif
789 
790  // global fullscreen class is not cleared, because it holds the carrier window
791  // but the menu must be cleared (maybe move Fullscreen.Menu somewhere else?)
793 
794  // Message
795  // avoid double message by not printing it if no restbl is loaded
796  // this would log an "[Undefined]" only, anyway
797  // (could abort the whole clear-procedure here, btw?)
798  if (::Languages.HasStringTable())
799  {
800  Log(LoadResStr("IDS_CNS_GAMECLOSED"));
801  }
802 
803  // clear game starting parameters
805 
806  // join reference
807  pJoinReference.reset();
808 
809  // okay, game cleared now. Remember log section
810  QuitLogPos = GetLogPos();
811 
812  fPreinited = false;
814 
815  // FIXME: remove this
816  Default();
817 }
818 
820 {
821  // Only every 35 ticks
822  if (::Game.iTick35)
823  {
824  return false;
825  }
826 
827  // do not GameOver in replay
828  if (Control.isReplay())
829  {
830  return false;
831  }
832 
833  // All players eliminated: game over
834  bool all_players_eliminated = false;
836  {
837  all_players_eliminated = true;
838  }
839 
840  // Message
841  if (all_players_eliminated)
842  {
843  DoGameOver();
844  }
845 
846  return GameOver;
847 }
848 
849 C4ST_NEW(ControlRcvStat, "C4Game::Execute ReceiveControl")
850 C4ST_NEW(ControlStat, "C4Game::Execute ExecuteControl")
851 C4ST_NEW(ExecObjectsStat, "C4Game::Execute ExecObjects")
852 C4ST_NEW(GEStats, "C4Game::Execute pGlobalEffects->Execute")
853 C4ST_NEW(PXSStat, "C4Game::Execute PXS.Execute")
854 C4ST_NEW(DynPartStat, "C4Game::Execute Particles.Execute")
855 C4ST_NEW(MassMoverStat, "C4Game::Execute MassMover.Execute")
856 C4ST_NEW(WeatherStat, "C4Game::Execute Weather.Execute")
857 C4ST_NEW(PlayersStat, "C4Game::Execute Players.Execute")
858 C4ST_NEW(LandscapeStat, "C4Game::Execute Landscape.Execute")
859 C4ST_NEW(MusicSystemStat, "C4Game::Execute MusicSystem.Execute")
860 C4ST_NEW(MessagesStat, "C4Game::Execute Messages.Execute")
861 
862 #define EXEC_S(Expressions, Stat) \
863  { C4ST_START(Stat) Expressions C4ST_STOP(Stat) }
864 
865 #define EXEC_S_DR(Expressions, Stat, DebugRecName) { if (Config.General.DebugRec) AddDbgRec(RCT_Block, DebugRecName, 6); EXEC_S(Expressions, Stat) }
866 #define EXEC_DR(Expressions, DebugRecName) { if (Config.General.DebugRec) AddDbgRec(RCT_Block, DebugRecName, 6); Expressions }
867 
868 bool C4Game::Execute() // Returns true if the game is over
869 {
870  // Let's go
871  GameGo = true;
872 
873  // Network
874  Network.Execute();
875 
876  // Prepare control
877  bool control_prepared;
878  EXEC_S( control_prepared = Control.Prepare(); , ControlStat )
879  if (!control_prepared)
880  {
881  return false; // not ready yet: wait
882  }
883 
884  // Halt
885  if (HaltCount)
886  {
887  return false;
888  }
889 
890  if (Config.General.DebugRec)
891  {
893  }
894 
895  // Execute the control
896  Control.Execute();
897  if (!IsRunning)
898  {
899  return false;
900  }
901 
902  // Ticks
903  EXEC_DR( Ticks(); , "Ticks")
904 
905  if (Config.General.DebugRec)
906  {
907  // debugrec
908  AddDbgRec(RCT_DbgFrame, &FrameCounter, sizeof(int32_t));
909  }
910 
911  // 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
913 
914  // Game
915 
916  EXEC_S( ExecObjects(); , ExecObjectsStat )
919  , GEStats , "GEEx\0");
920  EXEC_S_DR( PXS.Execute(); , PXSStat , "PXSEx")
921  EXEC_S_DR( MassMover.Execute(); , MassMoverStat , "MMvEx")
922  EXEC_S_DR( Weather.Execute(); , WeatherStat , "WtrEx")
923  EXEC_S_DR( Landscape.Execute(); , LandscapeStat , "LdsEx")
924  EXEC_S_DR( Players.Execute(); , PlayersStat , "PlrEx")
925  EXEC_S_DR( ::Messages.Execute(); , MessagesStat , "MsgEx")
926 
927  EXEC_DR( MouseControl.Execute(); , "Input")
928 
929  EXEC_DR( GameOverCheck(); , "Misc\0")
930 
932 
933  // Evaluation; Game over dlg
934  if (GameOver)
935  {
936  if (!Evaluated)
937  {
938  Evaluate();
939  }
940  if (!GameOverDlgShown)
941  {
942  ShowGameOverDlg();
943  }
944  }
945 
946  // show stat each 1000 ticks
947  if (!(FrameCounter % 1000))
948  {
951  }
952 
953  if (Config.General.DebugRec)
954  {
955  AddDbgRec(RCT_Block, "eGame", 6);
957  }
958 
959  return true;
960 }
961 
962 void C4Game::InitFullscreenComponents(bool is_running)
963 {
964  // It can happen that this is called before graphics are loaded due to
965  // an early OnResolutionChanged() call. Ignore it, the message board,
966  // upper board and viewports will be initialized within the regular
967  // startup sequence then.
969  {
970  return;
971  }
972 
973  // fullscreen message board
974  C4Facet cgo;
976  GraphicsSystem.MessageBoard->Init(cgo, !is_running);
977  if (is_running)
978  {
979  // running game: Message board upper board and viewports
980  C4Facet cgo2;
984  }
985 }
986 
988 {
989  // Clear old data
990  TextureMap.Clear();
992 
993  // Check for scenario local materials
994  bool has_local_materials = Game.ScenarioFile.FindEntry(C4CFN_Material);
995 
996  // Load all materials
997  C4GameRes *material_resource = nullptr;
998  bool first = true;
999  bool overload_materials = true;
1000  bool overload_textures = true;
1001  long tex_count = 0;
1002  long mat_count = 0;
1003  while (overload_materials || overload_textures)
1004  {
1005 
1006  // Are there any scenario local materials that need to be looked at firs?
1007  C4Group materials;
1008  if (has_local_materials)
1009  {
1010  if (!materials.OpenAsChild(&Game.ScenarioFile, C4CFN_Material))
1011  {
1012  return false;
1013  }
1014  // Once only
1015  has_local_materials = false;
1016  }
1017  else
1018  {
1019  // Find next external material source
1020  material_resource = Game.Parameters.GameRes.iterRes(material_resource, NRT_Material);
1021  if (!material_resource)
1022  {
1023  break;
1024  }
1025  if (!Reloc.Open(materials, material_resource->getFile()))
1026  {
1027  return false;
1028  }
1029  }
1030 
1031  // Texture loader will access out of order. Pre-cache the small text-files to prevent rewind.
1032  materials.PreCacheEntries(C4CFN_TexMap);
1033  materials.PreCacheEntries(C4CFN_MaterialFiles, true);
1034 
1035  // First material file? Load texture map.
1036  bool continue_overload_materials = false;
1037  bool continue_overload_textures = false;
1038  if (first)
1039  {
1040  long tme_count = TextureMap.LoadMap(materials, C4CFN_TexMap, &continue_overload_materials, &continue_overload_textures);
1041  LogF(LoadResStr("IDS_PRC_TEXMAPENTRIES"), tme_count);
1042  // Only once
1043  first = false;
1044  }
1045  else
1046  {
1047  // Check overload-flags only
1048  if (!C4TextureMap::LoadFlags(materials, C4CFN_TexMap, &continue_overload_materials, &continue_overload_textures))
1049  {
1050  overload_materials = overload_textures = false;
1051  }
1052  }
1053 
1054  // Load textures
1055  if (overload_textures)
1056  {
1057  int local_text_count = TextureMap.LoadTextures(materials);
1058  // Automatically continue search if no texture was found
1059  if (!local_text_count)
1060  {
1061  continue_overload_textures = true;
1062  }
1063  tex_count += local_text_count;
1064  }
1065 
1066  // Load materials
1067  if (overload_materials)
1068  {
1069  int local_mat_count = ::MaterialMap.Load(materials);
1070  // Automatically continue search if no material was found
1071  if (!local_mat_count)
1072  {
1073  continue_overload_materials = true;
1074  }
1075  mat_count += local_mat_count;
1076  }
1077 
1078  // Set flags
1079  overload_textures = continue_overload_textures;
1080  overload_materials = continue_overload_materials;
1081  }
1082 
1083  // Logs
1084  LogF(LoadResStr("IDS_PRC_TEXTURES"), tex_count);
1085  LogF(LoadResStr("IDS_PRC_MATERIALS"), mat_count);
1086 
1087  // Load material enumeration
1089  {
1090  LogFatal(LoadResStr("IDS_PRC_NOMATENUM"));
1091  return false;
1092  }
1093 
1094  // Initialize texture map
1095  TextureMap.Init();
1096 
1097  // Cross map mats (after texture init, because Material-Texture-combinations are used)
1099  {
1100  return false;
1101  }
1102 
1103  // get material script funcs
1105 
1106  return true;
1107 }
1108 
1110 {
1111  // May not call Objects.ClearPointers() because that would
1112  // remove pObj from primary list and pObj is to be kept
1113  // until CheckObjectRemoval().
1114  for (C4Object *obj : Objects)
1115  {
1116  obj->ClearPointers(to_obj);
1117  }
1118  // check in inactive objects as well
1119  for (C4Object *obj : Objects.InactiveObjects)
1120  {
1121  obj->ClearPointers(to_obj);
1122  }
1123 }
1124 
1126 {
1127  ::AulExec.ClearPointers(obj);
1130  ClearObjectPtrs(obj);
1132  ::Players.ClearPointers(obj);
1135  ::Console.ClearPointers(obj);
1137  if (ScriptGuiRoot)
1138  {
1139  ScriptGuiRoot->ClearPointers(obj);
1140  }
1143  {
1145  }
1147  {
1149  }
1151 }
1152 
1154 {
1155  // pause toggling disabled during round evaluation
1156  if (C4GameOverDlg::IsShown())
1157  {
1158  return false;
1159  }
1160  // otherwise, toggle
1161  if (IsPaused())
1162  {
1163  return Unpause();
1164  }
1165  else
1166  {
1167  return Pause();
1168  }
1169 }
1170 
1172 {
1173  // already paused?
1174  if (IsPaused())
1175  {
1176  return false;
1177  }
1178  // pause by net?
1179  if (::Network.isEnabled())
1180  {
1181  // league? Vote...
1182  if (Parameters.isLeague() && !Game.Evaluated)
1183  {
1184  ::Network.Vote(VT_Pause, true, true);
1185  return false;
1186  }
1187  // host only
1188  if (!::Network.isHost())
1189  {
1190  return true;
1191  }
1192  ::Network.Pause();
1193  }
1194  else
1195  {
1196  // pause game directly
1197  Game.HaltCount = true;
1198  }
1200  return true;
1201 }
1202 
1204 {
1205  // already paused?
1206  if (!IsPaused())
1207  {
1208  return false;
1209  }
1210  // pause by net?
1211  if (::Network.isEnabled())
1212  {
1213  // league? Vote...
1214  if (Parameters.isLeague() && !Game.Evaluated)
1215  {
1216  ::Network.Vote(VT_Pause, true, false);
1217  return false;
1218  }
1219  // host only
1220  if (!::Network.isHost())
1221  {
1222  return true;
1223  }
1224  ::Network.Start();
1225  }
1226  else
1227  {
1228  // unpause game directly
1229  Game.HaltCount = false;
1230  }
1232  return true;
1233 }
1234 
1236 {
1237  // pause state defined either by network or by game halt count
1238  if (::Network.isEnabled())
1239  {
1240  return !::Network.isRunning();
1241  }
1242  return !!HaltCount;
1243 }
1244 
1245 
1247  int32_t owner, C4ObjectInfo *info,
1248  int32_t x, int32_t y, int32_t r,
1249  C4Real xdir, C4Real ydir, C4Real rdir,
1250  int32_t con, int32_t controller, bool grow_from_center)
1251 {
1252  // Safety
1253  if (!def)
1254  {
1255  return nullptr;
1256  }
1257  if (Config.General.DebugRec)
1258  {
1259  C4RCCreateObj rect;
1260  memset(&rect, '\0', sizeof(rect));
1261  strncpy(rect.id, def->GetName(), 32+1);
1263  rect.x = x;
1264  rect.y = y;
1265  rect.ownr = owner;
1266  AddDbgRec(RCT_CrObj, &rect, sizeof(rect));
1267  }
1268 
1269  // Create object
1270  C4Object *obj;
1271  if (!(obj = new C4Object))
1272  {
1273  return nullptr;
1274  }
1275 
1276  // Initialize object
1277  obj->Init( def, creator, owner, info, x, y, r, xdir, ydir, rdir, controller );
1278 
1279  // Add to object list
1280  if (!Objects.Add(obj))
1281  {
1282  delete obj;
1283  return nullptr;
1284  }
1285 
1286  // ---- From now on, object is ready to be used in scripts!
1287  // Construction callback
1288  C4AulParSet pars(creator);
1289  obj->Call(PSF_Construction, &pars);
1290 
1291  // AssignRemoval called? (Con 0)
1292  if (!obj->Status)
1293  {
1294  return nullptr;
1295  }
1296  // Do initial con (grow)
1297  obj->DoCon(con, grow_from_center);
1298  // AssignRemoval called? (Con 0)
1299  if (!obj->Status)
1300  {
1301  return nullptr;
1302  }
1303  // Success
1304  return obj;
1305 }
1306 
1307 void C4Game::DeleteObjects(bool delete_inactive)
1308 {
1309  // del any objects
1310  ::Objects.DeleteObjects(delete_inactive);
1311  // reset resort flag
1312  fResortAnyObject = false;
1313 }
1314 
1315 C4Object* C4Game::CreateObject(C4ID id, C4Object *creator, int32_t owner,
1316  int32_t x, int32_t y, int32_t r, bool grow_from_center,
1317  C4Real xdir, C4Real ydir, C4Real rdir, int32_t controller)
1318 {
1319 
1320  // Get pDef
1321  C4Def *def;
1322  if (!(def = C4Id2Def(id)))
1323  {
1324  return nullptr;
1325  }
1326  // Create object
1327  return NewObject(def, creator,
1328  owner, nullptr,
1329  x, y, r,
1330  xdir, ydir, rdir,
1331  FullCon, controller, grow_from_center);
1332 }
1333 
1334 C4Object* C4Game::CreateObject(C4PropList * proplist, C4Object *creator, int32_t owner,
1335  int32_t x, int32_t y, int32_t r, bool grow_from_center,
1336  C4Real xdir, C4Real ydir, C4Real rdir, int32_t controller)
1337 {
1338  // check Definition
1339  if (!proplist || !proplist->GetDef())
1340  {
1341  return nullptr;
1342  }
1343  // Create object
1344  return NewObject(proplist, creator,
1345  owner, nullptr,
1346  x, y,r,
1347  xdir, ydir, rdir,
1348  FullCon, controller, grow_from_center);
1349 }
1350 
1352  int32_t x, int32_t y)
1353 {
1354  C4Def *def;
1355  // Valid check
1356  if (!info)
1357  {
1358  return nullptr;
1359  }
1360  // Get def
1361  if (!(def = C4Id2Def(info->id)))
1362  {
1363  return nullptr;
1364  }
1365  // Create object
1366  return NewObject( def, nullptr,
1367  owner, info,
1368  x, y, 0,
1369  Fix0, Fix0, Fix0,
1370  FullCon, NO_OWNER, false);
1371 }
1372 
1374  C4Object *creator,
1375  int32_t owner,
1376  int32_t center_x, int32_t bottom_y,
1377  int32_t con,
1378  bool adjust_terrain)
1379 {
1380  // Get def
1381  if (!proplist)
1382  {
1383  return nullptr;
1384  }
1385  C4Def *def;
1386  if (!(def = proplist->GetDef()))
1387  {
1388  return nullptr;
1389  }
1390 
1391  int32_t wdt = def->Shape.Wdt;
1392  int32_t hgt = def->Shape.Hgt;
1393  int32_t x = center_x - wdt/2;
1394  int32_t y = bottom_y - hgt;
1395 
1396  // Terrain
1397  if (adjust_terrain)
1398  {
1399  // Clear site background (ignored for ultra-large structures)
1400  if (wdt * hgt < 12000)
1401  {
1402  Landscape.DigFreeRect(x, y, wdt, hgt);
1403  }
1404  // Raise Terrain
1405  Landscape.RaiseTerrain(x, y + hgt, wdt);
1406  }
1407 
1408  // Create object
1409  C4Object *obj;
1410  if (!(obj = NewObject(proplist, creator,
1411  owner, nullptr,
1412  center_x, bottom_y, 0,
1413  Fix0, Fix0, Fix0,
1414  con, creator ? creator->Controller : NO_OWNER, false)))
1415  {
1416  return nullptr;
1417  }
1418 
1419  return obj;
1420 }
1421 
1422 // Finds an object (OCF_Exclusive) that blocks a potential construction site in the given rectangle
1423 C4Object* C4Game::FindConstuctionSiteBlock(int32_t x, int32_t y, int32_t wdt, int32_t hgt)
1424 {
1425  C4Rect search_area;
1426  search_area.x = x;
1427  search_area.y = y;
1428  search_area.Wdt = wdt;
1429  search_area.Hgt = hgt;
1430 
1431  C4LArea Area(&::Objects.Sectors, x, y, wdt, hgt);
1432  C4LSector *sector;
1433 
1434  for (C4ObjectList *objects = Area.FirstObjectShapes(&sector); sector; objects = Area.NextObjectShapes(objects, &sector))
1435  {
1436  for (C4Object *obj : *objects)
1437  {
1438  if (obj->Status && !obj->Contained)
1439  {
1440  if (obj->OCF & OCF_Exclusive)
1441  {
1442  C4Rect blocking_area = obj->Shape;
1443  blocking_area.x += obj->GetX();
1444  blocking_area.y += obj->GetY();
1445  if (search_area.Overlap(blocking_area))
1446  {
1447  return obj;
1448  }
1449  }
1450  }
1451  }
1452  }
1453  return nullptr;
1454 }
1455 
1457  int32_t x, int32_t y, int32_t wdt, int32_t hgt,
1458  DWORD ocf,
1459  C4Object *find_next)
1460 {
1461 
1462  C4Object *closest_obj = nullptr;
1463  int32_t closest_distance = 0;
1464  int32_t min_distance = -1;
1465  C4Object *find_next_copy = find_next;
1466 
1467  // check the easy case first: no instances at all?
1468  if (def && !def->Count)
1469  {
1470  return nullptr;
1471  }
1472 
1473  // Finding next closest: find closest but further away than last closest
1474  if (find_next && (wdt == -1) && (hgt == -1))
1475  {
1476  int32_t dx = find_next->GetX() - x;
1477  int32_t dy = find_next->GetY() - y;
1478  min_distance = dx * dx + dy * dy;
1479  find_next = nullptr;
1480  }
1481 
1482  // Scan all objects
1483  for (C4Object *obj : Objects)
1484  {
1485  // Not skipping to find next
1486  if (!find_next)
1487  // Status
1488  if (obj->Status)
1489  // ID
1490  if (!def || (obj->Def == def))
1491  // OCF (match any specified)
1492  if (obj->OCF & ocf)
1493  // Area
1494  {
1495  // Point
1496  if ((wdt == 0) && (hgt == 0))
1497  {
1498  if (Inside<int32_t>(x-(obj->GetX()+obj->Shape.x), 0, obj->Shape.Wdt-1))
1499  if (Inside<int32_t>(y-(obj->GetY()+obj->Shape.y), 0, obj->Shape.Hgt-1))
1500  return obj;
1501  continue;
1502  }
1503  // Closest
1504  if ((wdt == -1) && (hgt == -1))
1505  {
1506  int32_t dx = obj->GetX() - x;
1507  int32_t dy = obj->GetY() - y;
1508  int32_t distance = dx * dy + dy * dy;
1509  // same distance?
1510  if ((distance == min_distance) && !find_next_copy)
1511  return obj;
1512  // nearer than/first closest?
1513  if (!closest_obj || (distance < closest_distance))
1514  if (distance > min_distance)
1515  {
1516  closest_obj = obj;
1517  closest_distance = distance;
1518  }
1519  }
1520  // Range
1521  else if (Inside<int32_t>(obj->GetX()-x, 0, wdt-1) && Inside<int32_t>(obj->GetY()-y, 0, hgt-1))
1522  return obj;
1523  }
1524 
1525  // Find next mark reached
1526  if (obj == find_next_copy)
1527  {
1528  find_next = find_next_copy = nullptr;
1529  }
1530  }
1531 
1532  return closest_obj;
1533 
1534 }
1535 
1536 C4Object *C4Game::FindVisObject(float x, float y, int32_t player_nr, const C4Facet &viewport_game, const C4Facet &viewport_gui,
1537  float game_x, float game_y, DWORD category, float gui_x, float gui_y)
1538 {
1539  // FIXME: Use C4FindObject here for optimization
1540  // -- can't really do that, since sectors ignore parallaxity, etc.
1541  // determine layer to search in
1542  C4Object *layer_object = nullptr;
1543  C4Player *player = ::Players.Get(player_nr);
1544  if (player && player->Cursor)
1545  {
1546  layer_object = player->Cursor->Layer;
1547  }
1548  // scan all object lists separately
1549  C4ObjectList *obj_list = &::Objects.ForeObjects;
1550  while (obj_list)
1551  {
1552  // Scan all objects in list
1553  for (C4Object *obj : *obj_list)
1554  {
1555  // Status
1556  if (obj->Status == C4OS_NORMAL)
1557  // exclude fore-objects from main list
1558  if ((obj_list != &Objects) || (~obj->Category & C4D_Foreground))
1559  // exclude MouseIgnore-objects
1560  if (~obj->Category & C4D_MouseIgnore)
1561  // Category (match any specified)
1562  if (obj->Category & category)
1563  // Container
1564  if (!obj->Contained)
1565  // Visibility
1566  if (obj->IsVisible(player_nr, false))
1567  // Layer check: Layered objects are invisible to players whose cursor is in another layer
1568  // except for GUI: GUI always visible
1569  {
1570  if (obj->Layer != layer_object)
1571  if (obj_list != &::Objects.ForeObjects)
1572  continue;
1573  // Area
1574  // get object position
1575  float obj_x, obj_y, check_x, check_y;
1576  if (obj_list == &::Objects.ForeObjects)
1577  {
1578  // object position for HUD object
1579  check_x = gui_x; check_y = gui_y;
1580  obj->GetViewPos(obj_x, obj_y, -viewport_gui.X, -viewport_gui.Y, viewport_gui);
1581  }
1582  else
1583  {
1584  // object position for game object
1585  check_x = game_x; check_y = game_y;
1586  obj->GetViewPos(obj_x, obj_y, x, y, viewport_game);
1587  }
1588  // Point search
1589  if (Inside<float>(check_x-(obj_x+obj->Shape.x),0, float(obj->Shape.Wdt)-1))
1590  if (Inside<float>(check_y-(obj_y+obj->Shape.y-obj->addtop()),0, float(obj->Shape.Hgt+obj->addtop()-1)))
1591  return obj;
1592  }
1593  }
1594  // next list
1595  if (obj_list == &::Objects.ForeObjects)
1596  {
1597  obj_list = &Objects;
1598  }
1599  else
1600  {
1601  obj_list = nullptr;
1602  }
1603  }
1604 
1605  // none found
1606  return nullptr;
1607 }
1608 
1610 {
1611  C4Def *def;
1612  // check the easy cases first
1613  if (id != C4ID::None)
1614  {
1615  if (!(def = C4Id2Def(id)))
1616  {
1617  return 0; // no valid def
1618  }
1619  return def->Count;
1620  }
1621  int32_t count = 0;
1622  for (C4Object *obj : Objects)
1623  {
1624  // Status
1625  if (obj->Status)
1626  {
1627  ++count;
1628  }
1629  }
1630  return count;
1631 }
1632 
1633 // Deletes removal-assigned data from list.
1634 // Pointer clearance is done by AssignRemoval.
1635 
1636 void C4Game::ObjectRemovalCheck() // Every ::Game.iTick255 by ExecObjects
1637 {
1638  for (C4Object *obj : Objects)
1639  {
1640  if (!obj->Status && (obj->RemovalDelay == 0))
1641  {
1642  Objects.Remove(obj);
1643  delete obj;
1644  }
1645  }
1646 }
1647 
1648 void C4Game::ExecObjects() // Every Tick1 by Execute
1649 {
1650  if (Config.General.DebugRec)
1651  {
1652  AddDbgRec(RCT_Block, "ObjEx", 6);
1653  }
1654 
1655  // Execute objects - reverse order to ensure
1656  for (C4Object *obj : Objects.reverse())
1657  {
1658  if (obj)
1659  {
1660  if (obj->Status)
1661  {
1662  // Execute object
1663  obj->Execute();
1664  }
1665  // Status reset: process removal delay
1666  else if (obj->RemovalDelay > 0)
1667  {
1668  obj->RemovalDelay--;
1669  }
1670  }
1671  }
1672 
1673  if (Config.General.DebugRec)
1674  {
1675  AddDbgRec(RCT_Block, "ObjCC", 6);
1676  }
1677 
1678  // Cross check objects
1679  Objects.CrossCheck();
1680 
1681  if (Config.General.DebugRec)
1682  {
1683  AddDbgRec(RCT_Block, "ObjRs", 6);
1684  }
1685 
1686  // Resort
1687  if (fResortAnyObject)
1688  {
1689  fResortAnyObject = false;
1691  }
1692 
1693  if (Config.General.DebugRec)
1694  {
1695  AddDbgRec(RCT_Block, "ObjRm", 6);
1696  }
1697 
1698  // Removal
1699  if (!::Game.iTick255)
1700  {
1702  }
1703 }
1704 
1705 C4ID DefFileGetID(const char *filename)
1706 {
1707  C4Group group;
1708  if (!group.Open(filename))
1709  {
1710  return C4ID::None;
1711  }
1712  C4Def DefCore;
1713  if (!DefCore.LoadDefCore(group))
1714  {
1715  group.Close();
1716  return C4ID::None;
1717  }
1718  group.Close();
1719  return DefCore.id;
1720 }
1721 
1722 bool C4Game::DropFile(const char *filename, float x, float y)
1723 {
1724  C4ID id;
1725  C4Def *def;
1726  // Drop def to create object
1727  if (SEqualNoCase(GetExtension(filename), "ocd"))
1728  {
1729  // Get id from file
1730  if ((id = DefFileGetID(filename)))
1731  {
1732  // Get loaded def or try to load def from file
1733  if ((def = C4Id2Def(id))
1734  || (::Definitions.Load(filename, C4D_Load_RX, Config.General.LanguageEx,&Application.SoundSystem) && (def = C4Id2Def(id))) )
1735  {
1736  return DropDef(id, x, y);
1737  }
1738  }
1739  // Failure
1740  Console.Out(FormatString(LoadResStr("IDS_CNS_DROPNODEF"),GetFilename(filename)).getData());
1741  return false;
1742  }
1743  return false;
1744 }
1745 
1746 bool C4Game::DropDef(C4ID id, float x, float y)
1747 {
1748  // Get def
1749  C4Def *def;
1750  if ((def = C4Id2Def(id)))
1751  {
1753  return true;
1754  }
1755  else
1756  {
1757  // Failure
1758  Console.Out(FormatString(LoadResStr("IDS_CNS_DROPNODEF"),id.ToString()).getData());
1759  }
1760  return false;
1761 }
1762 
1763 void C4Game::CastObjects(C4ID id, C4Object *creator, int32_t amount, int32_t level, int32_t x, int32_t y, int32_t owner, int32_t controller, C4ValueArray *out_objects)
1764 {
1765  int32_t out_obj_size = 0;
1766  if (out_objects)
1767  {
1768  out_obj_size = out_objects->GetSize();
1769  out_objects->SetSize(out_obj_size + amount);
1770  }
1771  for (int32_t count = 0; count < amount; count++)
1772  {
1773  // Must do these calculation steps separately, because the order of
1774  // invokations of Random() is not defined if they're used as parameters
1775  int32_t angle = Random(360);
1776  C4Real xdir = C4REAL10(Random(2*level+1)-level);
1777  C4Real ydir = C4REAL10(Random(2*level+1)-level);
1778  C4Real rdir = itofix(Random(3)+1);
1779  C4Object *obj = CreateObject(id, creator, owner,
1780  x, y,angle,
1781  false,
1782  xdir,
1783  ydir,
1784  rdir, controller);
1785  if (obj && obj->Status && out_objects)
1786  {
1787  (*out_objects)[out_obj_size + count] = C4VObj(obj);
1788  }
1789  }
1790 }
1791 
1793 {
1794  // updates the game clock
1795  if (Game.TimeGo)
1796  {
1797  Game.Time++;
1798  Game.TimeGo = false;
1799  }
1800  Game.FPS = Game.cFPS;
1801  Game.cFPS = 0;
1802 }
1803 
1805 {
1806  PointersDenumerated = false;
1807  IsRunning = false;
1808  FrameCounter = 0;
1810  ScenarioFilename[0] = 0;
1811  PlayerFilenames[0] = 0;
1812  DefinitionFilenames[0] = 0;
1813  DirectJoinAddress[0] = 0;
1814  pJoinReference = nullptr;
1815  StartupPlayerCount = 0;
1816  StartupTeamCount = 0;
1817  ScenarioTitle.Ref("");
1818  HaltCount = 0;
1820  Evaluated = false;
1821  EvaluateOnAbort = false;
1822  TimeGo = false;
1823  Time = 0;
1824  StartTime = 0;
1825  InitProgress = 0; LastInitProgress = 0;
1826  FPS = cFPS = 0;
1827  fScriptCreatedObjects = false;
1828  fLobby = fObserve = false;
1829  iLobbyTimeout = 0;
1831  FullSpeed = false;
1832  FrameSkip = 1; DoSkipFrame = false;
1835  Objects.Default();
1836  Players.Default();
1837  Weather.Default();
1838  Landscape.Default();
1840  MassMover.Default();
1841  PXS.Default();
1843  C4S.Default();
1844  ::Messages.Default();
1847  PathFinder.Default();
1849  GroupSet.Default();
1850  pParentGroup = nullptr;
1853  fResortAnyObject = false;
1854  pNetworkStatistics.reset();
1856  DebugPort = 0;
1857  DebugPassword.Clear();
1858  DebugHost.Clear();
1859  DebugWait = false;
1860  assert(!ScriptGuiRoot);
1861  ScriptGuiRoot.reset();
1862 }
1863 
1865 {
1866 
1867  // League game?
1868  bool is_league = Network.isEnabled() && Network.isHost() && Parameters.isLeague();
1869 
1870  // Stop record
1871  StdStrBuf RecordName;
1872  BYTE RecordSHA[SHA_DIGEST_LENGTH];
1873  if (Control.isRecord())
1874  {
1875  Control.StopRecord(&RecordName, is_league ? RecordSHA : nullptr);
1876  }
1877 
1878  // Send league result
1879  if (is_league)
1880  {
1881  Network.LeagueGameEvaluate(RecordName.getData(), RecordSHA);
1882  }
1883 
1884  // Players
1885  // saving local players only, because remote players will probably not rejoin after evaluation anyway)
1886  Players.Evaluate();
1887  Players.Save(true);
1888 
1889  // Round results
1891 
1892  // Set game flag
1893  Log(LoadResStr("IDS_PRC_EVALUATED"));
1894  Evaluated = true;
1895 }
1896 
1897 void C4Game::DrawCrewOverheadText(C4TargetFacet &cgo, int32_t player_nr)
1898 {
1899  // All drawing in this function must not be affected by zoom; but remember zoom and reset later.
1900  ZoomData r;
1901  pDraw->GetZoom(&r);
1902  const float zoom = r.Zoom;
1903  r.Zoom = 1.0;
1904  pDraw->SetZoom(r);
1905 
1906  // Offset for all text/objects
1907  const float fixedOffsetX = -cgo.X * cgo.Zoom + cgo.X;
1908  const float fixedOffsetY = (-cgo.Y - 10.0f) * cgo.Zoom + cgo.Y;
1909 
1910  // Draw cursor mark arrow & cursor object name
1912  for (C4Player *player = Players.First; player; player = player->Next)
1913  {
1914  // Draw a small selector & name above the cursor? F.e. after switching crew.
1915  const bool drawCursorInfo = (player->Number == player_nr || player_nr == NO_OWNER) // only for the viewport's player..
1916  && (player->CursorFlash && player->Cursor); // ..and if the player wants to show their cursor.
1917  // Otherwise, for allied players we might want to draw player & crew names.
1918  // Note that these two conditions are generally mutually-exclusive.
1919  const bool drawPlayerAndCursorNames = (player->Number != player_nr) // Never for own player..
1920  && (Config.Graphics.ShowCrewNames || Config.Graphics.ShowCrewCNames) // ..and if the settings allow it..
1921  && !Hostile(player_nr, player->Number) && !player->IsInvisible(); // ..and of course only if applicable.
1922 
1923  if (!drawPlayerAndCursorNames && !drawCursorInfo)
1924  {
1925  continue;
1926  }
1927 
1928  // Lambda to calculate correct drawing position of object, (re-)adjusted by zoom.
1929  float drawX, drawY, drawZoom;
1930  auto calculateObjectTextPosition = [&](C4Object *obj)
1931  {
1932  obj->GetDrawPosition(cgo, fixtof(obj->fix_x), fixtof(obj->fix_y), 1.0, drawX, drawY, drawZoom);
1933  drawX = drawX * cgo.Zoom + fixedOffsetX;
1934  drawY = drawY * cgo.Zoom - static_cast<float>(obj->Def->Shape.Hgt) / 2.0 + fixedOffsetY;
1935  };
1936 
1937  // Actual text output!
1938  if (drawPlayerAndCursorNames)
1939  {
1940  // We need to show crew names for that player, we do so for every crew-member.
1941  for (C4Object * const & crew : player->Crew)
1942  {
1943  if (!crew->Status || !crew->Def) continue;
1944  if (crew->Contained) continue;
1945  if ((crew->OCF & OCF_CrewMember) == 0) continue;
1946  if (!crew->IsVisible(player_nr, false)) continue;
1947 
1948  calculateObjectTextPosition(crew);
1949  drawY -= 5.0f; // aesthetical offset
1950 
1951  // compose string
1952  char text[C4GM_MaxText + 1];
1955  {
1956  sprintf(text, "%s (%s)", crew->GetName(), player->GetName());
1957  }
1958  else
1959  {
1960  SCopy(player->GetName(), text);
1961  }
1962  else
1963  {
1964  SCopy(crew->GetName(), text);
1965  }
1966 
1967  // Word wrap to cgo width
1968  int32_t char_width, dummy;
1969  ::GraphicsResource.FontRegular.GetTextExtent("m", char_width, dummy, false);
1970  int32_t iMaxLine = std::max<int32_t>(cgo.Wdt / std::max<int32_t>(1, char_width), 20);
1971  SWordWrap(text, ' ', '|', iMaxLine);
1972 
1973  // Center text vertically, too
1974  int textWidth, textHeight;
1975  ::GraphicsResource.FontRegular.GetTextExtent(text, textWidth, textHeight, true);
1976 
1977  // Draw
1978  pDraw->TextOut(text, ::GraphicsResource.FontRegular, 1.0, cgo.Surface, drawX, drawY - static_cast<float>(textHeight) / 2.0, player->ColorDw | 0x7f000000, ACenter);
1979  }
1980  }
1981  else if (drawCursorInfo)
1982  {
1983  C4Object * const cursor = player->Cursor;
1984  calculateObjectTextPosition(cursor);
1985 
1986  // Draw a down-arrow above the Clonk's head
1987  drawY += -fctCursor.Hgt;
1988  fctCursor.Draw(cgo.Surface, drawX - static_cast<float>(fctCursor.Wdt) / 2.0, drawY, 4);
1989  // And possibly draw some info text, too
1990  if (cursor->Info)
1991  {
1992  int32_t texthgt = ::GraphicsResource.FontRegular.GetLineHeight();
1993  StdStrBuf str;
1994  if (cursor->Info->Rank > 0)
1995  {
1996  str.Format("%s|%s", cursor->Info->sRankName.getData(), cursor->GetName());
1997  texthgt += texthgt;
1998  }
1999  else
2000  {
2001  str = cursor->GetName();
2002  }
2003 
2005  drawX,
2006  drawY - static_cast<float>(texthgt) / 2.0,
2007  0xffff0000, ACenter);
2008  }
2009  }
2010  }
2011 
2012  // Reset zoom
2013  r.Zoom = zoom;
2014  pDraw->SetZoom(r);
2015 }
2016 
2018 {
2019  // Frames
2021  // Ticks
2022  if (++iTick2 == 2) iTick2 = 0;
2023  if (++iTick3 == 3) iTick3 = 0;
2024  if (++iTick5 == 5) iTick5 = 0;
2025  if (++iTick10 == 10) iTick10 = 0;
2026  if (++iTick35 == 35) iTick35 = 0;
2027  if (++iTick255 == 255) iTick255 = 0;
2028  if (++iTick1000 == 1000) iTick1000 = 0;
2029 
2030  // FPS / time
2031  cFPS++;
2032  TimeGo = true;
2033 
2034  // Frame skip
2035  if (FrameCounter % FrameSkip)
2036  {
2037  DoSkipFrame = true;
2038  }
2039 
2040  // Control
2041  Control.Ticks();
2042 
2043  // Full speed
2044  if (GameGo)
2045  {
2046  Application.NextTick(); // short-circuit the timer
2047  }
2048  // statistics
2049  if (pNetworkStatistics)
2050  {
2051  pNetworkStatistics->ExecuteFrame();
2052  }
2053 }
2054 
2055 void C4Game::CompileFunc(StdCompiler *compiler, CompileSettings settings, C4ValueNumbers * numbers)
2056 {
2057  if (settings.init_mode == IM_Normal && settings.fExact)
2058  {
2059  compiler->Name("Game");
2060  compiler->Value(mkNamingAdapt(Time, "Time", 0));
2061  compiler->Value(mkNamingAdapt(FrameCounter, "Frame", 0));
2062  if (settings.fSync)
2063  {
2064  compiler->Value(mkNamingAdapt(Control.ControlTick, "ControlTick", 0));
2065  compiler->Value(mkNamingAdapt(Control.SyncRate, "SyncRate", C4SyncCheckRate));
2066  }
2067  compiler->Value(mkNamingAdapt(iTick2, "Tick2", 0));
2068  compiler->Value(mkNamingAdapt(iTick3, "Tick3", 0));
2069  compiler->Value(mkNamingAdapt(iTick5, "Tick5", 0));
2070  compiler->Value(mkNamingAdapt(iTick10, "Tick10", 0));
2071  compiler->Value(mkNamingAdapt(iTick35, "Tick35", 0));
2072  compiler->Value(mkNamingAdapt(iTick255, "Tick255", 0));
2073  compiler->Value(mkNamingAdapt(iTick1000, "Tick1000", 0));
2074  compiler->Value(mkNamingAdapt(InitialPlayersJoined, "InitialPlayersJoined", false));
2075  compiler->Value(mkNamingAdapt(StartupPlayerCount, "StartupPlayerCount", 0));
2076  compiler->Value(mkNamingAdapt(StartupTeamCount, "StartupTeamCount", 0));
2077  compiler->Value(mkNamingAdapt(C4PropListNumbered::EnumerationIndex,"ObjectEnumerationIndex",0));
2078  compiler->Value(mkNamingAdapt(mkStringAdaptMA(CurrentScenarioSection), "CurrentScenarioSection", ""));
2079  compiler->Value(mkNamingAdapt(fResortAnyObject, "ResortAnyObj", false));
2080  compiler->Value(mkNamingAdapt(mkParAdapt(GlobalSoundModifier, numbers), "GlobalSoundModifier", C4Value()));
2081  compiler->Value(mkNamingAdapt(NextMission, "NextMission", StdCopyStrBuf()));
2082  compiler->Value(mkNamingAdapt(NextMissionText, "NextMissionText", StdCopyStrBuf()));
2083  compiler->Value(mkNamingAdapt(NextMissionDesc, "NextMissionDesc", StdCopyStrBuf()));
2084  compiler->NameEnd();
2085 
2086  // Music settings
2087  compiler->Value(mkNamingAdapt(::Application.MusicSystem, "Music"));
2088 
2089  // scoreboard compiles into main level [Scoreboard]
2090  compiler->Value(mkNamingAdapt(Scoreboard, "Scoreboard"));
2091  // Keyboard status of global keys synchronized for exact (runtime join) only; not for savegames,
2092  // as keys might be released between a savegame save and its resume
2093  }
2094 
2095  if (settings.fExact)
2096  {
2097  compiler->Value(mkNamingAdapt(Weather, "Weather"));
2098  compiler->Value(mkNamingAdapt(Landscape, "Landscape"));
2099  compiler->Value(mkNamingAdapt(Landscape.GetSky(), "Sky"));
2100 
2101  // save custom GUIs only if a real savegame and not for editor-scenario-saves or section changes
2102  if (settings.init_mode == IM_Normal)
2103  {
2104  compiler->Name("GUI");
2105  if (compiler->isDeserializer())
2106  {
2107  C4Value val;
2108  compiler->Value(mkNamingAdapt(mkParAdapt(val, numbers), "ScriptGUIs", C4VNull));
2109  // if loading, assume
2110  assert(ScriptGuiRoot->GetID() == 0); // ID of 0 means "had no subwindows ever" aka "is fresh" for root
2111  // we will need to denumerate and create the actual GUI post-loading
2112  // for now, just remember our enumerated ID
2113  if (val.GetType() == C4V_Enum)
2114  {
2115  int enumID = val._getInt();
2116  ScriptGuiRoot->SetEnumeratedID(enumID);
2117  }
2118  }
2119  else
2120  {
2121  C4Value *val = new C4Value(ScriptGuiRoot->ToC4Value());
2122  compiler->Value(mkNamingAdapt(mkParAdapt(*val, numbers), "ScriptGUIs", C4VNull));
2123  }
2124  compiler->NameEnd();
2125  }
2126  }
2127 
2128  if (settings.fPlayers)
2129  {
2130  assert(compiler->isSerializer());
2131  // player parsing: Parse all players
2132  // This doesn't create any players, but just parses existing by their ID
2133  // Primary player ininitialization (also setting ID) is done by player info list
2134  // Won't work this way for binary mode!
2135  for (C4Player *pPlr = Players.First; pPlr; pPlr = pPlr->Next)
2136  {
2137  compiler->Value(mkNamingAdapt(mkParAdapt(*pPlr, numbers), FormatString("Player%d", pPlr->ID).getData()));
2138  }
2139  }
2140 
2141  // Section load: Clear existing prop list numbering to make room for the new objects
2142  // Numbers will be re-acquired in C4GameObjects::PostLoad
2143  if (settings.init_mode == IM_Section)
2144  {
2146  }
2147 
2148  compiler->Value(mkParAdapt(Objects, !settings.fExact, numbers));
2149 
2150  compiler->Value(mkNamingAdapt(mkParAdapt(ScriptEngine, settings.init_mode == IM_Section, numbers), "Script"));
2151 }
2152 
2153 bool C4Game::CompileRuntimeData(C4Group &group, InitMode init_mode, bool exact, bool sync, C4ValueNumbers * numbers)
2154 {
2155  ::Objects.Clear(init_mode != IM_Section);
2156  GameText.Load(group, C4CFN_Game);
2157  CompileSettings Settings(init_mode, false, exact, sync);
2158  // C4Game is not defaulted on compilation.
2159  // Loading of runtime data overrides only certain values.
2160  // Doesn't compile players; those will be done later
2161  if (GameText.GetData())
2162  {
2163  if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(
2164  mkParAdapt(*this, Settings, numbers),
2166  {
2167  return false;
2168  }
2169  // Objects
2170  int32_t object_count = Objects.ObjectCount();
2171  if (object_count)
2172  {
2173  LogF(LoadResStr("IDS_PRC_OBJECTSLOADED"), object_count);
2174  }
2175  }
2176  // Success
2177  return true;
2178 }
2179 
2180 bool C4Game::SaveData(C4Group &group, bool save_section, bool save_exact, bool save_sync, C4ValueNumbers * numbers)
2181 {
2182  if (save_exact)
2183  {
2184  StdStrBuf Buf;
2185  // Decompile (without players for scenario sections)
2186  DecompileToBuf_Log<StdCompilerINIWrite>(mkParAdapt(*this, CompileSettings(save_section ? IM_Section : IM_Normal, !save_section && save_exact, save_exact, save_sync), numbers), &Buf, "Game");
2187 
2188  // Empty? All default save a Game.txt anyway because it is used to signal the engine to not load Objects.c
2189  if (!Buf.getLength())
2190  {
2191  Buf.Copy(" ");
2192  }
2193 
2194  // Save
2195  return group.Add(C4CFN_Game, Buf, false, true);
2196  }
2197  else
2198  {
2199  // Clear any exact game data in case scenario is saved from savegame resume
2200  group.Delete(C4CFN_Game);
2201 
2202  // Save objects to file using system scripts
2203  int32_t objects_file_handle = ::ScriptEngine.CreateUserFile();
2204  C4AulParSet pars(objects_file_handle);
2205  C4Value result_c4v(::ScriptEngine.GetPropList()->Call(PSF_SaveScenarioObjects, &pars));
2206  bool result = !!result_c4v;
2207  if (result_c4v.GetType() == C4V_Nil)
2208  {
2209  // Function returned nil: This usually means there was a script error during object writing.
2210  // It could also mean the scripter overloaded global func SaveScenarioObjects and returned nil.
2211  // In either case, objects will not match landscape any more, so better fail and don't save at all.
2212  LogF("ERROR: No valid result from global func " PSF_SaveScenarioObjects ". Saving objects failed.");
2213  }
2214  else
2215  {
2216  // Function completed successfully (returning true or false)
2217  C4AulUserFile *file = ::ScriptEngine.GetUserFile(objects_file_handle);
2218  if (!result || !file || !file->GetFileLength())
2219  {
2220  // Nothing written? Then we don't have objects.
2222  // That's OK; not an error.
2223  result = true;
2224  }
2225  else
2226  {
2227  // Write objects script to file!
2228  StdStrBuf data = file->GrabFileContents();
2229  result = group.Add(C4CFN_ScenarioObjectsScript, data, false, true);
2230  }
2231  }
2232  ::ScriptEngine.CloseUserFile(objects_file_handle);
2233  return result;
2234  }
2235 }
2236 
2238 {
2239  // Game not running
2240  if (!FrameCounter)
2241  {
2242  char* bytes;
2243  size_t size;
2244  StdStrBuf real_filename;
2245 
2246  if (ScenarioFile.FindEntry(FormatString("%s.*",C4CFN_ScenarioTitle).getData(), &real_filename, &size))
2247  {
2248  if (ScenarioFile.LoadEntry(real_filename.getData(), &bytes, &size))
2249  {
2250  group.Add(real_filename.getData(), bytes, size, false, true);
2251  }
2252  }
2253  }
2254  // Fullscreen screenshot
2255  else if (!Application.isEditor && Application.Active)
2256  {
2257  C4Surface * sfcPic;
2258  int32_t iSfcWdt = 200;
2259  int32_t iSfcHgt = 150;
2260  if (!(sfcPic = new C4Surface(iSfcWdt, iSfcHgt, 0)))
2261  {
2262  return false;
2263  }
2264 
2265  // Fullscreen
2268  sfcPic, 0,0, iSfcWdt, iSfcHgt);
2269 
2270  bool fOkay = true;
2271  fOkay = sfcPic->SavePNG(Config.AtTempPath(C4CFN_TempTitle), false, false, false);
2272 
2273  StdStrBuf destFilename = FormatString("%s.png",C4CFN_ScenarioTitle);
2274  delete sfcPic;
2275  if (!fOkay)
2276  {
2277  return false;
2278  }
2279  if (!group.Move(Config.AtTempPath(C4CFN_TempTitle),destFilename.getData()))
2280  {
2281  return false;
2282  }
2283  }
2284 
2285  return true;
2286 }
2287 
2288 bool C4Game::DoKeyboardInput(C4KeyCode vk_code, C4KeyEventType event_type, bool alt, bool ctrl, bool shift, bool repeated, class C4GUI::Dialog *for_dialog, bool fPlrCtrlOnly, int32_t strength)
2289 {
2290  // compose key
2291  C4KeyCodeEx Key(vk_code, C4KeyShiftState(alt*KEYS_Alt + ctrl*KEYS_Control + shift*KEYS_Shift), repeated);
2292  return DoKeyboardInput(Key, event_type, for_dialog, fPlrCtrlOnly, strength);
2293 }
2294 
2295 
2296 bool C4Game::DoKeyboardInput(C4KeyCodeEx key, C4KeyEventType event_type, class C4GUI::Dialog *for_dialog, bool fPlrCtrlOnly, int32_t strength)
2297 {
2298  key.FixShiftKeys();
2299  // compose keyboard scope
2300  DWORD InScope = 0;
2301  if (fPlrCtrlOnly)
2302  {
2303  InScope = KEYSCOPE_Control;
2304  }
2305  else
2306  {
2307  if (IsRunning)
2308  {
2309  InScope = KEYSCOPE_Generic;
2310  }
2311  // if GUI has keyfocus, this overrides regular controls
2312  if (pGUI->HasKeyboardFocus() || for_dialog)
2313  {
2314  InScope |= KEYSCOPE_Gui;
2315  // control to console mode dialog: Make current keyboard target the active dlg,
2316  // so it can process input
2317  if (for_dialog)
2318  {
2319  pGUI->ActivateDialog(for_dialog);
2320  }
2321  // any keystroke in GUI resets tooltip times
2322  pGUI->KeyAny();
2323  }
2324  else
2325  {
2326  if (!Application.isEditor)
2327  {
2328  if (FullScreen.MainMenu && FullScreen.MainMenu->IsActive()) // fullscreen menu
2329  {
2330  InScope |= KEYSCOPE_FullSMenu;
2331  }
2332  else if (Game.C4S.Head.Replay && C4S.Head.Film) // film view only
2333  {
2334  InScope |= KEYSCOPE_FilmView;
2335  }
2336  else if (::Viewports.GetViewport(NO_OWNER)) // NO_OWNER-viewport-controls
2337  {
2338  InScope |= KEYSCOPE_FreeView;
2339  }
2340  else
2341  {
2342  // regular player viewport controls
2343  InScope |= KEYSCOPE_FullSView;
2344  // player controls disabled during round over dlg
2345  if (!C4GameOverDlg::IsShown())
2346  {
2347  InScope |= KEYSCOPE_Control;
2348  }
2349  }
2350  }
2351  else
2352  {
2353  // regular player viewport controls
2354  InScope |= KEYSCOPE_Control;
2355  }
2356  }
2357  // fullscreen/console (in running game)
2358  if (IsRunning)
2359  {
2360  if (FullScreen.Active) InScope |= KEYSCOPE_Fullscreen;
2361  if (Console.Active) InScope |= KEYSCOPE_Console;
2362  }
2363  }
2364  // okay; do input
2365  if (KeyboardInput.DoInput(key, event_type, InScope, strength))
2366  {
2367  return true;
2368  }
2369 
2370  // unprocessed key
2371  return false;
2372 }
2373 
2375 {
2376  // Network hosts only
2377  if (Network.isEnabled() && !Network.isHost())
2378  {
2379  Log(LoadResStr("IDS_GAME_NOCLIENTSAVE"));
2380  return false;
2381  }
2382 
2383  return true;
2384 }
2385 
2386 bool C4Game::QuickSave(const char *filename, const char *title, bool force_save)
2387 {
2388  // Check
2389  if (!force_save)
2390  {
2391  if (!CanQuickSave())
2392  {
2393  return false;
2394  }
2395  }
2396 
2397  // Create savegame folder
2398  if (!Config.General.CreateSaveFolder(Config.AtUserDataPath(C4CFN_Savegames), LoadResStr("IDS_GAME_SAVEGAMESTITLE")))
2399  {
2400  Log(LoadResStr("IDS_GAME_FAILSAVEGAME"));
2401  return false;
2402  }
2403 
2404  // Create savegame subfolder(s)
2405  char save_folder[_MAX_PATH_LEN];
2406  for (uint32_t i = 0; i < SCharCount(DirectorySeparator, filename); i++)
2407  {
2408  SCopy(Config.AtUserDataPath(C4CFN_Savegames), save_folder);
2409  AppendBackslash(save_folder);
2410  SCopyUntil(filename, save_folder + SLen(save_folder), DirectorySeparator, _MAX_PATH, i);
2411  if (!Config.General.CreateSaveFolder(save_folder, title))
2412  {
2413  Log(LoadResStr("IDS_GAME_FAILSAVEGAME"));
2414  return false;
2415  }
2416  }
2417 
2418  // Compose savegame filename
2419  StdStrBuf save_path;
2420  save_path.Format("%s%c%s", Config.AtUserDataPath(C4CFN_Savegames), DirectorySeparator, filename);
2421 
2422  // Must not be the scenario file that is currently open
2423  if (ItemIdentical(ScenarioFilename, save_path.getData()))
2424  {
2425  StartSoundEffect("UI::Error");
2426  ::GraphicsSystem.FlashMessage(LoadResStr("IDS_GAME_NOSAVEONCURR"));
2427  Log(LoadResStr("IDS_GAME_FAILSAVEGAME"));
2428  return false;
2429  }
2430 
2431  // Wait message
2432  Log(LoadResStr("IDS_HOLD_SAVINGGAME"));
2433  GraphicsSystem.MessageBoard->EnsureLastMessage();
2434 
2435  // Save to target scenario file
2436  C4GameSave *game_save;
2437  game_save = new C4GameSaveSavegame();
2438  if (!game_save->Save(save_path.getData()))
2439  {
2440  Log(LoadResStr("IDS_GAME_FAILSAVEGAME"));
2441  delete game_save;
2442  return false;
2443  }
2444  delete game_save;
2445 
2446  // Success
2447  Log(LoadResStr("IDS_CNS_GAMESAVED"));
2448  return true;
2449 }
2450 
2451 bool LandscapeFree(int32_t x, int32_t y)
2452 {
2453  if (!Inside<int32_t>(x, 0,::Landscape.GetWidth()-1) || !Inside<int32_t>(y, 0,::Landscape.GetHeight()-1))
2454  {
2455  return false;
2456  }
2457  return !DensitySolid(GBackDensity(x, y));
2458 }
2459 
2460 static void FileMonitorCallback(const char * file, const char * extrafile)
2461 {
2462  Game.ReloadFile(file);
2463 }
2464 
2465 bool C4Game::ReloadFile(const char *filepath)
2466 {
2467  // not in network
2468  if (::Network.isEnabled())
2469  {
2470  return false;
2471  }
2472  const char *relative_path = Config.AtRelativePath(filepath);
2473 
2474  // a definition? or part of a definition?
2475  C4Def *def;
2476  if ((def = ::Definitions.GetByPath(relative_path)))
2477  {
2478  return ReloadDef(def->id);
2479  }
2480  // script?
2481  if (ScriptEngine.ReloadScript(relative_path, Config.General.LanguageEx))
2482  {
2484  }
2485  return true;
2486 }
2487 
2489 {
2490  // not in network
2491  if (::Network.isEnabled())
2492  {
2493  return false;
2494  }
2495 
2496  // syncronize (close menus with dead surfaces, etc.)
2497  // no need to sync back player files, though
2498  Synchronize(false);
2499 
2500  // SolidMasks might be updated
2502 
2503  // reload def
2504  C4Def *def = ::Definitions.ID2Def(id);
2505  if (!def)
2506  {
2507  return false;
2508  }
2509 
2510  // Open Graphics.ocg -- we might need to fetch some shader (slices)
2511  // from there when reloading mesh materials.
2512  if (!::GraphicsResource.RegisterGlobalGraphics()) return false;
2513  if (!::GraphicsResource.RegisterMainGroups()) return false;
2514 
2515  // Message
2516  LogF("Reloading %s from %s", def->id.ToString(), GetFilename(def->Filename));
2517 
2518  // Reload def
2519  bool reload_succeeded;
2521  {
2522  // update script engine - this will also do include callbacks and Freeze() def
2524  // Success, update all concerned object faces
2525  // may have been done by graphics-update already - but not for objects using graphics of another def
2526  // better update everything :)
2527  for (C4Object *obj : Objects)
2528  {
2529  if (obj->id == id)
2530  {
2531  obj->UpdateFace(true);
2532  }
2533  }
2534  reload_succeeded = true;
2535  }
2536  else
2537  {
2538  // Failure, remove all objects of this type
2539  for (C4Object *obj : Objects)
2540  {
2541  if (obj->id == id)
2542  {
2543  obj->AssignRemoval();
2544  }
2545  }
2546  // safety: If a removed def is being profiled, profiling must stop
2548  // Kill def
2549  ::Definitions.Remove(def);
2550  // Log
2551  Log("Reloading failure. All objects of this type removed.");
2552  reload_succeeded = false;
2553  }
2554 
2555  // close Graphics.ocg again
2557  // update game messages
2558  ::Messages.UpdateDef(id);
2559  // re-put removed SolidMasks
2561  // done
2562  return reload_succeeded;
2563 }
2564 
2565 bool C4Game::ReloadParticle(const char *name)
2566 {
2567  // not in network
2568  if (::Network.isEnabled())
2569  {
2570  return false;
2571  }
2572  // safety
2573  if (!name)
2574  {
2575  return false;
2576  }
2577  // get particle def
2579  if (!def)
2580  {
2581  return false;
2582  }
2583  // verbose
2584  LogF("Reloading particle %s from %s", def->Name.getData(), GetFilename(def->Filename.getData()));
2585  // reload it
2586  if (!def->Reload())
2587  {
2588  // safer: remove all particles
2590  delete def;
2591  LogF("Reloading failure. All particles removed.");
2592  // failure
2593  return false;
2594  }
2595  // success
2596  return true;
2597 }
2598 
2599 bool C4Game::InitGame(C4Group &group, InitMode init_mode, bool load_sky, C4ValueNumbers * numbers)
2600 {
2601  // Activate debugger if requested
2602  // needs to happen before any scripts are compiled to bytecode so AB_DEBUG chunks will be inserted
2603  if (DebugPort)
2604  {
2605  if (Parameters.isLeague())
2606  {
2607  Log("Debugger disabled. Not allowed in league.");
2608  }
2610  {
2611  return false;
2612  }
2613  }
2614 
2615  if (init_mode == IM_Normal)
2616  {
2617 
2618  // file monitor
2620  {
2621  pFileMonitor = std::make_unique<C4FileMonitor>(FileMonitorCallback);
2622  }
2623 
2624  // system scripts
2625  if (!InitScriptEngine())
2626  {
2627  LogFatal(LoadResStr("IDS_PRC_FAIL"));
2628  return false;
2629  }
2630  SetInitProgress(8);
2631 
2632  // Scenario components
2633  if (!LoadScenarioComponents())
2634  {
2635  LogFatal(LoadResStr("IDS_PRC_FAIL"));
2636  return false;
2637  }
2638  SetInitProgress(9);
2639 
2640  // join local players for regular games
2641  // should be done before record/replay is initialized, so the players are stored in PlayerInfos.txt
2642  // for local savegame resumes, players are joined into PlayerInfos and later associated in InitPlayers
2643  if (!::Network.isEnabled())
2644  {
2645  if (!PlayerInfos.InitLocal())
2646  {
2647  LogFatal(LoadResStr("IDS_PRC_FAIL"));
2648  return false;
2649  }
2650  }
2651 
2652  // for replays, make sure teams are assigned correctly
2653  if (C4S.Head.Replay)
2654  {
2655  PlayerInfos.RecheckAutoGeneratedTeams(); // checks that all teams used in playerinfos exist
2656  Teams.RecheckPlayers(); // syncs player list of teams with teams set in PlayerInfos
2657  }
2658 
2659  // set up control (inits Record/Replay)
2660  if (!InitControl())
2661  {
2662  return false;
2663  }
2664 
2665  // Graphics and fonts (may reinit main font, too)
2666  // redundant call in NETWORK2; but it may do scenario local overloads
2667  Log(LoadResStr("IDS_PRC_GFXRES"));
2668  if (!GraphicsResource.Init())
2669  {
2670  LogFatal(LoadResStr("IDS_PRC_FAIL"));
2671  return false;
2672  }
2673  SetInitProgress(25);
2674 
2675  // Definitions
2676  if (!InitDefs())
2677  {
2678  return false;
2679  }
2680  SetInitProgress(55);
2681 
2682  // Scenario scripts (and local system.ocg)
2684  // Map scripts
2686  // Scenario objects
2688  // After defs to get overloading priority
2690  {
2691  LogFatal(LoadResStr("IDS_PRC_FAIL"));
2692  return false;
2693  }
2694  SetInitProgress(57);
2695 
2696  // Final init for loaded player commands. Before linking scripts, so CON_* constants are registered
2698 
2699  // Register constants for scenario options
2701 
2702  // Now that all controls and assignments are known, resolve user overloads on control assignments
2704  {
2705  return false;
2706  }
2707  // Sort assignments by priority. Should be done last, because the user should not see this order in the control config dialog
2709  // (Theoretically, PlayerControlDefaultAssignmentSets could be cleared now. However, the amount of memory used is negligible)
2710 
2711  // Link scripts
2712  if (!LinkScriptEngine())
2713  {
2714  return false;
2715  }
2716  SetInitProgress(58);
2717 
2718  // Materials
2719  if (!InitMaterialTexture())
2720  {
2721  LogFatal(LoadResStr("IDS_PRC_MATERROR"));
2722  return false;
2723  }
2724  SetInitProgress(60);
2725 
2726  // prepare script menus
2727  assert(!ScriptGuiRoot);
2728  ScriptGuiRoot = std::make_unique<C4ScriptGuiWindow>();
2729  }
2730  else if (load_sky)
2731  {
2732  // Sky needs graphics loaded, for shaders
2733  if (!GraphicsResource.Init())
2734  {
2735  LogFatal(LoadResStr("IDS_PRC_FAIL"));
2736  return false;
2737  }
2738  }
2739 
2740  // Load section sounds
2741  Application.SoundSystem.LoadEffects(group, nullptr, true);
2742 
2743  // determine startup player and team count, which may be used for initial map generation
2744  if (!FrameCounter)
2745  {
2748  }
2749 
2750  // The Landscape is the last long chunk of loading time, so it's a good place to start the music fadeout
2751  if (init_mode == IM_Normal)
2752  {
2754  }
2755  // Landscape
2756  Log(LoadResStr("IDS_PRC_LANDSCAPE"));
2757  bool landscape_loaded = false;
2758  if (!Landscape.Init(group, init_mode != IM_Normal, load_sky, landscape_loaded, !!C4S.Head.SaveGame))
2759  {
2760  LogFatal(LoadResStr("IDS_ERR_GBACK"));
2761  return false;
2762  }
2763  SetInitProgress(88);
2764  // the savegame flag is set if runtime data is present, in which case this is to be used
2765  // except for scenario sections
2766  if (landscape_loaded && (!C4S.Head.SaveGame || init_mode == IM_Section))
2767  {
2769  }
2770  // clear old landscape data
2771  if (init_mode != IM_Normal && landscape_loaded)
2772  {
2773  PXS.Clear();
2774  MassMover.Clear();
2775  }
2776  SetInitProgress(89);
2777  // Init main object list
2779 
2780  // Pathfinder
2781  if (init_mode == IM_Normal)
2782  {
2784  }
2785  SetInitProgress(90);
2786 
2787  // PXS
2788  if (group.FindEntry(C4CFN_PXS))
2789  {
2790  if (!PXS.Load(group))
2791  {
2792  LogFatal(LoadResStr("IDS_ERR_PXS"));
2793  return false;
2794  }
2795  }
2796  SetInitProgress(91);
2797 
2798  // MassMover
2799  if (group.FindEntry(C4CFN_MassMover))
2800  {
2801  if (!MassMover.Load(group))
2802  {
2803  LogFatal(LoadResStr("IDS_ERR_MOVER"));
2804  return false;
2805  }
2806  }
2807  SetInitProgress(92);
2808 
2809  // definition value overloads
2810  // TODO: Remove this function? We could move value to script and allow it through regular overloads
2811  if (init_mode == IM_Normal)
2812  {
2814  }
2815 
2816  // runtime data
2817  if (!CompileRuntimeData(group, init_mode, C4S.Head.SaveGame, C4S.Head.NetworkGame, numbers))
2818  {
2819  LogFatal(LoadResStr("IDS_PRC_FAIL"));
2820  return false;
2821  }
2822 
2823  SetInitProgress(93);
2824 
2825  // Load round results
2826  if (init_mode == IM_Normal)
2827  {
2828  if (group.FindEntry(C4CFN_RoundResults))
2829  {
2830  if (!RoundResults.Load(group, C4CFN_RoundResults))
2831  {
2832  LogFatal(LoadResStr("IDS_ERR_ERRORLOADINGROUNDRESULTS"));
2833  return false;
2834  }
2835  }
2836  else
2837  {
2838  RoundResults.Init();
2839  }
2840  // Per-scenario flag, ignored in sections.
2842  }
2843 
2844  // Denumerate game data pointers
2845  if (init_mode == IM_Normal) ScriptEngine.Denumerate(numbers);
2846  if (init_mode == IM_Normal) GlobalSoundModifier.Denumerate(numbers);
2847 
2848  numbers->Denumerate();
2849  if (init_mode == IM_Normal)
2850  {
2851  ScriptGuiRoot->Denumerate(numbers);
2852  }
2853 
2854  // Object.PostLoad must happen after number->Denumerate(), becuase UpdateFace() will access Action proplist,
2855  // which might have a non-denumerated prototype otherwise
2856  Objects.PostLoad(init_mode == IM_Section, numbers);
2857 
2858  // Check object enumeration
2859  if (!CheckObjectEnumeration())
2860  {
2861  return false;
2862  }
2863 
2864  // Okay; everything in denumerated state from now on
2865  PointersDenumerated = true;
2866 
2867  // scenario objects script
2869  {
2871  }
2872 
2873  // Environment
2874  if (!C4S.Head.NoInitialize && landscape_loaded)
2875  {
2876  Log(LoadResStr("IDS_PRC_ENVIRONMENT"));
2877  InitVegetation();
2878  InitInEarth();
2879  InitAnimals();
2880  InitEnvironment();
2881  InitRules();
2882  InitGoals();
2884  }
2885  SetInitProgress(94);
2886 
2887  // Weather
2888  if (landscape_loaded)
2889  {
2891  }
2892  SetInitProgress(96);
2893 
2894  // close any gfx groups, because they are no longer needed (after sky is initialized)
2896 
2897  if (init_mode == IM_Normal) // reload doesn't affect the music (takes too long)
2898  {
2899  // Music
2902  if (::Config.Sound.RXMusic)
2903  {
2904  // Play something that is not Frontend.mid
2906  }
2907  else
2908  {
2910  }
2911  SetInitProgress(97);
2912  }
2913 
2914  return true;
2915 }
2916 
2918 {
2919  // Validate object owners & assign loaded info objects
2921  Objects.AssignInfo();
2922  Objects.AssignLightRange(); // update FoW-repellers
2923 
2924  // Ambience init (before scenario construction, so the scenario can easily modify ambience in Initialize)
2925  if (!C4S.Head.SaveGame)
2926  {
2928  }
2929 
2930  // Script constructor call
2931  int32_t object_count = Objects.ObjectCount();
2932  if (!C4S.Head.SaveGame)
2933  {
2935  }
2936  if (Objects.ObjectCount() != object_count)
2937  {
2938  fScriptCreatedObjects = true;
2939  }
2940 
2941  // Player final init
2942  C4Player *player;
2943  for (player = Players.First; player; player = player->Next)
2944  {
2945  if (init_mode == IM_ReInit)
2946  {
2947  player->ScenarioInit();
2948  }
2949  player->FinalInit(!C4S.Head.SaveGame);
2950  }
2951 
2952  // Create viewports
2953  if (init_mode == IM_Normal)
2954  {
2955  for (player = Players.First; player; player = player->Next)
2956  {
2957  if (player->LocalControl)
2958  {
2960  }
2961  }
2962  // Check fullscreen viewports
2964  // update halt state
2966 
2967  // Host: players without connected clients: remove via control queue
2968  if (Network.isEnabled() && Network.isHost())
2969  {
2970  for (int32_t cnt = 0; cnt < Players.GetCount(); cnt++)
2971  {
2972  if (Players.GetByIndex(cnt)->AtClient < 0)
2973  {
2974  Players.Remove(Players.GetByIndex(cnt), true, false);
2975  }
2976  }
2977  }
2978 
2979  // It should be safe now to reload stuff
2980  if (pFileMonitor)
2981  {
2982  pFileMonitor->StartMonitoring();
2983  }
2984  }
2985  return true;
2986 }
2987 
2989 {
2990  // engine functions
2995 
2996  // system functions: check if system group is open
2998  {
2999  LogFatal(LoadResStr("IDS_ERR_INVALIDSYSGRP"));
3000  return false;
3001  }
3003 
3004  // get scripts
3005  char filename[_MAX_FNAME_LEN] = { 0 };
3006  File.ResetSearch();
3007  while (File.FindNextEntry(C4CFN_ScriptFiles, filename, nullptr, !!filename[0]))
3008  {
3009  // host will be destroyed by script engine, so drop the references
3010  C4ScriptHost *script_host = new C4ExtraScriptHost();
3011  script_host->Reg2List(&ScriptEngine);
3012  script_host->Load(File, filename, Config.General.LanguageEx, &MainSysLangStringTable);
3013  }
3014 
3015  // if it's a physical group: watch out for changes
3016  if (!File.IsPacked() && Game.pFileMonitor)
3017  {
3018  Game.pFileMonitor->AddDirectory(File.GetFullName().getData());
3019  }
3020 
3021  // Prepare host for Objects.c script
3024 
3025  C4Value scen_obj_script_val;
3026  scen_obj_script_val.SetPropList(pScenarioObjectsScript->GetPropList());
3027  ::ScriptEngine.RegisterGlobalConstant("ScenarioObjects", scen_obj_script_val);
3028 
3029  // load standard clonk names
3030  Names.Load(File, C4CFN_Names);
3031 
3032  return true;
3033 }
3034 
3036 {
3037  // Link script engine (resolve includes/appends, generate code)
3039 
3040  // display errors
3041  LogF("C4AulScriptEngine linked - %d line%s, %d warning%s, %d error%s",
3042  ScriptEngine.lineCnt, (ScriptEngine.lineCnt != 1 ? "s" : ""),
3043  ScriptEngine.warnCnt, (ScriptEngine.warnCnt != 1 ? "s" : ""),
3044  ScriptEngine.errCnt, (ScriptEngine.errCnt != 1 ? "s" : ""));
3045 
3046  // update material pointers
3048 
3049  if (C4AulDebug *pDebug = C4AulDebug::GetDebugger())
3050  {
3051  if (!pDebug->Listen(DebugPort, !!DebugWait))
3052  {
3053  return false;
3054  }
3055  }
3056 
3057  return true;
3058 }
3059 
3061 {
3063 
3064  // update effect pointers
3066 
3067  // update material pointers
3069 
3070  return true;
3071 }
3072 
3074 {
3075  int32_t player_count = 0;
3076 
3078  {
3079  // Load players to restore from scenario
3080  C4PlayerInfoList LocalRestorePlayerInfos;
3081  LocalRestorePlayerInfos.Load(ScenarioFile, C4CFN_SavePlayerInfos, &ScenarioLangStringTable);
3082  // -- runtime join player restore
3083  // all restore functions will be executed on RestorePlayerInfos, because the main playerinfos may be more up-to-date
3084  // extract all players to temp store and update filenames to point there
3085  if (!LocalRestorePlayerInfos.RecreatePlayerFiles())
3086  {
3087  LogFatal(LoadResStr("IDS_ERR_NOPLRFILERECR"));
3088  return false;
3089  }
3090  // recreate the files
3091  if (!LocalRestorePlayerInfos.RecreatePlayers(numbers))
3092  {
3093  LogFatal(LoadResStr("IDS_ERR_NOPLRNETRECR"));
3094  return false;
3095  }
3096  }
3098  {
3099  // -- savegame player restore
3100  // for savegames or regular scenarios with restore infos, the player info list should have been loaded from the savegame
3101  // or got restored from game text in OpenScenario()
3102  // merge restore player info into main player info list now
3103  // -for single-host games, this will move all infos
3104  // -for network games, it will merge according to savegame association done in the lobby
3105  // for all savegames, script players get restored by adding one new script player for earch savegame script player to the host
3107  {
3108  LogFatal(LoadResStr("IDS_ERR_NOPLRSAVEINFORECR"));
3109  return false;
3110  }
3112  // try to associate local filenames (non-net+replay) or resources (net) with all player infos
3114  {
3115  LogFatal(LoadResStr("IDS_ERR_NOPLRFILERECR"));
3116  return false;
3117  }
3118  // recreate players by joining all players whose joined-flag is already set
3119  if (!PlayerInfos.RecreatePlayers(numbers))
3120  {
3121  LogFatal(LoadResStr("IDS_ERR_NOPLRSAVERECR"));
3122  return false;
3123  }
3124  }
3125 
3126  // any regular non-net non-replay game: Do the normal control queue join
3127  // this includes additional player joins in savegames
3128  if (!Network.isEnabled() && !Control.NoInput())
3129  {
3131  {
3132  // error joining local players - either join was done earlier somehow,
3133  // or the player count check will soon end this round
3134  }
3135  }
3136 
3137  // non-replay player joins will be done by player info list when go tick is reached
3138  // this is handled by C4Network2Players and needs no further treatment here
3139  // set iPlrCnt for player count check in host/single games
3140  player_count = PlayerInfos.GetJoinIssuedPlayerCount();
3141 
3142  // Check valid participating player numbers (host/single only)
3143  if (!Network.isEnabled() || (Network.isHost() && !fLobby))
3144  {
3145 #ifndef USE_CONSOLE
3146  // No players in fullscreen
3147  if (player_count == 0)
3148  {
3149  if (!Application.isEditor && !Control.NoInput())
3150  {
3151  LogFatal(LoadResStr("IDS_CNS_NOFULLSCREENPLRS")); return false;
3152  }
3153  }
3154 #endif
3155  // Too many players
3156  if (player_count > Game.Parameters.MaxPlayers)
3157  {
3158  if (!Application.isEditor)
3159  {
3160  LogFatal(FormatString(LoadResStr("IDS_PRC_TOOMANYPLRS"),Game.Parameters.MaxPlayers).getData());
3161  return false;
3162  }
3163  else
3164  {
3166  }
3167  }
3168  }
3169  // Console and no real players: halt
3170  if (Console.Active)
3171  {
3172  if (!fLobby)
3173  {
3175  {
3176  ++HaltCount;
3177  }
3178  }
3179  }
3180  return true;
3181 }
3182 
3184 {
3185  // update random seed
3186  if (C4S.Head.NetworkGame || C4S.Head.Replay)
3187  {
3189  }
3190  // Randomize
3192 
3193  // Replay?
3194  if (C4S.Head.Replay)
3195  {
3196  // no joins
3197  PlayerFilenames[0]=0;
3198  // start playback
3200  {
3201  return false;
3202  }
3203  // no record!
3204  Record = false;
3205  }
3206  else if (Network.isEnabled())
3207  {
3208  // initialize
3210  {
3211  return false;
3212  }
3213  // league? always record
3214  if (Parameters.isLeague())
3215  {
3216  Record = true;
3217  }
3218  }
3219  // Otherwise: local game
3220  else
3221  {
3222  // init
3224  {
3225  return false;
3226  }
3227  }
3228 
3229  // record?
3230  if (Record)
3231  {
3232  if (!Control.StartRecord(true, Parameters.doStreaming()))
3233  {
3234  // Special: If this happens for a league host, the game must not start.
3236  {
3237  LogFatal(LoadResStr("IDS_ERR_NORECORD"));
3238  return false;
3239  }
3240  else
3241  {
3242  Log(LoadResStr("IDS_ERR_NORECORD"));
3243  }
3244  }
3245  }
3246 
3247  return true;
3248 }
3249 
3251  C4ID *idlist, int32_t maxidlist)
3252 {
3253  int32_t cnt, cnt2, ccount, cpos;
3254  for (cpos = 0, cnt = 0; rlist.GetID(cnt); cnt++)
3255  {
3256  if (C4Id2Def(rlist.GetID(cnt,&ccount)))
3257  {
3258  for (cnt2 = 0; cnt2 < ccount; cnt2++)
3259  {
3260  if (cpos < maxidlist)
3261  {
3262  idlist[cpos] = rlist.GetID(cnt);
3263  cpos++;
3264  }
3265  }
3266  }
3267  }
3268  return cpos;
3269 }
3270 
3272 {
3273  int32_t cnt, tx, ty;
3274  for (cnt = 0; cnt < 35; cnt++) // cheap trys
3275  {
3276  tx = Random(::Landscape.GetWidth());
3277  ty = Random(::Landscape.GetHeight());
3278  if (GBackMat(tx, ty) == MEarth)
3279  {
3280  if (CreateObject(id, nullptr, NO_OWNER, tx, ty, Random(360)))
3281  {
3282  return true;
3283  }
3284  }
3285  }
3286  return false;
3287 }
3288 
3289 static bool PlaceVegetation_GetRandomPoint(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, C4PropList * shape_proplist, C4PropList * out_pos_proplist, int32_t *piTx, int32_t *piTy)
3290 {
3291  // Helper for C4Game::PlaceVegetation: return random position in rectangle. Use shape_proplist if provided.
3292  if (shape_proplist && out_pos_proplist)
3293  {
3294  C4AulParSet pars(C4VPropList(out_pos_proplist));
3295  if (!shape_proplist->Call(P_GetRandomPoint, &pars)) return false;
3296  *piTx = out_pos_proplist->GetPropertyInt(P_x);
3297  *piTy = out_pos_proplist->GetPropertyInt(P_y);
3298  }
3299  else
3300  {
3301  *piTx = iX + Random(iWdt);
3302  *piTy = iY + Random(iHgt);
3303  }
3304  return true;
3305 }
3306 
3307 static bool PlaceVegetation_IsPosInBounds(int32_t iTx, int32_t iTy, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, C4PropList * shape_proplist)
3308 {
3309  if (shape_proplist)
3310  {
3311  // check using shape proplist
3312  C4AulParSet pars(C4VInt(iTx), C4VInt(iTy));
3313  if (!shape_proplist->Call(P_IsPointContained, &pars)) return false;
3314  }
3315  else
3316  {
3317  // check using bounds rect
3318  if (iTy < iY) return false;
3319  }
3320  return true;
3321 }
3322 
3323 C4Object* C4Game::PlaceVegetation(C4PropList * PropList, int32_t x, int32_t y, int32_t wdt, int32_t hgt, int32_t growth, C4PropList * shape_proplist, C4PropList * out_pos_proplist)
3324 {
3325  int32_t cnt, iTx, iTy, iMaterial;
3326 
3327  // Get definition
3328  C4Def* pDef;
3329  if (!PropList || !(pDef = PropList->GetDef())) return nullptr;
3330 
3331  // No growth specified: full growth
3332  if (growth <= 0)
3333  {
3334  growth = FullCon;
3335  }
3336 
3337  // Place by placement type
3338  switch (PropList->GetPropertyInt(P_Placement))
3339  {
3340 
3341  // Surface soil
3342  case C4D_Place_Surface:
3343  for (cnt = 0; cnt < 20; cnt++)
3344  {
3345  // Random hit within target area
3346  if (!PlaceVegetation_GetRandomPoint(x, y, wdt, hgt, shape_proplist, out_pos_proplist, &iTx, &iTy)) break;
3347  // Above tunnel
3348  while ((iTy > 0) && Landscape.GetBackPix(iTx, iTy) == 0) iTy--;
3349  // Above semi solid
3350  if (!AboveSemiSolid(iTx, iTy) || !Inside<int32_t>(iTy, 50,::Landscape.GetHeight()-50))
3351  continue;
3352  // Still inside bounds?
3353  if (!PlaceVegetation_IsPosInBounds(iTx, iTy, x, y, wdt, hgt, shape_proplist)) continue;
3354  // Free above
3355  if (GBackSemiSolid(iTx, iTy-pDef->Shape.Hgt) || GBackSemiSolid(iTx, iTy-pDef->Shape.Hgt/2))
3356  continue;
3357  // Free upleft and upright
3358  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))
3359  continue;
3360  // Soil check
3361  iTy += 3; // two pix into ground
3362  iMaterial = GBackMat(iTx, iTy);
3363  if (iMaterial!=MNone) if (::MaterialMap.Map[iMaterial].Soil)
3364  {
3365  iTy += 5;
3366  return CreateObjectConstruction(PropList, nullptr, NO_OWNER, iTx, iTy, growth);
3367  }
3368  }
3369  break;
3370 
3371  // Underwater
3372  case C4D_Place_Liquid:
3373  // Random range
3374  if (!PlaceVegetation_GetRandomPoint(x, y, wdt, hgt, shape_proplist, out_pos_proplist, &iTx, &iTy)) return nullptr;
3375  // Find liquid
3376  if (!FindSurfaceLiquid(iTx, iTy, pDef->Shape.Wdt, pDef->Shape.Hgt))
3377  if (!FindLiquid(iTx, iTy, pDef->Shape.Wdt, pDef->Shape.Hgt))
3378  return nullptr;
3379  // Liquid bottom
3380  if (!SemiAboveSolid(iTx, iTy)) return nullptr;
3381  iTy += 3;
3382  // Still inside bounds?
3383  if (!PlaceVegetation_IsPosInBounds(iTx, iTy, x, y, wdt, hgt, shape_proplist)) return nullptr;
3384  // Create object
3385  return CreateObjectConstruction(PropList, nullptr, NO_OWNER, iTx, iTy, growth);
3386  break;
3387 
3388  // Underground/Tunnel
3389  case C4D_Place_Subsurface:
3390  for (cnt = 0; cnt < 5; cnt++)
3391  {
3392  // Random range
3393  if (!PlaceVegetation_GetRandomPoint(x, y, wdt, hgt, shape_proplist, out_pos_proplist, &iTx, &iTy)) break;
3394  // Find tunnel
3395  if (!FindTunnel(iTx, iTy, pDef->Shape.Wdt, pDef->Shape.Hgt))
3396  continue;
3397  // Tunnel bottom
3398  if (!AboveSemiSolid(iTx, iTy)) continue;
3399  // Still inside bounds?
3400  if (!PlaceVegetation_IsPosInBounds(iTx, iTy, x, y, wdt, hgt, shape_proplist)) continue;
3401  // Soil check
3402  iTy += 3; // two pix into ground
3403  iMaterial = GBackMat(iTx, iTy);
3404  if (iMaterial!=MNone) if (::MaterialMap.Map[iMaterial].Soil)
3405  {
3406  // Create object
3407  iTy += 5;
3408  return CreateObjectConstruction(PropList, nullptr, NO_OWNER, iTx, iTy, growth);
3409  }
3410  }
3411 
3412  // Under- or aboveground
3413  case C4D_Place_BothSurface:
3414  for (cnt = 0; cnt < 20; cnt++)
3415  {
3416  // Random hit within target area
3417  if (!PlaceVegetation_GetRandomPoint(x, y, wdt, hgt, shape_proplist, out_pos_proplist, &iTx, &iTy)) break;
3418  // Above semi solid
3419  if (!AboveSemiSolid(iTx, iTy) || !Inside<int32_t>(iTy, 50,::Landscape.GetHeight()-50))
3420  continue;
3421  // Free above
3422  if (GBackSemiSolid(iTx, iTy-pDef->Shape.Hgt) || GBackSemiSolid(iTx, iTy-pDef->Shape.Hgt/2))
3423  continue;
3424  // Still inside bounds?
3425  if (!PlaceVegetation_IsPosInBounds(iTx, iTy, x, y, wdt, hgt, shape_proplist))
3426  continue;
3427  // Free upleft and upright
3428  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))
3429  continue;
3430  // Soil check
3431  iTy += 3; // two pix into ground
3432  iMaterial = GBackMat(iTx, iTy);
3433  if (iMaterial!=MNone) if (::MaterialMap.Map[iMaterial].Soil)
3434  {
3435  iTy += 5;
3436  return CreateObjectConstruction(PropList, nullptr, NO_OWNER, iTx, iTy, growth);
3437  }
3438  }
3439 
3440  }
3441 
3442  // Undefined placement type
3443  return nullptr;
3444 }
3445 
3447 {
3448  C4Def * pDef;
3449  if (!PropList || !(pDef = PropList->GetDef())) return nullptr;
3450  int32_t iX, iY;
3451  // Placement
3452  switch (PropList->GetPropertyInt(P_Placement))
3453  {
3454  // Running free
3455  case C4D_Place_Surface:
3456  iX = Random(::Landscape.GetWidth()); iY = Random(::Landscape.GetHeight());
3457  if (!FindSolidGround(iX, iY, pDef->Shape.Wdt)) return nullptr;
3458  break;
3459  // In liquid
3460  case C4D_Place_Liquid:
3461  iX = Random(::Landscape.GetWidth()); iY = Random(::Landscape.GetHeight());
3462  if (!FindSurfaceLiquid(iX, iY, pDef->Shape.Wdt, pDef->Shape.Hgt))
3463  if (!FindLiquid(iX, iY, pDef->Shape.Wdt, pDef->Shape.Hgt))
3464  return nullptr;
3465  iY += pDef->Shape.Hgt/2;
3466  break;
3467  // Floating in air
3468  case C4D_Place_Air:
3469  iX = Random(::Landscape.GetWidth());
3470  for (iY = 0; (iY<::Landscape.GetHeight()) && !GBackSemiSolid(iX, iY); iY++) {}
3471  if (iY <= 0) return nullptr;
3472  iY = Random(iY);
3473  break;
3474  default:
3475  return nullptr;
3476  }
3477  // Create object
3478  return CreateObject(PropList, nullptr, NO_OWNER, iX, iY);
3479 }
3480 
3482 {
3483  const int32_t maxvid = 100;
3484  int32_t cnt, vidnum;
3485  C4ID vidlist[maxvid];
3486  // Amount
3488  // List all valid IDs from C4S
3489  vidnum = ListExpandValids(C4S.Landscape.InEarth, vidlist, maxvid);
3490  // Place
3491  if (vidnum > 0)
3492  for (cnt = 0; cnt < amt; cnt++)
3493  PlaceInEarth(vidlist[Random(vidnum)]);
3494 
3495 }
3496 
3498 {
3499  const int32_t maxvid = 100;
3500  int32_t cnt, vidnum;
3501  C4ID vidlist[maxvid];
3502  // Amount
3503  int32_t amt=(::Landscape.GetWidth()/50)*C4S.Landscape.VegLevel.Evaluate()/100;
3504  // Get percentage vidlist from C4S
3505  vidnum = ListExpandValids(C4S.Landscape.Vegetation, vidlist, maxvid);
3506  // Place vegetation
3507  if (vidnum > 0)
3508  {
3509  for (cnt = 0; cnt < amt; cnt++)
3510  {
3511  PlaceVegetation(C4Id2Def(vidlist[Random(vidnum)]),0, 0,::Landscape.GetWidth(),::Landscape.GetHeight(),-1, nullptr, nullptr);
3512  }
3513  }
3514 }
3515 
3517 {
3518  int32_t cnt, cnt2;
3519  C4ID idAnimal; int32_t iCount;
3520  // Place animals
3521  for (cnt = 0; (idAnimal = C4S.Animals.FreeLife.GetID(cnt,&iCount)); cnt++)
3522  {
3523  for (cnt2 = 0; cnt2 < iCount; cnt2++)
3524  {
3525  PlaceAnimal(C4Id2Def(idAnimal));
3526  }
3527  }
3528  // Place nests
3529  for (cnt = 0; (idAnimal = C4S.Animals.EarthNest.GetID(cnt,&iCount)); cnt++)
3530  {
3531  for (cnt2 = 0; cnt2 < iCount; cnt2++)
3532  {
3533  PlaceInEarth(idAnimal);
3534  }
3535  }
3536 }
3537 
3538 
3540 {
3541  // Info
3543  // Overload clonk names from scenario file
3545  {
3547  }
3548  // scenario sections
3549  char filename[_MAX_FNAME_LEN] = { 0 };
3551  *filename = 0;
3552  while (ScenarioFile.FindNextEntry(C4CFN_ScenarioSections, filename, nullptr, !!*filename))
3553  {
3554  // get section name
3555  char section_name[_MAX_FNAME_LEN];
3556  int32_t wildcard_pos = SCharPos('*', C4CFN_ScenarioSections);
3557  SCopy(filename + wildcard_pos, section_name, _MAX_FNAME);
3558  RemoveExtension(section_name);
3559  if (std::strlen(section_name)>C4MaxName || !*section_name)
3560  {
3561  DebugLog("invalid section name");
3562  LogFatal(FormatString(LoadResStr("IDS_ERR_SCENSECTION"), filename).getData());
3563  return false;
3564  }
3565  // load this section into temp store
3566  C4ScenarioSection *pSection = new C4ScenarioSection(section_name);
3567  if (!pSection->ScenarioLoad(filename, false))
3568  {
3569  LogFatal(FormatString(LoadResStr("IDS_ERR_SCENSECTION"), filename).getData());
3570  return false;
3571  }
3572  }
3573  // Success
3574  return true;
3575 }
3576 
3578 {
3579  // called for scenario local and definition local System.ocg groups
3580  C4Group SysGroup;
3581  char filename[_MAX_FNAME_LEN] = { 0 };
3582  if (SysGroup.OpenAsChild(&parent_group, C4CFN_System))
3583  {
3584  C4LangStringTable *local_strings = new C4LangStringTable();
3586  // load custom scenario control definitions
3587  if (SysGroup.FindEntry(C4CFN_PlayerControls))
3588  {
3589  Log(LoadResStr("IDS_PRC_LOADSCEPLRCTRL"));
3590  C4PlayerControlFile PlayerControlFile;
3591  if (!PlayerControlFile.Load(SysGroup, C4CFN_PlayerControls, local_strings))
3592  {
3593  // non-fatal error here
3594  Log(LoadResStr("IDS_PRC_LOADSCEPLRCTRLFAIL"));
3595  }
3596  else
3597  {
3598  // local definitions loaded successfully - merge into global definitions
3599  PlayerControlDefs.MergeFrom(PlayerControlFile.GetControlDefs());
3602  }
3603  }
3604  // load all scripts in there
3605  SysGroup.ResetSearch();
3606  while (SysGroup.FindNextEntry(C4CFN_ScriptFiles, filename, nullptr, !!filename[0]))
3607  {
3608  // host will be destroyed by script engine, so drop the references
3609  C4ScriptHost *script_host = new C4ExtraScriptHost();
3610  script_host->Reg2List(&ScriptEngine);
3611  script_host->Load(SysGroup, filename, Config.General.LanguageEx, local_strings);
3612  }
3613  // if it's a physical group: watch out for changes
3614  if (!SysGroup.IsPacked() && Game.pFileMonitor)
3615  {
3616  Game.pFileMonitor->AddDirectory(SysGroup.GetFullName().getData());
3617  }
3618  SysGroup.Close();
3619  // release string table if no longer used
3620  local_strings->DelRef();
3621  }
3622  return true;
3623 }
3624 
3626 {
3627  C4CustomKey::CodeList Keys;
3628 
3629  // clear previous
3630  KeyboardInput.Clear();
3631 
3632  // globals
3637 
3638  // main ingame
3643 
3644  // debug mode & debug displays
3649 
3650  // playback speed - improve...
3653 
3654  // fullscreen menu
3655  Keys.clear(); Keys.emplace_back(K_LEFT);
3658  Keys.clear(); Keys.emplace_back(K_RIGHT);
3661  Keys.clear(); Keys.emplace_back(K_UP);
3664  Keys.clear(); Keys.emplace_back(K_DOWN);
3667  Keys.clear(); Keys.emplace_back(K_SPACE); Keys.emplace_back(K_RETURN);
3669  KeyboardInput.RegisterKey(new C4CustomKey(Keys, "FullscreenMenuOK", KEYSCOPE_FullSMenu, new C4KeyCBEx<C4FullScreen, BYTE> (FullScreen, COM_MenuEnter, &C4FullScreen::MenuKeyControl))); // name used by PlrControlKeyName
3670  Keys.clear(); Keys.emplace_back(K_ESCAPE);
3672  KeyboardInput.RegisterKey(new C4CustomKey(Keys, "FullscreenMenuCancel", KEYSCOPE_FullSMenu, new C4KeyCBEx<C4FullScreen, BYTE> (FullScreen, COM_MenuClose, &C4FullScreen::MenuKeyControl))); // name used by PlrControlKeyName
3673  Keys.clear(); Keys.emplace_back(K_SPACE);
3675  KeyboardInput.RegisterKey(new C4CustomKey(Keys, "FullscreenMenuOpen", KEYSCOPE_FreeView, new C4KeyCB <C4FullScreen> (FullScreen, &C4FullScreen::ActivateMenuMain))); // name used by C4MainMenu!
3677 
3678  // chat
3679  Keys.clear();
3680  Keys.emplace_back(K_RETURN);
3681  Keys.emplace_back(K_F2); // alternate chat key, if RETURN is blocked by player control
3684 
3692 
3693  // console keys
3702 
3703  // no default keys assigned
3711 
3712  // load any custom keysboard overloads
3714 
3715  // done, success
3716  return true;
3717 }
3718 
3720 {
3721  // Reload System.ocg string table
3723 }
3724 
3726 {
3727  // Load controls and default control sets
3728  C4PlayerControlFile PlayerControlFile;
3730  {
3731  LogFatal("[!]Error loading player controls");
3732  return false;
3733  }
3734  PlayerControlDefs = PlayerControlFile.GetControlDefs();
3738  // Merge w/ config settings into user control sets
3739  // User settings will be cleared and re-merged again later after scenario/definition control overloads, but initialization
3740  // is needed already for config dialogs
3742  {
3743  return false;
3744  }
3745  return true;
3746 }
3747 
3749 {
3750  // Merge config control settings with user settings
3755  return true;
3756 }
3757 
3758 C4Player *C4Game::JoinPlayer(const char *filename, int32_t at_client, const char *at_client_name, C4PlayerInfo *info)
3759 {
3760  assert(info);
3761  C4Player *player;
3762  // Join
3763  if (!( player = Players.Join(filename, true, at_client, at_client_name, info, nullptr) ))
3764  {
3765  return nullptr;
3766  }
3767  // Player final init
3768  player->FinalInit(true);
3769  // Create player viewport
3770  if (player->LocalControl)
3771  {
3773  }
3774  // Check fullscreen viewports
3776  // Update menus
3777  Console.UpdateMenus();
3778  // Append player name to list of session player names (no duplicates)
3779  if (!SIsModule(PlayerNames.getData(), player->GetName()))
3780  {
3781  if (PlayerNames)
3782  {
3783  PlayerNames += ";";
3784  }
3785  PlayerNames += player->GetName();
3786  }
3787  // Success
3788  return player;
3789 }
3790 
3792 {
3793  // Do the InitializePlayers callback once all player joins have finished with at least one human player
3795  {
3796  InitialPlayersJoined = true;
3798  }
3799 }
3800 
3801 void C4Game::FixRandom(uint64_t seed)
3802 {
3803  FixedRandom(seed);
3804 }
3805 
3807 {
3808  // Duplication safety
3809  if (GameOver)
3810  {
3811  return false;
3812  }
3813  // Flag, log, call
3814  GameOver = true;
3815  Log(LoadResStr("IDS_PRC_GAMEOVER"));
3817  // Flag all surviving players as winners
3818  for (C4Player *pPlayer = Players.First; pPlayer; pPlayer = pPlayer->Next)
3819  {
3820  if (!pPlayer->Eliminated)
3821  {
3822  pPlayer->EvaluateLeague(false, true);
3823  }
3824  }
3825  // Immediately save config so mission access gained by this round is stored if the game crashes during shutdown
3826  // or in a following round
3827  Config.Save();
3828  return true;
3829 }
3830 
3832 {
3833  // safety
3834  if (GameOverDlgShown)
3835  {
3836  return;
3837  }
3838  // flag, show
3839  GameOverDlgShown = true;
3840 #ifndef USE_CONSOLE
3841  if (!Application.isEditor)
3842  {
3843  C4GameOverDlg *dialog = new C4GameOverDlg();
3844  dialog->SetDelOnClose();
3845  if (!dialog->Show(pGUI, true))
3846  {
3847  delete dialog;
3849  }
3850  }
3851 #endif
3852 }
3853 
3855 {
3857 }
3858 
3859 void C4Game::Synchronize(bool save_player_files)
3860 {
3861  // Log
3862  LogSilentF("Network: Synchronization (Frame %i) [PlrSave: %d]",FrameCounter, save_player_files);
3863  // callback to control (to start record)
3865  // Fix random
3867  // Synchronize members
3871  Objects.Synchronize();
3872  // synchronize local player files if desired
3873  // this will reset any InActionTimes!
3874  // (not in replay mode)
3875  if (save_player_files && !Control.isReplay())
3876  {
3878  }
3879  // callback to network
3880  if (Network.isEnabled())
3881  {
3883  }
3884  // TransferZone synchronization: Must do this after dynamic creation to avoid synchronization loss
3885  // if OnSynchronized-callbacks do sync-relevant changes
3887 }
3888 
3889 bool C4Game::InitNetworkFromAddress(const char *address)
3890 {
3891  StdCopyStrBuf strRefQueryFailed(LoadResStr("IDS_NET_REFQUERY_FAILED"));
3892  // Query reference
3893  C4Network2RefClient RefClient;
3894  if (!RefClient.Init() ||
3895  !RefClient.SetServer(address) ||
3896  !RefClient.QueryReferences())
3897  {
3898  LogFatal(FormatString(strRefQueryFailed.getData(), RefClient.GetError()).getData());
3899  return false;
3900  }
3901 
3902  // We have to wait for the answer
3903  StdStrBuf message = FormatString(LoadResStr("IDS_NET_REFQUERY_QUERYMSG"), address);
3904  Log(message.getData());
3905 
3906  // Set up wait dialog
3907  C4GUI::MessageDialog *dialog = nullptr;
3908  if (!Application.isEditor)
3909  {
3910  // create & show
3911  dialog = new C4GUI::MessageDialog(message.getData(), LoadResStr("IDS_NET_REFQUERY_QUERYTITLE"),
3913  if (!dialog || !dialog->Show(::pGUI, true))
3914  {
3915  return false;
3916  }
3917  }
3918  // Wait for response
3919  while (RefClient.isBusy())
3920  {
3921  // Execute GUI
3922  if (!Application.ScheduleProcs(100)
3923  || (dialog && dialog->IsAborted()))
3924  {
3925  delete dialog;
3926  return false;
3927  }
3928  // Check if reference is received
3929  if (!RefClient.Execute(0))
3930  {
3931  break;
3932  }
3933  }
3934  // Close dialog
3935  delete dialog;
3936 
3937  // Error?
3938  if (!RefClient.isSuccess())
3939  {
3940  LogFatal(FormatString(strRefQueryFailed.getData(), RefClient.GetError()).getData());
3941  return false;
3942  }
3943  // Get references
3944  C4Network2Reference **refs = nullptr;
3945  int32_t ref_count;
3946  if (!RefClient.GetReferences(refs, ref_count) || ref_count <= 0)
3947  {
3948  LogFatal(FormatString(strRefQueryFailed.getData(), LoadResStr("IDS_NET_REFQUERY_NOREF")).getData());
3949  return false;
3950  }
3951  // Connect to first reference
3952  bool connected = InitNetworkFromReference(*refs[0]);
3953  // Remove references
3954  for (int i = 0; i < ref_count; i++)
3955  {
3956  delete refs[i];
3957  }
3958  delete[] refs;
3959  return connected;
3960 }
3961 
3962 bool C4Game::InitNetworkFromReferenceFile(const char *temp_filename)
3963 {
3964  // We need winsock for address parsing
3965  WinSockHolder winsock;
3966  // Load reference from temp file + delete the temp file
3967  bool success = false;
3968  C4Network2Reference ref;
3969  StdStrBuf join_data;
3970  if (join_data.LoadFromFile(temp_filename))
3971  {
3972  CompileFromBuf<StdCompilerINIRead>(mkNamingAdapt(ref, "Reference"), join_data);
3973  success = true;
3974  }
3975  EraseFile(temp_filename);
3976  if (!success)
3977  {
3978  return false;
3979  }
3980  return InitNetworkFromReference(ref);
3981 }
3982 
3984 {
3985  // Find host data
3986  C4Client *host_data = reference.Parameters.Clients.getClientByID(C4ClientIDHost);
3987  if (!host_data)
3988  {
3989  LogFatal(LoadResStr("IDS_NET_INVALIDREF"));
3990  return false;
3991  }
3992  // Save scenario title
3993  ScenarioTitle = reference.getTitle();
3994  // Log
3995  LogF(LoadResStr("IDS_NET_JOINGAMEBY"), host_data->getName());
3996  // Init clients
3997  if (!Clients.Init())
3998  {
3999  return false;
4000  }
4001  // Connect
4002  if (Network.InitClient(reference, false) != C4Network2::IR_Success)
4003  {
4004  LogFatal(FormatString(LoadResStr("IDS_NET_NOHOSTCON"), host_data->getName()).getData());
4005  return false;
4006  }
4007  // init control
4009  {
4010  return false;
4011  }
4012  // init local player info list
4013  Network.Players.Init();
4014  return true;
4015 }
4016 
4018 {
4019  // Network not active?
4020  if (!NetworkActive)
4021  {
4022  // Clear client list
4023  if (!C4S.Head.Replay)
4024  {
4025  Clients.Init();
4026  }
4027  return true;
4028  }
4029  // network not active?
4030  if (C4S.Head.NetworkGame)
4031  {
4032  LogFatal(LoadResStr("IDS_NET_NODIRECTSTART"));
4033  return Clients.Init();
4034  }
4035  // replay?
4036  if (C4S.Head.Replay)
4037  {
4038  LogFatal(LoadResStr("IDS_PRC_NONETREPLAY"));
4039  return true;
4040  }
4041  // clear client list
4042  if (!Clients.Init())
4043  {
4044  return false;
4045  }
4046  // init network as host
4047  if (!Network.InitHost(fLobby))
4048  {
4049  return false;
4050  }
4051  // init control
4053  {
4054  return false;
4055  }
4056  // init local player info list
4057  Network.Players.Init();
4058  // allow connect
4059  Network.AllowJoin(true);
4060  // do lobby (if desired)
4061  if (fLobby)
4062  {
4063  if (!Network.DoLobby())
4064  {
4065  return false;
4066  }
4067  }
4068  else
4069  {
4070  // otherwise: start manually
4071  if (!Network.Start())
4072  {
4073  return false;
4074  }
4075  }
4076  // ok
4077  return true;
4078 }
4079 
4081 {
4082 
4083  struct Check
4084  {
4085  int32_t maxNumber{0};
4086  Check() = default;
4087  // Check valid & maximum number & duplicate numbers
4088  bool that(C4Object* obj)
4089  {
4090  // Invalid number
4091  if (obj->Number < 1)
4092  {
4093  LogFatal(FormatString("Invalid object enumeration number (%d) of object %s (x=%d)", obj->Number, obj->id.ToString(), obj->GetX()).getData());
4094  return false;
4095  }
4096  // Max
4097  if (obj->Number > maxNumber)
4098  {
4099  maxNumber = obj->Number;
4100  }
4101  // Duplicate
4102  for (C4Object *other : Objects)
4103  {
4104  if (other != obj)
4105  {
4106  if (obj->Number == other->Number)
4107  {
4108  LogFatal(FormatString("Duplicate object enumeration number %d (%s and %s)", other->Number, obj->GetName(), other->GetName()).getData());
4109  return false;
4110  }
4111  }
4112  }
4113  for (C4Object *inactive : Objects.InactiveObjects)
4114  {
4115  if (inactive != obj)
4116  {
4117  if (obj->Number == inactive->Number)
4118  {
4119  LogFatal(FormatString("Duplicate object enumeration number %d (%s and %s(i))", inactive->Number, obj->GetName(), inactive->GetName()).getData());
4120  return false;
4121  }
4122  }
4123  }
4124  return true;
4125  }
4126  };
4127 
4128  Check check;
4129  for (C4Object *obj : Objects)
4130  {
4131  if (!check.that(obj))
4132  {
4133  return false;
4134  }
4135  }
4136 
4137  for (C4Object *obj : Objects.InactiveObjects)
4138  {
4139  if (!check.that(obj))
4140  {
4141  return false;
4142  }
4143  }
4144 
4145  // Adjust enumeration index
4146  C4PropListNumbered::SetEnumerationIndex(check.maxNumber);
4147  // Done
4148  return true;
4149 }
4150 
4152 {
4153  C4ID overload_id;
4154  C4Def *def;
4155  // set new values
4156  for (int32_t i = 0; (overload_id = C4S.Game.Realism.ValueOverloads.GetID(i)); i++)
4157  {
4158  if ((def = ::Definitions.ID2Def(overload_id)))
4159  {
4160  def->Value = C4S.Game.Realism.ValueOverloads.GetIDCount(overload_id);
4161  }
4162  }
4163 }
4164 
4166 {
4167  // Place environment objects
4168  C4ID id;
4169  int32_t amount;
4170  for (int32_t index = 0; (id = C4S.Environment.Objects.GetID(index, &amount)); index++)
4171  {
4172  for (int32_t placed = 0; placed < amount; placed++)
4173  {
4174  CreateObject(id, nullptr);
4175  }
4176  }
4177 }
4178 
4180 {
4181  // Place rule objects
4182  C4ID id;
4183  int32_t amount;
4184  for (int32_t index = 0; (id = Parameters.Rules.GetID(index, &amount)); index++)
4185  {
4186  for (int32_t placed = 0; placed < std::max<int32_t>(amount, 1); placed++)
4187  {
4188  CreateObject(id, nullptr);
4189  }
4190  }
4191 }
4192 
4194 {
4195  // Place goal objects
4196  C4ID id;
4197  int32_t amount;
4198  for (int32_t index = 0; (id = Parameters.Goals.GetID(index, &amount)); index++)
4199  {
4200  for (int32_t placed = 0; placed < amount; placed++)
4201  {
4202  CreateObject(id, nullptr);
4203  }
4204  }
4205 }
4206 
4207 void C4Game::SetInitProgress(float to_progress)
4208 {
4209  // set new progress
4210  InitProgress = int32_t(to_progress);
4211  // if progress is more than one percent, display it
4213  {
4215  GraphicsSystem.MessageBoard->LogNotify();
4216  }
4217  // Cheap hack to get the Console window updated while loading
4218  // (unless game is running, i.e. section change - section change would be quick and timer execution can mess with things unpredictably)
4219  if (!IsRunning)
4220  {
4222 #ifdef WITH_QT_EDITOR
4223  Application.ProcessQtEvents();
4224 #endif
4225  }
4226 }
4227 
4228 void C4Game::OnResolutionChanged(unsigned int res_x, unsigned int res_y)
4229 {
4230  // update anything that's dependant on screen resolution
4231  pGUI->SetBounds(C4Rect(0, 0, res_x, res_y));
4232  if (FullScreen.Active)
4233  {
4235  }
4236  // note that this may fail if the gfx groups are closed already (runtime resolution change)
4237  // doesn't matter; old gfx are kept in this case
4240 }
4241 
4243 {
4244  // Layout changed: Re-resolve keys
4247 }
4248 
4249 bool C4Game::CreateSectionFromTempFile(const char *section_name, const char *temp_filename)
4250 {
4251  // Remove existing (temp) section of same name
4252  C4ScenarioSection *existing_section = pScenarioSections;
4253  C4ScenarioSection *prev = nullptr;
4254  while (existing_section)
4255  {
4256  if (SEqualNoCase(existing_section->name.getData(), section_name))
4257  {
4258  break;
4259  }
4260  else
4261  {
4262  existing_section = (prev = existing_section)->pNext;
4263  }
4264  }
4265  bool deleted_current_section = false;
4266  if (existing_section)
4267  {
4268  deleted_current_section = (existing_section == pCurrentScenarioSection);
4269  if (deleted_current_section)
4270  {
4271  pCurrentScenarioSection = nullptr;
4272  pScenarioObjectsScript = nullptr;
4273  }
4274  if (existing_section->pObjectScripts)
4275  {
4276  delete existing_section->pObjectScripts;
4277  }
4278  if (prev)
4279  {
4280  prev->pNext = existing_section->pNext;
4281  }
4282  else
4283  {
4284  pScenarioSections = existing_section->pNext;
4285  }
4286  existing_section->pNext = nullptr;
4287  delete existing_section;
4288  }
4289  // Create new (temp) section
4290  C4ScenarioSection *new_section = new C4ScenarioSection(section_name);
4291  if (!new_section->ScenarioLoad(temp_filename, true))
4292  {
4293  pScenarioSections = new_section->pNext;
4294  new_section->pNext = nullptr;
4295  delete new_section;
4296  return false;
4297  }
4298  // Re-Link current section into newly created section
4299  if (deleted_current_section)
4300  {
4301  pCurrentScenarioSection = new_section;
4302  pScenarioObjectsScript = new_section->pObjectScripts;
4303  }
4304  // Link new Objects.c (or re-link because old Objects.c was removed)
4306  return !!new_section;
4307 }
4308 
4309 bool C4Game::LoadScenarioSection(const char *section_name, DWORD flags)
4310 {
4311  // note on scenario section saving:
4312  // if a scenario section overwrites a value that had used the default values in the main scenario section,
4313  // returning to the main section with an unsaved landscape (and thus an unsaved scenario core),
4314  // would leave those values in the altered state of the previous section
4315  // scenario designers should regard this and always define any values, that are defined in subsections as well
4316  C4Group group;
4317  C4Group *section_group;
4318  // if current section was the loaded section (maybe main, but need not for resumed savegames)
4320  {
4321  if (!*CurrentScenarioSection)
4322  {
4324  }
4327  }
4328  // find section to load
4329  C4ScenarioSection *section_to_load = pScenarioSections;
4330  while (section_to_load)
4331  {
4332  if (SEqualNoCase(section_to_load->name.getData(), section_name))
4333  {
4334  break;
4335  }
4336  else
4337  {
4338  section_to_load = section_to_load->pNext;
4339  }
4340  }
4341  if (!section_to_load)
4342  {
4343  DebugLogF("LoadScenarioSection: scenario section %s not found!", section_name);
4344  return false;
4345  }
4346  // save current section state
4347  if (section_to_load != pCurrentScenarioSection && (flags & (C4S_SAVE_LANDSCAPE | C4S_SAVE_OBJECTS)))
4348  {
4349  // ensure that the section file does point to temp store
4351  {
4352  DebugLogF("LoadScenarioSection(%s): could not extract section files of current section %s", section_name, pCurrentScenarioSection->name.getData());
4353  return false;
4354  }
4355  // open current group
4356  if (!(section_group = pCurrentScenarioSection->GetGroupfile(group)))
4357  {
4358  DebugLog("LoadScenarioSection: error opening current group file");
4359  return false;
4360  }
4361  // store landscape, if desired (w/o material enumeration - that's assumed to stay consistent during the game)
4362  if (flags & C4S_SAVE_LANDSCAPE)
4363  {
4364  // storing the landscape implies storing the scenario core
4365  // otherwise, the ExactLandscape-flag would be lost
4366  // maybe imply exact landscapes by the existance of Landscape.png-files?
4367  C4Scenario scenario = C4S;
4368  scenario.SetExactLandscape();
4369  if (!scenario.Save(*section_group, true))
4370  {
4371  DebugLog("LoadScenarioSection: Error saving C4S");
4372  return false;
4373  }
4374  // landscape
4375  {
4376  C4DebugRecOff DBGRECOFF;
4377  if (!Landscape.Save(*section_group))
4378  {
4379  DebugLog("LoadScenarioSection: Error saving Landscape");
4380  return false;
4381  }
4382  }
4383  // PXS
4384  if (!PXS.Save(*section_group))
4385  {
4386  DebugLog("LoadScenarioSection: Error saving PXS");
4387  return false;
4388  }
4389  // MassMover (create copy, may not modify running data)
4390  C4MassMoverSet MassMoverSet;
4391  MassMoverSet.Copy(MassMover);
4392  if (!MassMoverSet.Save(*section_group))
4393  {
4394  DebugLog("LoadScenarioSection: Error saving MassMover");
4395  return false;
4396  }
4397  }
4398  // store objects
4399  if (flags & C4S_SAVE_OBJECTS)
4400  {
4401  C4ValueNumbers numbers;
4402  // objects: do not save info objects or inactive objects
4403  if (!SaveData(*section_group, true, false, false, &numbers))
4404  {
4405  DebugLog("LoadScenarioSection: Error saving objects");
4406  return false;
4407  }
4408  }
4409  // close current group
4410  if (group.IsOpen())
4411  {
4412  group.Close();
4413  }
4414  // mark modified
4416  }
4417  // open section group
4418  if (!(section_group = section_to_load->GetGroupfile(group)))
4419  {
4420  DebugLog("LoadScenarioSection: error opening group file");
4421  return false;
4422  }
4423  // remove all objects
4424  // do correct removal calls, because this will stop fire sounds, etc.
4425  for (C4Object *obj : Objects)
4426  {
4427  obj->AssignRemoval();
4428  }
4429  for (C4Object *obj : Objects)
4430  {
4431  if (obj->Status)
4432  {
4433  DebugLogF("LoadScenarioSection: WARNING: Object %d created in destruction process!", (int) obj->Number);
4434  ClearPointers(obj);
4435  }
4436  }
4437  // Final removal in case objects got recreated
4438  // Also kill inactive objects if scenario is reinitialized
4439  DeleteObjects(!!(flags & C4S_REINIT_SCENARIO));
4440  // remove global effects
4441  if (::ScriptEngine.pGlobalEffects && !(flags & C4S_KEEP_EFFECTS))
4442  {
4444  // scenario section call might have been done from a global effect
4445  // rely on dead effect removal for actually removing the effects; do not clear the array here!
4446  }
4447  if (::GameScript.pScenarioEffects && !(flags & C4S_KEEP_EFFECTS))
4448  {
4450  }
4451  // del particles as well
4453  // clear transfer zones
4454  TransferZones.Clear();
4455  // backup old sky
4456  std::string old_sky;
4457  old_sky = C4S.Landscape.SkyDef;
4458  // do not warn on ignored values in main section
4459  // they are caused because not all parts of scenario core are compiled on section change
4460  bool is_main_section = SEqualNoCase(section_to_load->name.getData(), C4ScenSect_Main);
4461  // overload scenario values (fails if no scenario core is present; that's OK)
4462  C4S.Load(*section_group, true, is_main_section);
4463  // determine whether a new sky has to be loaded
4464  bool should_load_new_sky = !SEqualNoCase(old_sky.c_str(), C4S.Landscape.SkyDef.c_str()) || section_group->FindEntry(C4CFN_Sky ".*");
4465  // set new Objects.c source
4466  Game.pScenarioObjectsScript = section_to_load->pObjectScripts;
4467  // remove reference to FoW from viewports, so that we can safely
4468  // reload the landscape and its FoW.
4470  // landscape initialization resets the RNG
4471  // set a new seed here to get new dynamic landscapes
4472  // TODO: add an option to disable this?
4473  RandomSeed = Random(2147483647);
4475  // re-init game in new section
4476  C4ValueNumbers numbers;
4477  if (!InitGame(*section_group, (flags & C4S_REINIT_SCENARIO) ? IM_ReInit : IM_Section, should_load_new_sky, &numbers))
4478  {
4479  DebugLog("LoadScenarioSection: Error reiniting game");
4481  return false;
4482  }
4483  // restore shelved proplists in case loading failed
4485  // set new current section
4486  pCurrentScenarioSection = section_to_load;
4488  // Final init on game re-init (doing mostly player initialization)
4489  if (flags & C4S_REINIT_SCENARIO)
4490  {
4492  // Extra InitializePlayers callback on the already-joined players to start intros, etc.
4493  // (unless the call is still pending - can happen if section is loaded during player join)
4495  {
4497  }
4498  }
4499  // resize viewports, and enable lighting again
4502  // done, success
4503  return true;
4504 }
4505 
4507 {
4508  // debug mode not allowed
4509  if (!Parameters.AllowDebug && !DebugMode)
4510  {
4511  GraphicsSystem.FlashMessage(LoadResStr("IDS_MSG_DEBUGMODENOTALLOWED"));
4512  return false;
4513  }
4514  DebugMode = !DebugMode;
4515  if (!DebugMode)
4516  {
4518  }
4519  GraphicsSystem.FlashMessageOnOff(LoadResStr("IDS_CTL_DEBUGMODE"), DebugMode);
4520  return true;
4521 }
4522 
4523 bool C4Game::ActivateMenu(const char *command)
4524 {
4525  // no new menu during round evaluation
4526  if (C4GameOverDlg::IsShown())
4527  {
4528  return false;
4529  }
4530  // forward to primary player
4532  if (!player)
4533  {
4534  return false;
4535  }
4536  player->Menu.ActivateCommand(player->Number, command);
4537  return true;
4538 }
4539 
4541 {
4543  return true;
4544 }
4545 
4546 void C4Game::Abort(bool approval_given)
4547 {
4548  // league needs approval
4549  if (Network.isEnabled() && Parameters.isLeague() && !approval_given)
4550  {
4551  if (Control.isCtrlHost() && !Game.GameOver)
4552  {
4554  return;
4555  }
4557  {
4558  Network.Vote(VT_Kick, true, Control.ClientID());
4559  return;
4560  }
4561  }
4562  if (EvaluateOnAbort)
4563  {
4564  // Scenario forces evaluation. This is intended for scenarios that
4565  // always save progress in the players, such as Tower of Despair.
4566  Evaluate();
4567  }
4568  // hard-abort: eval league and quit
4569  // manually evaluate league
4570  Players.RemoveLocal(true, true);
4571  Players.RemoveAtRemoteClient(true, true);
4572  // normal quit
4574 }
4575 
4576 static const std::unordered_map<std::string, C4GUI::Icons> str_to_icon =
4577 {
4578  { "Locked", C4GUI::Ico_Ex_LockedFrontal },
4579  { "League", C4GUI::Ico_Ex_League },
4580  { "GameRunning", C4GUI::Ico_GameRunning },
4581  { "Lobby", C4GUI::Ico_Lobby },
4582  { "RuntimeJoin", C4GUI::Ico_RuntimeJoin },
4583 
4584  { "A", C4GUI::Ico_Controller_A },
4585  { "B", C4GUI::Ico_Controller_B },
4586  { "X", C4GUI::Ico_Controller_X },
4587  { "Y", C4GUI::Ico_Controller_Y },
4588  { "Back", C4GUI::Ico_Controller_Back },
4589  { "Start", C4GUI::Ico_Controller_Start },
4590  { "Dpad", C4GUI::Ico_Controller_Dpad },
4591  { "DpadLeft", C4GUI::Ico_Controller_DpadLeft },
4592  { "DpadRight", C4GUI::Ico_Controller_DpadRight },
4593  { "DpadDown", C4GUI::Ico_Controller_DpadDown },
4594  { "DpadUp", C4GUI::Ico_Controller_DpadUp },
4595  { "LeftShoulder", C4GUI::Ico_Controller_LeftShoulder },
4596  { "RightShoulder", C4GUI::Ico_Controller_RightShoulder },
4597  { "LeftTrigger", C4GUI::Ico_Controller_LeftTrigger },
4598  { "RightTrigger", C4GUI::Ico_Controller_RightTrigger },
4599  { "LeftStick", C4GUI::Ico_Controller_LeftStick },
4600  { "RightStick", C4GUI::Ico_Controller_RightStick },
4601 };
4602 
4603 bool GetTextSpecFacet(const char* spec, C4Facet& facet)
4604 {
4605  // safety
4606  assert(spec && *spec);
4607  if (!spec)
4608  {
4609  return false;
4610  }
4611  // Special icon?
4612  if (SEqual2(spec, "@Ico:"))
4613  {
4614  spec += 5;
4615  auto it = str_to_icon.find(spec);
4616  if (it != str_to_icon.end())
4617  {
4618  facet = C4GUI::Icon::GetIconFacet(it->second);
4619  return true;
4620  }
4621  }
4622 
4623  return false;
4624 }
4625 
4626 bool C4Game::DrawTextSpecImage(C4Facet &target, const char *spec, C4DrawTransform* transform, uint32_t color)
4627 {
4628  // safety
4629  assert(spec && *spec);
4630  if (!spec)
4631  {
4632  return false;
4633  }
4634 
4635  C4Facet source;
4636  if (GetTextSpecFacet(spec, source))
4637  {
4638  source.DrawXT(target.Surface, target.X, target.Y, target.Wdt, target.Hgt, 0, 0, transform);
4639  return true;
4640  }
4641  else
4642  {
4643  C4Def *def = C4Id2Def(C4ID(spec));
4644  if (!def)
4645  {
4646  return false;
4647  }
4648 
4649  def->Draw(target, false, color, nullptr, 0, 0, transform);
4650  return true;
4651  }
4652 }
4653 
4654 float C4Game::GetTextSpecImageAspect(const char* spec)
4655 {
4656  // safety
4657  assert(spec && *spec);
4658  if (!spec)
4659  {
4660  return -1.0f;
4661  }
4662 
4663  C4Facet source;
4664  if (GetTextSpecFacet(spec, source))
4665  {
4666  return static_cast<float>(source.Wdt) / static_cast<float>(source.Hgt);
4667  }
4668  else
4669  {
4670  C4Def *def = C4Id2Def(C4ID(spec));
4671  if (!def)
4672  {
4673  return -1.0f;
4674  }
4675 
4676  C4DefGraphics* gfx = &def->Graphics;
4677  if (gfx->Type == C4DefGraphics::TYPE_Bitmap)
4678  {
4679  return static_cast<float>(def->PictureRect.Wdt) / static_cast<float>(def->PictureRect.Hgt);
4680  }
4681  else if (gfx->Type == C4DefGraphics::TYPE_Mesh)
4682  {
4683  const StdMesh& mesh = *gfx->Mesh;
4684  const StdMeshBox& box = mesh.GetBoundingBox();
4685  return (box.x2 - box.x1) / (box.y2 - box.y1);
4686  }
4687 
4688  return -1.0f;
4689  }
4690 }
4691 
4693 {
4694  // safety
4695  assert(spec);
4696  if (!spec)
4697  {
4698  return false;
4699  }
4700 
4701  // get source definition
4702  C4PropList *source_def_proplist = spec->GetPropertyPropList(P_Source);
4703  if (!source_def_proplist)
4704  {
4705  return false;
4706  }
4707  C4Def *source_def = source_def_proplist->GetDef();
4708  if (!source_def)
4709  {
4710  return false;
4711  }
4712 
4713  // get custom color
4714  uint32_t color = (uint32_t)spec->GetPropertyInt(P_Color);
4715 
4716  C4String *source_name = spec->GetPropertyStr(P_Name);
4717  if (!source_name)
4718  {
4719  // Base graphics
4720  source_def->Draw(target, false, color);
4721  }
4722  else
4723  {
4724  // Alternative named graphics
4725  C4DefGraphics *source_graphics = source_def->Graphics.Get(source_name->GetCStr());
4726  if (!source_graphics)
4727  {
4728  return false;
4729  }
4730  source_graphics->Draw(target, color, nullptr, 0, 0, nullptr);
4731  }
4732  return true;
4733 }
4734 
4736 {
4737  // As these functions work stepwise, there's the old maximum speed of 50.
4738  // Use /fast to set to even higher speeds.
4739  FrameSkip = Clamp<int32_t>(FrameSkip + 1, 1, 50);
4740  FullSpeed = true;
4741  GraphicsSystem.FlashMessage(FormatString(LoadResStr("IDS_MSG_SPEED"), FrameSkip).getData());
4742  return true;
4743 }
4744 
4746 {
4747  FrameSkip = Clamp<int32_t>(FrameSkip - 1, 1, 50);
4748  if (FrameSkip == 1)
4749  {
4750  FullSpeed = false;
4751  }
4752  GraphicsSystem.FlashMessage(FormatString(LoadResStr("IDS_MSG_SPEED"), FrameSkip).getData());
4753  return true;
4754 }
4755 
4757 {
4758  return C4ChatDlg::ToggleChat();
4759 }
4760 
4761 C4Value C4Game::GRBroadcast(const char *function, C4AulParSet *pars, bool pass_error, bool reject_test)
4762 {
4763  std::string func{ function };
4764  if (func[0] != '~')
4765  {
4766  func.insert(0, 1, '~');
4767  }
4768 
4769  // call objects first - scenario script might overwrite hostility, etc...
4770  C4Value result = ::Objects.GRBroadcast(func.c_str(), pars, pass_error, reject_test);
4771  // rejection tests abort on first nonzero result
4772  if (reject_test && !!result)
4773  {
4774  return result;
4775  }
4776  // scenario script call
4777  return ::GameScript.Call(func.c_str(), pars, pass_error);
4778 }
4779 
4781 {
4782  // Skip this if graphics haven't been initialized yet (happens when
4783  // we bail during initialization)
4784  if (!pDraw) return;
4785  // Default gamma
4786  pDraw->ResetGamma();
4787  pDraw->SetGamma(float(Config.Graphics.Gamma) / 100.0,
4788  float(Config.Graphics.Gamma) / 100.0,
4789  float(Config.Graphics.Gamma) / 100.0,
4791 }
4792 
4794 {
4795  // set in prop list (for savegames) and in sound system::
4796  C4SoundModifier *mod;
4797  if (new_modifier)
4798  {
4799  GlobalSoundModifier.SetPropList(new_modifier);
4800  mod = ::Application.SoundSystem.Modifiers.Get(new_modifier, true);
4801  }
4802  else
4803  {
4805  mod = nullptr;
4806  }
4808 }
4809 
4810 C4String *C4Game::GetTranslatedString(const C4Value &input_string, C4Value *selected_language, bool fail_silently) const
4811 {
4812  // Resolve a localized string
4813  // If a string is passed, just return it
4814  // If a proplist like { DE="Hallo, Welt!", US="Hello, world!" } is passed, return the string matching the selected language
4815  // Nothing?
4816  if (input_string.GetType() == C4V_Nil)
4817  {
4818  return nullptr;
4819  }
4820  // Non-localized string?
4821  if (input_string.GetType() == C4V_String)
4822  {
4823  return input_string._getStr();
4824  }
4825  // Invalid type for this function?
4826  C4PropList *proplist = input_string._getPropList();
4827  if (!proplist || proplist->GetPropertyStr(P_Function) != &::Strings.P[P_Translate])
4828  {
4829  if (fail_silently)
4830  {
4831  return nullptr;
4832  }
4833  else
4834  {
4835  throw C4AulExecError(FormatString("Invalid value for translation: %s", input_string.GetDataString().getData()).getData());
4836  }
4837  }
4838  // This is a proplist. Resolve the language as the key.
4839  char lang_code[3] = "";
4840  for (int32_t lang_index = 0; SCopySegment(Config.General.LanguageEx, lang_index, lang_code, ',', 2); ++lang_index)
4841  {
4842  C4String *lang_string = ::Strings.FindString(lang_code);
4843  if (lang_string) // If the string is not found, it cannot be the key in a prop list
4844  {
4845  C4Value localized_string_val;
4846  if (proplist->GetPropertyByS(lang_string, &localized_string_val))
4847  {
4848  C4String *localized_string = localized_string_val.getStr();
4849  if (localized_string)
4850  {
4851  // Found it!
4852  if (selected_language)
4853  {
4854  selected_language->SetString(lang_string);
4855  }
4856  return localized_string;
4857  }
4858  }
4859  }
4860  }
4861  // No language matched. Just use any property and assume it's a language key.
4862  for (C4String *lang_string : proplist->GetSortedLocalProperties(false))
4863  {
4864  C4Value localized_string_val;
4865  if (proplist->GetPropertyByS(lang_string, &localized_string_val))
4866  {
4867  C4String *localized_string = localized_string_val.getStr();
4868  if (localized_string)
4869  {
4870  // Found it!
4871  if (selected_language)
4872  {
4873  selected_language->SetString(lang_string);
4874  }
4875  return localized_string;
4876  }
4877  }
4878  }
4879  // No string properties. There's no localized information to be found.
4880  return nullptr;
4881 }
4882 
4884 {
4885  C4PropListScript *value_proplist = new C4PropListScript();
4886  value_proplist->SetProperty(P_Function, C4VString(&::Strings.P[P_Translate]));
4887  return value_proplist;
4888 }
void InitCoreFunctionMap(C4AulScriptEngine *pEngine)
Definition: C4Script.cpp:1128
C4AulExec AulExec
Definition: C4AulExec.cpp:29
const int32_t C4ClientIDHost
Definition: C4Client.h:25
#define C4CFN_PXS
Definition: C4Components.h:75
#define C4CFN_Game
Definition: C4Components.h:73
#define C4CFN_ScenarioObjectsScript
Definition: C4Components.h:74
#define C4CFN_TempTitle
Definition: C4Components.h:159
#define C4CFN_Info
Definition: C4Components.h:70
#define C4CFN_Savegames
Definition: C4Components.h:35
#define C4CFN_Script
Definition: C4Components.h:66
#define C4CFN_PlayerControls
Definition: C4Components.h:130
#define C4CFN_Sky
Definition: C4Components.h:65
#define C4CFN_ScenarioTitle
Definition: C4Components.h:84
#define C4CFN_System
Definition: C4Components.h:29
#define C4CFN_ScriptStringTbl
Definition: C4Components.h:68
#define C4CFN_ScriptFiles
Definition: C4Components.h:180
#define C4CFN_MapScript
Definition: C4Components.h:67
#define C4CFN_Material
Definition: C4Components.h:25
#define C4CFN_ScenarioSections
Definition: C4Components.h:38
#define C4CFN_Names
Definition: C4Components.h:145
#define C4CFN_RoundResults
Definition: C4Components.h:129
#define C4CFN_MassMover
Definition: C4Components.h:76
#define C4CFN_Title
Definition: C4Components.h:82
#define C4CFN_TexMap
Definition: C4Components.h:80
#define C4CFN_SavePlayerInfos
Definition: C4Components.h:125
#define C4CFN_MaterialFiles
Definition: C4Components.h:169
C4Config Config
Definition: C4Config.cpp:930
const int32_t FullCon
Definition: C4Constants.h:181
const int C4MaxGammaUserRamps
Definition: C4Constants.h:34
const BYTE COM_MenuLeft
Definition: C4Constants.h:128
const int32_t MNone
Definition: C4Constants.h:177
const BYTE COM_MenuUp
Definition: C4Constants.h:130
const BYTE COM_MenuClose
Definition: C4Constants.h:126
const BYTE COM_MenuRight
Definition: C4Constants.h:129
const BYTE COM_MenuDown
Definition: C4Constants.h:131
const uint32_t OCF_Exclusive
Definition: C4Constants.h:89
@ C4PT_User
Definition: C4Constants.h:154
const int C4UpperBoardHeight
Definition: C4Constants.h:59
const BYTE COM_MenuEnter
Definition: C4Constants.h:124
const uint32_t OCF_CrewMember
Definition: C4Constants.h:97
const int NO_OWNER
Definition: C4Constants.h:137
@ VT_Pause
Definition: C4Control.h:564
@ VT_Cancel
Definition: C4Control.h:562
@ VT_Kick
Definition: C4Control.h:563
const int32_t C4D_Foreground
Definition: C4Def.h:53
const int32_t C4D_Place_Liquid
Definition: C4Def.h:71
const int32_t C4D_Place_Surface
Definition: C4Def.h:70
const int32_t C4D_Place_Air
Definition: C4Def.h:72
const int32_t C4D_MouseIgnore
Definition: C4Def.h:54
const int32_t C4D_Place_Subsurface
Definition: C4Def.h:73
const DWORD C4D_Load_RX
Definition: C4Def.h:91
const int32_t C4D_Place_BothSurface
Definition: C4Def.h:74
C4Def * C4Id2Def(C4ID id)
Definition: C4DefList.h:84
C4Draw * pDraw
Definition: C4Draw.cpp:42
#define C4FxCall_RemoveClear
Definition: C4Effect.h:45
C4FontLoader FontLoader
bool GetTextSpecFacet(const char *spec, C4Facet &facet)
Definition: C4Game.cpp:4603
C4ID DefFileGetID(const char *filename)
Definition: C4Game.cpp:1705
bool LandscapeFree(int32_t x, int32_t y)
Definition: C4Game.cpp:2451
#define EXEC_S(Expressions, Stat)
Definition: C4Game.cpp:862
#define EXEC_S_DR(Expressions, Stat, DebugRecName)
Definition: C4Game.cpp:865
#define EXEC_DR(Expressions, DebugRecName)
Definition: C4Game.cpp:866
int32_t ListExpandValids(C4IDList &rlist, C4ID *idlist, int32_t maxidlist)
Definition: C4Game.cpp:3250
C4GameControl Control
const int32_t C4SyncCheckRate
Definition: C4GameControl.h:53
@ CDT_Decide
Definition: C4GameControl.h:39
C4GameMessageList Messages
const int32_t C4GM_MaxText
Definition: C4GameMessage.h:26
void InitGameFunctionMap(C4AulScriptEngine *pEngine)
#define PSF_Initialize
Definition: C4GameScript.h:34
#define PSF_InitializePlayers
Definition: C4GameScript.h:35
#define PSF_InitializeAmbience
Definition: C4GameScript.h:36
#define PSF_OnGameOver
Definition: C4GameScript.h:138
#define PSF_InitializeObjects
Definition: C4GameScript.h:45
#define PSF_SaveScenarioObjects
Definition: C4GameScript.h:101
#define PSF_Construction
Definition: C4GameScript.h:37
void InitObjectFunctionMap(C4AulScriptEngine *pEngine)
int CompareVersion(int iVer1, int iVer2, int iRVer1=C4XVER1, int iRVer2=C4XVER2)
Definition: C4GameVersion.h:52
C4Game Game
Definition: C4Globals.cpp:52
C4AulScriptEngine ScriptEngine
Definition: C4Globals.cpp:43
C4Console Console
Definition: C4Globals.cpp:45
C4Application Application
Definition: C4Globals.cpp:44
C4GameObjects Objects
Definition: C4Globals.cpp:48
C4DefList Definitions
Definition: C4Globals.cpp:49
C4Network2 Network
Definition: C4Globals.cpp:53
C4StringTable Strings
Definition: C4Globals.cpp:42
C4MouseControl MouseControl
Definition: C4Globals.cpp:47
C4FullScreen FullScreen
Definition: C4Globals.cpp:46
C4GraphicsSystem GraphicsSystem
Definition: C4Globals.cpp:51
C4GraphicsResource GraphicsResource
#define C4GSPrio_Scenario
Definition: C4GroupSet.h:31
#define C4GSCnt_Scenario
Definition: C4GroupSet.h:46
C4GUIScreen * pGUI
Definition: C4Gui.cpp:1191
const unsigned int C4MaxName
C4KeyboardInput & C4KeyboardInput_Init()
const C4KeyCode KEY_Default
C4KeyScope
@ KEYSCOPE_Gui
@ KEYSCOPE_FullSMenu
@ KEYSCOPE_Control
@ KEYSCOPE_FilmView
@ KEYSCOPE_FullSView
@ KEYSCOPE_Generic
@ KEYSCOPE_FreeView
@ KEYSCOPE_Fullscreen
@ KEYSCOPE_Console
C4KeyShiftState
@ KEYS_Shift
@ KEYS_Control
@ KEYS_Alt
C4KeyEventType
unsigned long C4KeyCode
bool FindLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height)
bool FindSurfaceLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height)
bool FindTunnel(int32_t &rx, int32_t &ry, int32_t width, int32_t height)
C4Landscape Landscape
bool FindSolidGround(int32_t &rx, int32_t &ry, int32_t width)
bool AboveSemiSolid(int32_t &rx, int32_t &ry)
bool SemiAboveSolid(int32_t &rx, int32_t &ry)
bool DensitySolid(int32_t dens)
Definition: C4Landscape.h:196
bool GBackSemiSolid(int32_t x, int32_t y)
Definition: C4Landscape.h:234
int32_t GBackMat(int32_t x, int32_t y)
Definition: C4Landscape.h:219
int32_t GBackDensity(int32_t x, int32_t y)
Definition: C4Landscape.h:224
C4Language Languages
Definition: C4Language.cpp:42
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
size_t GetLogPos()
Definition: C4Log.cpp:298
bool Log(const char *szMessage)
Definition: C4Log.cpp:204
bool DebugLog(const char *strMessage)
Definition: C4Log.cpp:282
bool LogSilentF(const char *strMessage,...)
Definition: C4Log.cpp:272
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:262
bool LogFatal(const char *szMessage)
Definition: C4Log.cpp:239
bool DebugLogF(const char *strMessage ...)
Definition: C4Log.cpp:290
C4MapScriptHost MapScript
C4MassMoverSet MassMover
int32_t MEarth
Definition: C4Material.cpp:36
C4MaterialMap MaterialMap
Definition: C4Material.cpp:974
C4MessageInput MessageInput
@ NRT_Definitions
Definition: C4Network2Res.h:46
@ NRT_Material
Definition: C4Network2Res.h:48
#define C4OS_NORMAL
Definition: C4Object.h:35
C4PXSSystem PXS
Definition: C4PXS.cpp:423
@ CID_EMMoveObj
Definition: C4PacketBase.h:169
C4ParticleSystem Particles
C4PlayerList Players
int32_t Hostile(int32_t plr1, int32_t plr2)
void FixedRandom(uint64_t seed)
Definition: C4Random.cpp:37
uint32_t Random()
Definition: C4Random.cpp:43
C4RankSystem DefaultRanks
float fixtof(const C4Fixed &x)
Definition: C4Real.h:257
C4Fixed itofix(int32_t x)
Definition: C4Real.h:261
C4Fixed ftofix(float x)
Definition: C4Real.h:258
const C4Real Fix0
Definition: C4Real.h:312
C4Real C4REAL10(int x)
Definition: C4Real.h:269
void AddDbgRec(C4RecordChunkType eType, const void *pData, int iSize)
Definition: C4Record.cpp:32
@ RCT_Block
Definition: C4Record.h:55
@ RCT_DbgFrame
Definition: C4Record.h:54
@ RCT_CrObj
Definition: C4Record.h:62
char id[32+1]
Definition: C4Record.h:150
C4Reloc Reloc
Definition: C4Reloc.cpp:21
#define C4S_REINIT_SCENARIO
Definition: C4Scenario.h:51
#define C4S_SAVE_OBJECTS
Definition: C4Scenario.h:49
#define C4S_SAVE_LANDSCAPE
Definition: C4Scenario.h:48
const char * C4ScenSect_Main
#define C4S_KEEP_EFFECTS
Definition: C4Scenario.h:50
C4GameScriptHost GameScript
C4SoundInstance * StartSoundEffect(const char *szSndName, bool fLoop, int32_t iVolume, C4Object *pObj, int32_t iCustomFalloffDistance, int32_t iPitch, C4SoundModifier *modifier)
#define C4ST_RESETPART
Definition: C4Stat.h:157
#define C4ST_SHOWPARTSTAT(FrameCounter)
Definition: C4Stat.h:155
#define C4ST_SHOWSTAT
Definition: C4Stat.h:154
#define C4ST_NEW(StatName, strName)
Definition: C4Stat.h:151
@ P_Name
@ P_Color
@ P_GetRandomPoint
@ P_Placement
@ P_Translate
@ P_Source
@ P_x
@ P_IsPointContained
@ P_Function
@ P_y
const int ACenter
Definition: C4Surface.h:41
C4TextureMap TextureMap
Definition: C4Texture.cpp:576
C4Value C4VObj(C4Object *pObj)
Definition: C4Value.cpp:88
const C4Value C4VNull
Definition: C4Value.cpp:30
@ C4V_Nil
Definition: C4Value.h:25
@ C4V_String
Definition: C4Value.h:29
@ C4V_Enum
Definition: C4Value.h:33
C4Value C4VInt(int32_t i)
Definition: C4Value.h:239
C4Value C4VPropList(C4PropList *p)
Definition: C4Value.h:242
C4Value C4VString(C4String *pStr)
Definition: C4Value.h:243
C4ViewportList Viewports
C4Weather Weather
Definition: C4Weather.cpp:206
#define _MAX_FNAME
#define DirectorySeparator
#define _MAX_PATH
#define _MAX_PATH_LEN
#define _MAX_FNAME_LEN
uint8_t BYTE
uint32_t DWORD
#define SHA_DIGEST_LENGTH
Definition: SHA1.h:42
unsigned int SCharCount(char cTarget, const char *szInStr, const char *cpUntil)
Definition: Standard.cpp:326
int SCharPos(char cTarget, const char *szInStr, int iIndex)
Definition: Standard.cpp:239
bool SEqual2(const char *szStr1, const char *szStr2)
Definition: Standard.cpp:204
bool SIsModule(const char *szList, const char *szString, int *ipIndex, bool fCaseSensitive)
Definition: Standard.cpp:547
bool SCopySegment(const char *szString, int iSegment, char *sTarget, char cSeparator, int iMaxL, bool fSkipWhitespace)
Definition: Standard.cpp:279
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:152
void SWordWrap(char *szText, char cSpace, char cSepa, int iMaxLine)
Definition: Standard.cpp:399
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:213
void SCopyUntil(const char *szSource, char *sTarget, char cUntil, int iMaxL, int iIndex)
Definition: Standard.cpp:172
#define sprintf
Definition: Standard.h:162
size_t SLen(const char *sptr)
Definition: Standard.h:74
StdParameterAdapt< T, P > mkParAdapt(T &&rObj, P &&rPar)
Definition: StdAdaptors.h:490
StdStringAdapt mkStringAdaptMA(char(&szString)[size])
Definition: StdAdaptors.h:190
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
Definition: StdAdaptors.h:92
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
bool EraseItem(const char *szItemName)
Definition: StdFile.cpp:833
char * GetExtension(char *szFilename)
Definition: StdFile.cpp:118
bool ItemIdentical(const char *szFilename1, const char *szFilename2)
Definition: StdFile.cpp:879
char * GetFilename(char *szPath)
Definition: StdFile.cpp:42
void AppendBackslash(char *szFilename)
Definition: StdFile.cpp:254
void RemoveExtension(char *szFilename)
Definition: StdFile.cpp:303
bool EraseFile(const char *szFileName)
StdMeshMatManager MeshMaterialManager
bool Active
Definition: C4App.h:63
bool FlushMessages()
Definition: C4AppSDL.cpp:115
C4Group SystemGroup
Definition: C4Application.h:40
C4MusicSystem MusicSystem
Definition: C4Application.h:41
C4SoundSystem SoundSystem
Definition: C4Application.h:42
bool OpenSystemGroup()
Definition: C4Application.h:55
static bool InitDebug(const char *szPassword, const char *szHost)
Definition: C4AulDebug.cpp:43
static C4AulDebug * GetDebugger()
Definition: C4AulDebug.h:31
void ClearPointers(C4Object *)
Definition: C4AulExec.cpp:136
static void Abort()
Definition: C4AulExec.h:257
int32_t CreateUserFile()
Definition: C4Aul.cpp:228
void Denumerate(C4ValueNumbers *) override
Definition: C4Aul.cpp:145
bool ReloadScript(const char *szScript, const char *szLanguage)
Definition: C4AulLink.cpp:224
C4PropListStatic * GetPropList()
Definition: C4Aul.h:151
C4Effect * pGlobalEffects
Definition: C4Aul.h:144
C4AulUserFile * GetUserFile(int32_t handle)
Definition: C4Aul.cpp:252
void RegisterGlobalConstant(const char *szName, const C4Value &rValue)
Definition: C4Aul.cpp:123
void CloseUserFile(int32_t handle)
Definition: C4Aul.cpp:241
void Clear()
Definition: C4Aul.cpp:85
void Link(C4DefList *rDefs)
Definition: C4AulLink.cpp:165
void ReLink(C4DefList *rDefs)
Definition: C4AulLink.cpp:204
size_t GetFileLength()
Definition: C4Aul.h:100
StdStrBuf GrabFileContents()
Definition: C4Aul.h:99
static void Toggle()
static bool ToggleChat()
Definition: C4ChatDlg.cpp:987
const char * getName() const
Definition: C4Client.h:107
C4Client * getLocal() const
Definition: C4Client.h:161
C4Client * getClientByID(int32_t iID) const
Definition: C4Client.cpp:200
bool Init(int32_t iLocalClientID=C4ClientIDHost)
Definition: C4Client.cpp:243
bool Load(C4Group &hGroup, const char *szFilename, const char *szLanguage=nullptr)
const StdStrBuf & GetDataBuf() const
const char * GetData() const
bool GetLanguageString(const char *szLanguage, StdStrBuf &rTarget)
C4PlayerControlAssignmentSets UserSets
Definition: C4Config.h:235
int32_t GamepadGuiControl
Definition: C4Config.h:233
int32_t AutoFileReload
Definition: C4Config.h:84
char Participants[CFG_MaxString+1]
Definition: C4Config.h:39
char LanguageEx[CFG_MaxString+1]
Definition: C4Config.h:38
int32_t AlwaysDebug
Definition: C4Config.h:40
char MissionAccess[CFG_MaxString+1]
Definition: C4Config.h:47
int32_t DebugRec
Definition: C4Config.h:63
bool CreateSaveFolder(const char *directory, const char *language_title)
Definition: C4Config.cpp:636
int32_t Gamma
Definition: C4Config.h:111
int32_t ShowCrewNames
Definition: C4Config.h:108
int32_t ShowCrewCNames
Definition: C4Config.h:109
C4ConfigGeneral General
Definition: C4Config.h:255
const char * AtRelativePath(const char *filename)
Definition: C4Config.cpp:741
const char * AtTempPath(const char *filename)
Definition: C4Config.cpp:600
const char * AtUserDataPath(const char *filename)
Definition: C4Config.cpp:586
bool Save()
Definition: C4Config.cpp:439
const char * GetSubkeyPath(const char *subkey)
Definition: C4Config.cpp:806
C4ConfigControls Controls
Definition: C4Config.h:263
C4ConfigDeveloper Developer
Definition: C4Config.h:256
C4ConfigGraphics Graphics
Definition: C4Config.h:257
C4ConfigSound Sound
Definition: C4Config.h:258
int32_t RXMusic
Definition: C4Config.h:127
bool UpdateHaltCtrls(bool fHalt)
Definition: C4ConsoleGUI.h:152
void Out(const char *message)
Definition: C4Console.cpp:684
void InitGame()
Definition: C4Console.cpp:590
bool Message(const char *szMessage, bool fQuery=false)
Definition: C4Console.cpp:292
void CloseGame()
Definition: C4Console.cpp:609
C4EditCursor EditCursor
Definition: C4Console.h:90
void UpdateMenus()
Definition: C4Console.cpp:504
void ClearPointers(C4Object *pObj)
Definition: C4Console.cpp:405
bool TogglePause()
Definition: C4Console.cpp:617
C4ToolsDlg ToolsDlg
Definition: C4Console.h:88
static C4ControlEMMoveObject * CreateObject(const C4ID &id, C4Real x, C4Real y, C4Object *container)
Definition: C4Control.cpp:1214
std::vector< C4KeyCodeEx > CodeList
C4DefGraphics * Get(const char *szGrpName)
GraphicsType Type
Definition: C4DefGraphics.h:48
void Draw(C4Facet &cgo, DWORD iColor, C4Object *pObj, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *trans)
Definition: C4Def.h:99
char Filename[_MAX_FNAME_LEN]
Definition: C4Def.h:176
int32_t Value
Definition: C4Def.h:115
C4DefGraphics Graphics
Definition: C4Def.h:191
C4ID id
Definition: C4Def.h:101
bool LoadDefCore(C4Group &hGroup)
Definition: C4Def.cpp:141
C4Rect PictureRect
Definition: C4Def.h:107
C4Shape Shape
Definition: C4Def.h:104
void Draw(C4Facet &cgo, bool fSelected=false, DWORD iColor=0, C4Object *pObj=nullptr, int32_t iPhaseX=0, int32_t iPhaseY=0, C4DrawTransform *trans=nullptr, const char *graphicsName=nullptr)
Definition: C4Def.cpp:607
int32_t Count
Definition: C4Def.h:179
int32_t Load(C4Group &hGroup, DWORD dwLoadWhat, const char *szLanguage, C4SoundSystem *pSoundSystem=nullptr, bool fOverload=false, bool fSearchMessage=false, int32_t iMinProgress=0, int32_t iMaxProgress=0, bool fLoadSysGroups=true)
Definition: C4DefList.cpp:71
void Default()
Definition: C4DefList.cpp:413
void Clear()
bool LoadFailure
Definition: C4DefList.h:31
void Synchronize()
Definition: C4DefList.cpp:458
C4Def * GetByPath(const char *szPath)
Definition: C4DefList.cpp:323
void BuildTable()
Definition: C4DefList.cpp:514
int32_t CheckRequireDef()
Definition: C4DefList.cpp:384
int32_t CheckEngineVersion(int32_t ver1, int32_t ver2)
Definition: C4DefList.cpp:365
void Remove(C4Def *def)
Definition: C4DefList.cpp:220
bool Reload(C4Def *pDef, DWORD dwLoadWhat, const char *szLanguage, C4SoundSystem *pSoundSystem=nullptr)
Definition: C4DefList.cpp:420
void AppendAndIncludeSkeletons()
Definition: C4DefList.cpp:521
C4Def * ID2Def(C4ID id)
bool Blit(C4Surface *sfcSource, float fx, float fy, float fwdt, float fhgt, C4Surface *sfcTarget, float tx, float ty, float twdt, float thgt, bool fSrcColKey=false, const C4BltTransform *pTransform=nullptr)
Definition: C4Draw.cpp:301
void GetZoom(ZoomData *r)
Definition: C4Draw.h:197
void SetGamma(float r, float g, float b, int32_t iRampIndex)
Definition: C4Draw.cpp:738
void SetZoom(float X, float Y, float Zoom)
Definition: C4Draw.cpp:773
void ResetGamma()
Definition: C4Draw.cpp:754
bool TextOut(const char *szText, CStdFont &rFont, float fZoom, C4Surface *sfcDest, float iTx, float iTy, DWORD dwFCol=0xffffffff, BYTE byForm=ALeft, bool fDoMarkup=true)
Definition: C4Draw.cpp:561
void ClearPointers(C4PropList *pObj)
Definition: C4Effect.cpp:191
static void Execute(C4Effect **ppEffectList)
Definition: C4Effect.cpp:297
void ClearAll(int32_t iClearFlag)
Definition: C4Effect.cpp:369
bool InitGroup()
Definition: C4Extra.cpp:27
bool Init()
Definition: C4Extra.cpp:41
C4PropListStatic * GetPropList() override
void Set(C4Surface &rSfc)
Definition: C4Facet.cpp:459
C4Surface * Surface
Definition: C4Facet.h:117
float Hgt
Definition: C4Facet.h:118
float Wdt
Definition: C4Facet.h:118
void DrawXT(C4Surface *sfcTarget, float iX, float iY, int32_t iWdt, int32_t iHgt, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform)
Definition: C4Facet.cpp:392
float Y
Definition: C4Facet.h:118
float X
Definition: C4Facet.h:118
Definition: C4Real.h:59
C4MainMenu * MainMenu
Definition: C4FullScreen.h:30
bool MenuKeyControl(BYTE command)
bool ShowAbortDlg()
bool ActivateMenuMain()
bool ViewportCheck()
void SetDelOnClose(bool fToVal=true)
Definition: C4Gui.h:2191
bool IsAborted()
Definition: C4Gui.h:2150
bool Show(Screen *pOnScreen, bool fCB)
void SetBounds(const C4Rect &rcNewBound)
Definition: C4Gui.h:446
static C4Facet GetIconFacet(Icons icoIconIndex)
void Clear()
Definition: C4Gui.cpp:588
void Init(int32_t tx, int32_t ty, int32_t twdt, int32_t thgt)
Definition: C4Gui.cpp:578
bool HasKeyboardFocus()
Definition: C4Gui.h:2671
void ActivateDialog(Dialog *pDlg)
Definition: C4Gui.cpp:647
void SetExclusive(bool fToState)
Definition: C4Gui.h:2669
bool KeyAny()
Definition: C4Gui.cpp:771
bool InitLocal(C4Client *pLocal)
bool isReplay() const
Definition: C4GameControl.h:98
bool NoInput() const
bool StartRecord(bool fInitial, bool fStreaming)
int32_t ControlTick
Definition: C4GameControl.h:89
void OnGameSynchronizing()
int32_t SyncRate
Definition: C4GameControl.h:90
bool InitNetwork(C4Client *pLocal)
bool isRecord() const
bool KeyAdjustControlRate(int32_t iBy)
bool isCtrlHost() const
Definition: C4GameControl.h:99
void DoInput(C4PacketType eCtrlType, C4ControlPacket *pPkt, C4ControlDeliveryType eDelivery)
void StopRecord(StdStrBuf *pRecordName=nullptr, BYTE *pRecordSHA1=nullptr)
int32_t ClientID() const
bool InitReplay(C4Group &rGroup)
Definition: C4Game.h:33
bool FullSpeed
Definition: C4Game.h:137
C4RoundResults & RoundResults
Definition: C4Game.h:73
C4TeamList & Teams
Definition: C4Game.h:70
std::unique_ptr< C4Network2Stats > pNetworkStatistics
Definition: C4Game.h:95
C4Scenario C4S
Definition: C4Game.h:74
void Ticks()
Definition: C4Game.cpp:2017
StdStrBuf RecordStream
Definition: C4Game.h:126
void OnResolutionChanged(unsigned int res_x, unsigned int res_y)
Definition: C4Game.cpp:4228
C4TransferZones TransferZones
Definition: C4Game.h:85
StdStrBuf DebugPassword
Definition: C4Game.h:149
StdStrBuf TempScenarioFile
Definition: C4Game.h:127
bool InitScriptEngine()
Definition: C4Game.cpp:2988
C4Game()
Definition: C4Game.cpp:97
bool SlowDown()
Definition: C4Game.cpp:4745
bool LoadScenarioSection(const char *section_name, DWORD flags)
Definition: C4Game.cpp:4309
int32_t StartTime
Definition: C4Game.h:133
bool InitNetworkFromReference(const C4Network2Reference &Reference)
Definition: C4Game.cpp:3983
C4ComponentHost Title
Definition: C4Game.h:77
int DebugWait
Definition: C4Game.h:149
char PlayerFilenames[20 *_MAX_PATH_LEN]
Definition: C4Game.h:104
bool EvaluateOnAbort
Definition: C4Game.h:115
void DrawCrewOverheadText(C4TargetFacet &cgo, int32_t player_nr)
Definition: C4Game.cpp:1897
bool Record
Definition: C4Game.h:124
C4ComponentHost Info
Definition: C4Game.h:76
C4KeyboardInput & KeyboardInput
Definition: C4Game.h:96
C4String * GetTranslatedString(const class C4Value &input_string, C4Value *selected_language, bool fail_silently) const
Definition: C4Game.cpp:4810
bool SpeedUp()
Definition: C4Game.cpp:4735
StdStrBuf DebugHost
Definition: C4Game.h:149
bool InitNetworkFromAddress(const char *address)
Definition: C4Game.cpp:3889
bool ToggleChat()
Definition: C4Game.cpp:4756
~C4Game()
Definition: C4Game.cpp:114
char DirectJoinAddress[_MAX_PATH_LEN]
Definition: C4Game.h:106
int32_t cFPS
Definition: C4Game.h:111
bool QuickSave(const char *filename, const char *title, bool force_save=false)
Definition: C4Game.cpp:2386
void CompileFunc(StdCompiler *compiler, CompileSettings settings, C4ValueNumbers *)
Definition: C4Game.cpp:2055
std::unique_ptr< C4FileMonitor > pFileMonitor
Definition: C4Game.h:97
void InitInEarth()
Definition: C4Game.cpp:3481
C4Object * PlaceVegetation(C4PropList *def, int32_t x, int32_t y, int32_t wdt, int32_t hgt, int32_t growth, C4PropList *shape_proplist, C4PropList *out_pos_proplist)
Definition: C4Game.cpp:3323
C4PathFinder PathFinder
Definition: C4Game.h:84
C4Player * JoinPlayer(const char *filename, int32_t at_client, const char *at_client_name, C4PlayerInfo *info)
Definition: C4Game.cpp:3758
C4ComponentHost GameText
Definition: C4Game.h:79
void UpdateLanguage()
Definition: C4Game.cpp:3719
bool IsRunning
Definition: C4Game.h:140
void FixRandom(uint64_t seed)
Definition: C4Game.cpp:3801
void Evaluate()
Definition: C4Game.cpp:1864
int32_t iTick3
Definition: C4Game.h:130
int32_t iTick255
Definition: C4Game.h:130
void SetScenarioFilename(const char *)
Definition: C4Game.cpp:660
void Clear()
Definition: C4Game.cpp:672
bool DrawPropListSpecImage(C4Facet &target, C4PropList *spec)
Definition: C4Game.cpp:4692
bool ReloadDef(C4ID id)
Definition: C4Game.cpp:2488
bool CompileRuntimeData(C4Group &group, InitMode init_mode, bool exact, bool sync, C4ValueNumbers *)
Definition: C4Game.cpp:2153
bool ToggleChart()
Definition: C4Game.cpp:4540
std::unique_ptr< C4ScriptGuiWindow > ScriptGuiRoot
Definition: C4Game.h:234
C4Object * NewObject(C4PropList *def, C4Object *creator, int32_t owner, C4ObjectInfo *info, int32_t x, int32_t y, int32_t r, C4Real xdir, C4Real ydir, C4Real rdir, int32_t con, int32_t controller, bool grow_from_center)
Definition: C4Game.cpp:1246
int32_t InitProgress
Definition: C4Game.h:134
bool InitPlayers(C4ValueNumbers *)
Definition: C4Game.cpp:3073
C4ComponentHost Names
Definition: C4Game.h:78
bool TogglePause()
Definition: C4Game.cpp:1153
C4Object * FindObject(C4Def *def, int32_t x=0, int32_t y=0, int32_t wdt=0, int32_t hgt=0, DWORD ocf=OCF_All, C4Object *find_next=nullptr)
Definition: C4Game.cpp:1456
void SetInitProgress(float to_progress)
Definition: C4Game.cpp:4207
void ShowGameOverDlg()
Definition: C4Game.cpp:3831
void ClearPointers(C4Object *obj)
Definition: C4Game.cpp:1125
C4Value & GlobalSoundModifier
Definition: C4Game.h:99
void Abort(bool fApproved=false)
Definition: C4Game.cpp:4546
bool InitControl()
Definition: C4Game.cpp:3183
C4Object * FindVisObject(float x, float y, int32_t player_nr, const C4Facet &viewport_game, const C4Facet &viewport_gui, float game_x, float game_y, DWORD category, float gui_x, float gui_y)
Definition: C4Game.cpp:1536
void InitGoals()
Definition: C4Game.cpp:4193
class C4ScenarioParameterDefs & ScenarioParameterDefs
Definition: C4Game.h:75
float GetTextSpecImageAspect(const char *spec)
Definition: C4Game.cpp:4654
C4PlayerControlAssignmentSets PlayerControlDefaultAssignmentSets
Definition: C4Game.h:93
bool InitNetworkFromReferenceFile(const char *temp_filename)
Definition: C4Game.cpp:3962
void SyncClearance()
Definition: C4Game.cpp:3854
int32_t iTick2
Definition: C4Game.h:130
C4Object * PlaceAnimal(C4PropList *def)
Definition: C4Game.cpp:3446
bool fResortAnyObject
Definition: C4Game.h:139
C4Scoreboard Scoreboard
Definition: C4Game.h:94
C4Object * CreateInfoObject(C4ObjectInfo *info, int32_t owner, int32_t x=50, int32_t y=50)
Definition: C4Game.cpp:1351
bool PointersDenumerated
Definition: C4Game.h:141
int32_t LastInitProgress
Definition: C4Game.h:134
C4PropList * AllocateTranslatedString()
Definition: C4Game.cpp:4883
bool CreateSectionFromTempFile(const char *section_name, const char *temp_filename)
Definition: C4Game.cpp:4249
void InitFullscreenComponents(bool is_running)
Definition: C4Game.cpp:962
void InitEnvironment()
Definition: C4Game.cpp:4165
bool DoKeyboardInput(C4KeyCode vk_code, C4KeyEventType event_type, bool alt, bool ctrl, bool shift, bool repeated, class C4GUI::Dialog *for_dialog=nullptr, bool fPlrCtrlOnly=false, int32_t strength=-1)
Definition: C4Game.cpp:2288
StdCopyStrBuf NextMissionText
Definition: C4Game.h:147
void ClearObjectPtrs(C4Object *to_obj)
Definition: C4Game.cpp:1109
bool InitialPlayersJoined
Definition: C4Game.h:113
bool LinkScriptEngine()
Definition: C4Game.cpp:3035
bool Pause()
Definition: C4Game.cpp:1171
void OnPlayerJoinFinished()
Definition: C4Game.cpp:3791
class C4ScenarioObjectsScriptHost * pScenarioObjectsScript
Definition: C4Game.h:90
C4PlayerControlAssignmentSets PlayerControlUserAssignmentSets
Definition: C4Game.h:93
InitMode
Definition: C4Game.h:37
@ IM_Normal
Definition: C4Game.h:38
@ IM_Section
Definition: C4Game.h:39
@ IM_ReInit
Definition: C4Game.h:40
bool DoSkipFrame
Definition: C4Game.h:138
C4Object * FindConstuctionSiteBlock(int32_t x, int32_t y, int32_t wdt, int32_t hgt)
Definition: C4Game.cpp:1423
bool IsPaused()
Definition: C4Game.cpp:1235
bool ReloadFile(const char *filepath)
Definition: C4Game.cpp:2465
char ScenarioFilename[_MAX_PATH_LEN]
Definition: C4Game.h:102
bool fPreinited
Definition: C4Game.h:128
bool OpenScenario()
Definition: C4Game.cpp:177
void InitRules()
Definition: C4Game.cpp:4179
int32_t iLobbyTimeout
Definition: C4Game.h:120
int32_t RandomSeed
Definition: C4Game.h:135
StdCopyStrBuf NextMissionDesc
Definition: C4Game.h:147
size_t StartupLogPos
Definition: C4Game.h:142
bool Init()
Definition: C4Game.cpp:397
bool Evaluated
Definition: C4Game.h:116
C4ClientList & Clients
Definition: C4Game.h:69
bool DrawTextSpecImage(C4Facet &target, const char *spec, class C4DrawTransform *transform, uint32_t color=0xff)
Definition: C4Game.cpp:4626
C4PlayerInfoList & PlayerInfos
Definition: C4Game.h:71
C4ScenarioSection * pCurrentScenarioSection
Definition: C4Game.h:91
bool InitMaterialTexture()
Definition: C4Game.cpp:987
bool PlaceInEarth(C4ID id)
Definition: C4Game.cpp:3271
bool InitKeyboard()
Definition: C4Game.cpp:3625
static constexpr const char * DirectJoinFilePrefix
Definition: C4Game.h:296
size_t QuitLogPos
Definition: C4Game.h:142
C4Extra Extra
Definition: C4Game.h:89
int32_t iTick35
Definition: C4Game.h:130
bool DropFile(const char *filename, float x, float y)
Definition: C4Game.cpp:1722
class C4ScenarioParameters & StartupScenarioParameters
Definition: C4Game.h:68
C4PlayerInfoList & RestorePlayerInfos
Definition: C4Game.h:72
void OnKeyboardLayoutChanged()
Definition: C4Game.cpp:4242
int32_t ObjectCount(C4ID id)
Definition: C4Game.cpp:1609
int32_t FrameSkip
Definition: C4Game.h:138
int32_t StartupPlayerCount
Definition: C4Game.h:109
int32_t FrameCounter
Definition: C4Game.h:129
void ExecObjects()
Definition: C4Game.cpp:1648
C4GameParameters & Parameters
Definition: C4Game.h:67
bool LoadAdditionalSystemGroup(class C4Group &parent_group)
Definition: C4Game.cpp:3577
int32_t iTick10
Definition: C4Game.h:130
bool InitDefs()
Definition: C4Game.cpp:120
std::unique_ptr< C4Network2Reference > pJoinReference
Definition: C4Game.h:108
bool NetworkActive
Definition: C4Game.h:123
bool GameOver
Definition: C4Game.h:114
StdStrBuf PlayerNames
Definition: C4Game.h:81
int32_t Time
Definition: C4Game.h:132
bool Unpause()
Definition: C4Game.cpp:1203
C4LangStringTable ScenarioLangStringTable
Definition: C4Game.h:80
bool GameOverDlgShown
Definition: C4Game.h:117
C4LangStringTable MainSysLangStringTable
Definition: C4Game.h:80
bool PreInit()
Definition: C4Game.cpp:333
int32_t StartupTeamCount
Definition: C4Game.h:110
void ObjectRemovalCheck()
Definition: C4Game.cpp:1636
bool CheckObjectEnumeration()
Definition: C4Game.cpp:4080
bool GameOverCheck()
Definition: C4Game.cpp:819
C4Group * pParentGroup
Definition: C4Game.h:88
bool CanQuickSave()
Definition: C4Game.cpp:2374
bool SaveData(C4Group &group, bool save_section, bool save_exact, bool save_sync, C4ValueNumbers *)
Definition: C4Game.cpp:2180
C4ScenarioSection * pScenarioSections
Definition: C4Game.h:91
bool LoadScenarioComponents()
Definition: C4Game.cpp:3539
void InitAnimals()
Definition: C4Game.cpp:3516
char CurrentScenarioSection[C4MaxName+1]
Definition: C4Game.h:101
StdCopyStrBuf ScenarioTitle
Definition: C4Game.h:103
void SetDefaultGamma()
Definition: C4Game.cpp:4780
bool GameGo
Definition: C4Game.h:136
void Synchronize(bool save_player_files)
Definition: C4Game.cpp:3859
bool ToggleDebugMode()
Definition: C4Game.cpp:4506
bool InitPlayerControlUserSettings()
Definition: C4Game.cpp:3748
bool Execute()
Definition: C4Game.cpp:868
bool InitGameFinal(InitMode init_mode)
Definition: C4Game.cpp:2917
int32_t FPS
Definition: C4Game.h:111
bool fScriptCreatedObjects
Definition: C4Game.h:118
C4Object * CreateObjectConstruction(C4PropList *type, C4Object *creator, int32_t owner, int32_t center_x=0, int32_t bottom_y=0, int32_t con=1, bool adjust_terrain=false)
Definition: C4Game.cpp:1373
void SetGlobalSoundModifier(C4PropList *modifier_props)
Definition: C4Game.cpp:4793
bool DebugMode
Definition: C4Game.h:145
bool DoGameOver()
Definition: C4Game.cpp:3806
C4PlayerControlDefs PlayerControlDefs
Definition: C4Game.h:92
bool DropDef(C4ID id, float x, float y)
Definition: C4Game.cpp:1746
bool fQuitWithError
Definition: C4Game.h:143
bool fObserve
Definition: C4Game.h:121
void Default()
Definition: C4Game.cpp:1804
void DeleteObjects(bool delete_inactive)
Definition: C4Game.cpp:1307
void InitVegetation()
Definition: C4Game.cpp:3497
bool InitNetworkHost()
Definition: C4Game.cpp:4017
bool fReferenceDefinitionOverride
Definition: C4Game.h:122
C4Value GRBroadcast(const char *function, C4AulParSet *pars=nullptr, bool pass_error=false, bool reject_test=false)
Definition: C4Game.cpp:4761
bool InitPlayerControlSettings()
Definition: C4Game.cpp:3725
int32_t HaltCount
Definition: C4Game.h:112
C4Object * CreateObject(C4PropList *type, C4Object *creator, int32_t owner=NO_OWNER, int32_t x=50, int32_t y=50, int32_t r=0, bool grow_from_center=false, C4Real xdir=Fix0, C4Real ydir=Fix0, C4Real rdir=Fix0, int32_t controller=NO_OWNER)
Definition: C4Game.cpp:1334
bool SaveGameTitle(C4Group &hGroup)
Definition: C4Game.cpp:2237
StdStrBuf RecordDumpFile
Definition: C4Game.h:125
void InitValueOverloads()
Definition: C4Game.cpp:4151
bool InitGame(C4Group &group, InitMode init_mode, bool load_sky, C4ValueNumbers *)
Definition: C4Game.cpp:2599
bool TimeGo
Definition: C4Game.h:131
C4GroupSet GroupSet
Definition: C4Game.h:87
C4Group ScenarioFile
Definition: C4Game.h:86
int32_t iTick1000
Definition: C4Game.h:130
char DefinitionFilenames[20 *_MAX_PATH_LEN]
Definition: C4Game.h:105
bool fLobby
Definition: C4Game.h:119
void CastObjects(C4ID id, C4Object *creator, int32_t num, int32_t level, int32_t x, int32_t y, int32_t owner=NO_OWNER, int32_t controller=NO_OWNER, C4ValueArray *out_objects=nullptr)
Definition: C4Game.cpp:1763
int32_t iTick5
Definition: C4Game.h:130
uint16_t DebugPort
Definition: C4Game.h:149
bool ReloadParticle(const char *name)
Definition: C4Game.cpp:2565
bool ActivateMenu(const char *command)
Definition: C4Game.cpp:4523
void CloseScenario()
Definition: C4Game.cpp:310
StdCopyStrBuf NextMission
Definition: C4Game.h:147
bool ReLinkScriptEngine()
Definition: C4Game.cpp:3060
void ClearPointers(C4Object *pObj)
void UpdateDef(C4ID idUpdDef)
void Clear(bool fClearInactive)
void Init(int32_t width, int32_t height)
bool Remove(C4Object *game_object) override
void Default() override
void AssignLightRange()
C4Value GRBroadcast(const char *function_name, C4AulParSet *parameters, bool pass_error, bool reject_test)
bool Add(C4Object *game_object)
void UpdateScriptPointers()
C4ObjectList ForeObjects
Definition: C4GameObjects.h:44
C4LSectors Sectors
Definition: C4GameObjects.h:42
void DeleteObjects(bool delete_inactive_objects)
bool ValidateOwners() override
C4ObjectList InactiveObjects
Definition: C4GameObjects.h:43
bool AssignInfo() override
int PostLoad(bool keep_inactive_objects, C4ValueNumbers *)
static bool IsShown()
Definition: C4GameOverDlg.h:91
bool isLeague() const
C4GameResList GameRes
C4ClientList Clients
bool doStreaming() const
C4ScenarioParameters ScenarioParameters
bool Load(C4Group &hGroup, C4Scenario *pDefault, const char *szGameText, C4LangStringTable *pLang, const char *DefinitionFilenames, C4ScenarioParameters *pStartupScenarioParameters)
const char * getFile() const
C4GameRes * iterRes(C4GameRes *pLast, C4Network2ResType eType=NRT_Null)
bool Save(const char *szFilename)
Definition: C4GameSave.cpp:398
C4Effect * pScenarioEffects
Definition: C4ScriptHost.h:166
bool Load(C4Group &, const char *, const char *, C4LangStringTable *) override
C4Value Call(const char *szFunction, C4AulParSet *pPars=nullptr, bool fPassError=false)
~C4GameSec1Timer() override
Definition: C4Game.cpp:87
void OnSec1Timer() override
Definition: C4Game.cpp:1792
C4UpperBoard UpperBoard
bool InitLoaderScreen(const char *image_name)
std::unique_ptr< C4MessageBoard > MessageBoard
bool SaveScreenshotKey(bool save_all)
void FlashMessage(const char *message)
C4LoaderScreen * pLoaderScreen
void FlashMessageOnOff(const char *description, bool switch_on)
bool FindNextEntry(const char *wildcard, StdStrBuf *filename=nullptr, size_t *size=nullptr, bool start_at_filename=false)
Definition: C4Group.cpp:2217
bool IsPacked() const
Definition: C4Group.cpp:2541
int EntryCount(const char *wildcard=nullptr)
Definition: C4Group.cpp:2314
StdStrBuf GetFullName() const
Definition: C4Group.cpp:2638
int PreCacheEntries(const char *search_pattern, bool cache_previous=false)
Definition: C4Group.cpp:2831
bool Add(const char *filename, const char *entry_name)
Definition: C4Group.cpp:1621
bool LoadEntry(const char *entry_name, char **buffer, size_t *size_info=nullptr, int zeros_to_append=0)
Definition: C4Group.cpp:2375
bool OpenAsChild(C4Group *mother, const char *entry_name, bool is_exclusive=false, bool do_create=false)
Definition: C4Group.cpp:1952
bool IsOpen() const
Definition: C4Group.cpp:2373
void ResetSearch(bool reload_contents=false)
Definition: C4Group.cpp:1316
bool Close()
Definition: C4Group.cpp:971
bool Move(const char *filename, const char *entry_name)
Definition: C4Group.cpp:1633
bool Delete(const char *files, bool recursive=false)
Definition: C4Group.cpp:1645
bool FindEntry(const char *wildcard, StdStrBuf *filename=nullptr, size_t *size=nullptr)
Definition: C4Group.cpp:2211
bool Open(const char *group_name, bool do_create=false)
Definition: C4Group.cpp:660
void Clear()
Definition: C4GroupSet.cpp:50
bool RegisterGroup(C4Group &rGroup, bool fOwnGrp, int32_t Priority, int32_t Contents, bool fCheckContent=true)
Definition: C4GroupSet.cpp:88
C4Group * RegisterParentFolders(const char *szScenFilename)
Definition: C4GroupSet.cpp:294
bool CloseFolders()
Definition: C4GroupSet.cpp:235
void Default()
Definition: C4GroupSet.cpp:57
bool isSuccess() const
Definition: C4HTTP.h:88
bool Execute(int iMaxTime=-1, pollfd *readyfds=nullptr) override
Definition: C4HTTP.cpp:59
bool Init()
Definition: C4HTTP.cpp:42
virtual const char * GetError() const
Definition: C4HTTP.h:96
bool SetServer(const char *szServerAddress)
Definition: C4HTTP.cpp:298
bool isBusy() const
Definition: C4HTTP.h:86
Definition: C4Id.h:26
const char * ToString() const
Definition: C4Id.h:56
static const C4ID None
Definition: C4Id.h:39
C4ID GetID(size_t index, int32_t *ipCount=nullptr) const
Definition: C4IDList.cpp:103
int32_t GetIDCount(C4ID c_id, int32_t iZeroDefVal=0) const
Definition: stub-handle.cpp:67
bool DoInput(const C4KeyCodeEx &InKey, C4KeyEventType InEvent, DWORD InScope, int32_t iStrength)
void RegisterKey(C4CustomKey *pRegKey)
C4ObjectList * NextObjectShapes(C4ObjectList *pPrev, C4LSector **ppSct)
Definition: C4Sector.cpp:317
C4ObjectList * FirstObjectShapes(C4LSector **ppSct)
Definition: C4Sector.h:122
void RaiseTerrain(int32_t tx, int32_t ty, int32_t wdt)
int32_t GetWidth() const
int32_t DigFreeRect(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, C4Object *by_object=nullptr, bool no_dig2objects=false, bool no_instability_check=false)
BYTE GetBackPix(int32_t x, int32_t y) const
class C4Sky & GetSky()
void Clear(bool fClearMapCreator=true, bool fClearSky=true, bool fClearRenderer=true)
void Synchronize()
void ScenarioInit()
bool PostInitMap()
int32_t GetHeight() const
bool Save(C4Group &hGroup) const
bool Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bool &rfLoaded, bool fSavegame)
void ClearPointers(C4Object *pObj)
bool DoRelights()
void Execute()
static bool LoadComponentHost(C4ComponentHost *host, C4Group &hGroup, const char *szFilename, const char *szLanguage)
Definition: C4Language.cpp:232
bool HasStringTable() const
Definition: C4Language.h:70
bool Load(C4Group &, const char *, const char *, C4LangStringTable *) override
void InitFunctionMap(C4AulScriptEngine *pEngine)
void Copy(C4MassMoverSet &rSet)
bool Load(C4Group &hGroup)
bool Save(C4Group &hGroup)
int32_t Soil
Definition: C4Material.h:111
C4Material * Map
Definition: C4Material.h:169
void UpdateScriptPointers()
Definition: C4Material.cpp:968
bool LoadEnumeration(C4Group &hGroup)
Definition: C4Material.cpp:587
int32_t Load(C4Group &hGroup)
Definition: C4Material.cpp:319
bool CrossMapMaterials(const char *szEarthMaterial)
Definition: C4Material.cpp:375
bool IsActive()
Definition: C4Menu.cpp:480
void ClearPointers(C4Object *pObj)
bool KeyStartTypeIn(bool fTeam)
void ClearPointers(C4Object *pObj)
void FadeOut(int fadeout_ms)
bool Play(const char *szSongname=nullptr, bool fLoop=false, int fadetime_ms=0, double max_resume_time=0.0, bool allow_break=false)
bool InitForScenario(C4Group &hGroup)
C4Network2Players Players
Definition: C4Network2.h:119
bool Pause()
Definition: C4Network2.cpp:514
bool ToggleClientListDlg()
Definition: C4Network2.cpp:766
void OnGameSynchronized()
void Clear()
Definition: C4Network2.cpp:712
InitResult InitClient(const class C4Network2Reference &Ref, bool fObserver)
bool isRunning() const
Definition: C4Network2.h:206
void LeagueGameEvaluate(const char *szRecordName=nullptr, const BYTE *pRecordSHA=nullptr)
void AllowJoin(bool fAllow)
Definition: C4Network2.cpp:802
bool isEnabled() const
Definition: C4Network2.h:203
bool ToggleAllowJoin()
Definition: C4Network2.cpp:759
bool isHost() const
Definition: C4Network2.h:209
void Vote(C4ControlVoteType eType, bool fApprove=true, int32_t iData=0)
bool DoLobby()
Definition: C4Network2.cpp:433
bool InitHost(bool fLobby)
Definition: C4Network2.cpp:139
bool isLobbyActive() const
Definition: C4Network2.h:204
bool FinalInit()
Definition: C4Network2.cpp:538
bool Start()
Definition: C4Network2.cpp:506
void Execute()
Definition: C4Network2.cpp:649
bool RetrieveScenario(char *szScenario)
Definition: C4Network2.cpp:590
bool GetReferences(C4Network2Reference **&rpReferences, int32_t &rRefCount)
C4GameParameters Parameters
const char * getTitle() const
C4ObjectInfo * Info
Definition: C4Object.h:143
bool Init(C4PropList *ndef, C4Object *pCreator, int32_t owner, C4ObjectInfo *info, int32_t nx, int32_t ny, int32_t nr, C4Real nxdir, C4Real nydir, C4Real nrdir, int32_t iController)
Definition: C4Object.cpp:112
int32_t GetX() const
Definition: C4Object.h:285
void ClearPointers(C4Object *ptr)
Definition: C4Object.cpp:816
bool IsVisible(int32_t iForPlr, bool fAsOverlay) const
int32_t Controller
Definition: C4Object.h:109
uint32_t OCF
Definition: C4Object.h:132
C4ID id
Definition: C4Object.h:106
int32_t GetY() const
Definition: C4Object.h:286
void DoCon(int32_t iChange, bool grow_from_center)
Definition: C4Object.cpp:631
C4ObjectPtr Contained
Definition: C4Object.h:142
C4Def * Def
Definition: C4Object.h:141
StdStrBuf sRankName
Definition: C4InfoCore.h:40
const ReverseView reverse() const
Definition: C4ObjectList.h:104
int ObjectCount(C4ID id=C4ID::None) const
int ClearPointers(C4Object *obj)
bool Save(C4Group &hGroup)
Definition: C4PXS.cpp:325
bool Load(C4Group &hGroup)
Definition: C4PXS.cpp:358
void Execute()
Definition: C4PXS.cpp:186
void Default()
Definition: C4PXS.cpp:158
void Clear()
Definition: C4PXS.cpp:163
StdStrBuf Name
Definition: C4Particles.h:73
StdStrBuf Filename
Definition: C4Particles.h:88
C4ParticleDef * GetDef(const char *name, C4ParticleDef *exclude=nullptr)
void CalculateNextStep()
Definition: C4Particles.h:481
C4ParticleSystemDefinitionList definitions
Definition: C4Particles.h:510
void Init(PointFreeFn fnPointFree, C4TransferZones *pTransferZones=nullptr)
static bool StreamToRecord(const char *szStream, StdStrBuf *pRecord)
Definition: C4Record.cpp:1107
bool ResolveRefs(C4PlayerControlDefs *pControlDefs)
void MergeFrom(const C4PlayerControlAssignmentSets &Src, C4PlayerControlAssignmentSet::MergeMode merge_mode)
void MergeFrom(const C4PlayerControlDefs &Src)
bool Load(C4Group &hGroup, const char *szFilename, C4LangStringTable *pLang)
const C4PlayerControlDefs & GetControlDefs() const
const C4PlayerControlAssignmentSets & GetAssignmentSets() const
C4Player * Next
Definition: C4Player.h:142
int32_t AtClient
Definition: C4Player.h:97
int32_t GetJoinIssuedPlayerCount() const
bool RecreatePlayers(C4ValueNumbers *)
bool Load(C4Group &hGroup, const char *szFromFile, class C4LangStringTable *pLang=nullptr)
int32_t GetJoinPendingPlayerCount() const
int32_t GetActiveScriptPlayerCount(bool fCountSavegameResumes, bool fCountInvisible) const
void RecheckAutoGeneratedTeams()
int32_t GetStartupCount()
bool LocalJoinUnjoinedPlayersInQueue()
int32_t GetActivePlayerCount(bool fCountInvisible) const
bool RestoreSavegameInfos(C4PlayerInfoList &rSavegamePlayers)
void ClearPointers(C4Object *pObj)
bool Remove(int iPlayer, bool fDisonnected, bool fNoCalls)
C4Player * Join(const char *szFilename, bool fScenarioInit, int iAtClient, const char *szAtClientName, class C4PlayerInfo *pInfo, C4ValueNumbers *)
C4Player * GetByIndex(int iIndex) const
C4Player * Get(int iPlayer) const
C4Player * First
Definition: C4PlayerList.h:31
int GetCountNotEliminated() const
bool HasPlayerInTeamSelection()
bool RemoveLocal(bool fDisonnected, bool fNoCalls)
bool SynchronizeLocalFiles()
bool Save(bool fSaveLocalOnly)
C4Player * GetLocalByIndex(int iIndex) const
bool RemoveAtRemoteClient(bool fDisonnected, bool fNoCalls)
int GetCount() const
int32_t GetPropertyInt(C4PropertyName k, int32_t default_val=0) const
Definition: C4PropList.cpp:855
virtual const char * GetName() const
Definition: C4PropList.cpp:618
int32_t Status
Definition: C4PropList.h:173
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
Definition: C4PropList.cpp:726
std::vector< C4String * > GetSortedLocalProperties(bool add_prototype=true) const
Definition: C4PropList.cpp:545
C4PropList * GetPropertyPropList(C4PropertyName k) const
Definition: C4PropList.cpp:869
C4String * GetPropertyStr(C4PropertyName k) const
Definition: C4PropList.cpp:744
virtual C4Def const * GetDef() const
Definition: C4PropList.cpp:654
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4PropList.h:114
void SetProperty(C4PropertyName k, const C4Value &to)
Definition: C4PropList.h:124
static void ClearShelve()
Definition: C4PropList.cpp:107
static int32_t GetEnumerationIndex()
Definition: C4PropList.h:230
static void ShelveNumberedPropLists()
Definition: C4PropList.cpp:81
static void UnshelveNumberedPropLists()
Definition: C4PropList.cpp:99
static void ClearNumberedPropLists()
Definition: C4PropList.cpp:113
static void SetEnumerationIndex(int32_t iMaxObjectNumber)
Definition: C4PropList.cpp:69
static void ResetEnumerationIndex()
Definition: C4PropList.cpp:75
static int32_t EnumerationIndex
Definition: C4PropList.h:243
static void ClearScriptPropLists()
Definition: C4PropList.cpp:183
int Init(const char *szRegister, const char *szDefRanks, int iRankBase)
Definition: C4Rect.h:28
bool Overlap(C4Rect &rTarget)
Definition: C4Rect.cpp:91
int32_t y
Definition: C4Rect.h:30
int32_t Hgt
Definition: C4Rect.h:30
int32_t Wdt
Definition: C4Rect.h:30
int32_t x
Definition: C4Rect.h:30
bool Open(C4Group &group, const char *filename) const
Definition: C4Reloc.cpp:156
bool Load(C4Group &hGroup, const char *szFilename=C4CFN_RoundResults)
C4IDList EarthNest
Definition: C4Scenario.h:212
C4IDList FreeLife
Definition: C4Scenario.h:211
bool AllowUserChange
Definition: C4Scenario.h:93
bool GetModules(StdStrBuf *psOutModules) const
Definition: C4Scenario.cpp:422
C4IDList Objects
Definition: C4Scenario.h:221
C4SRealism Realism
Definition: C4Scenario.h:127
bool EvaluateOnAbort
Definition: C4Scenario.h:129
bool Replay
Definition: C4Scenario.h:72
bool NetworkGame
Definition: C4Scenario.h:78
bool NoInitialize
Definition: C4Scenario.h:69
int32_t Film
Definition: C4Scenario.h:73
int32_t RandomSeed
Definition: C4Scenario.h:74
std::string MissionAccess
Definition: C4Scenario.h:76
std::string Loader
Definition: C4Scenario.h:65
int32_t C4XVer[2]
Definition: C4Scenario.h:63
StdCopyStrBuf Origin
Definition: C4Scenario.h:80
bool NetworkRuntimeJoin
Definition: C4Scenario.h:79
bool SaveGame
Definition: C4Scenario.h:71
std::string Title
Definition: C4Scenario.h:64
C4IDList Vegetation
Definition: C4Scenario.h:167
C4SVal VegLevel
Definition: C4Scenario.h:166
std::string Material
Definition: C4Scenario.h:183
C4SVal InEarthLevel
Definition: C4Scenario.h:168
C4IDList InEarth
Definition: C4Scenario.h:169
std::string SkyDef
Definition: C4Scenario.h:173
C4IDList ValueOverloads
Definition: C4Scenario.h:109
int32_t Evaluate()
Definition: C4Scenario.cpp:50
C4SGame Game
Definition: C4Scenario.h:234
C4SEnvironment Environment
Definition: C4Scenario.h:239
void SetExactLandscape()
Definition: C4Scenario.cpp:415
bool Save(C4Group &hGroup, bool fSaveSection=false)
Definition: C4Scenario.cpp:114
C4SLandscape Landscape
Definition: C4Scenario.h:236
C4SAnimals Animals
Definition: C4Scenario.h:237
C4SHead Head
Definition: C4Scenario.h:232
void Default()
Definition: C4Scenario.cpp:78
C4SDefinitions Definitions
Definition: C4Scenario.h:233
void Clear()
Definition: C4Scenario.cpp:410
bool Load(C4Group &hGroup, bool fLoadSection=false, bool suppress_errors=false)
Definition: C4Scenario.cpp:92
void RegisterScriptConstants(const class C4ScenarioParameters &values)
bool Load(C4Group &hGroup, class C4LangStringTable *pLang)
bool ScenarioLoad(const char *szFilename, bool is_temp_file)
bool EnsureTempStore(bool fExtractLandscape, bool fExtractObjects)
StdCopyStrBuf name
Definition: C4Scenario.h:260
class C4ScenarioObjectsScriptHost * pObjectScripts
Definition: C4Scenario.h:264
C4ScenarioSection * pNext
Definition: C4Scenario.h:266
C4Group * GetGroupfile(C4Group &rGrp)
void DoDlgShow(int32_t iChange, bool fUserToggle)
bool KeyUserShow()
Definition: C4Scoreboard.h:86
virtual bool Load(C4Group &hGroup, const char *szFilename, const char *szLanguage, C4LangStringTable *pLocalTable)
void Reg2List(C4AulScriptEngine *pEngine)
static void RemoveSolidMasks()
static void PutSolidMasks()
C4SoundModifier * Get(class C4PropList *props, bool create_if_not_found)
void SetGlobalModifier(C4SoundModifier *new_modifier, int32_t player_index)
C4SoundModifierList Modifiers
Definition: C4SoundSystem.h:54
void ClearPointers(C4Object *pObj)
int32_t LoadEffects(C4Group &hGroup, const char *namespace_prefix, bool group_is_root)
static void Unload()
Definition: C4Startup.cpp:313
const char * GetCStr() const
Definition: C4StringTable.h:49
C4String * FindString(const char *strString) const
C4String P[P_LAST]
bool SavePNG(C4Group &hGroup, const char *szFilename, bool fSaveAlpha=true, bool fSaveOverlayOnly=false)
float Zoom
Definition: C4Facet.h:165
int32_t GetStartupTeamCount(int32_t startup_player_count)
Definition: C4Teams.cpp:913
void RecheckPlayers()
Definition: C4Teams.cpp:663
static bool LoadFlags(C4Group &hGroup, const char *szEntryName, bool *pOverloadMaterials, bool *pOverloadTextures)
Definition: C4Texture.cpp:187
int32_t Init()
Definition: C4Texture.cpp:292
void Clear()
Definition: C4Texture.cpp:168
int32_t LoadMap(C4Group &hGroup, const char *szEntryName, bool *pOverloadMaterials, bool *pOverloadTextures)
Definition: C4Texture.cpp:211
int32_t LoadTextures(C4Group &hGroup, C4Group *OverloadFile=nullptr)
Definition: C4Texture.cpp:340
bool ChangeGrade(int32_t iChange)
Definition: C4ToolsDlg.cpp:173
bool ToggleIFT()
Definition: C4ToolsDlg.h:74
bool ToggleTool()
Definition: C4ToolsDlg.h:71
bool PopMaterial()
Definition: C4Console.cpp:703
bool PopTextures()
Definition: C4Console.cpp:704
void ClearPointers(C4Object *pObj)
void Init(C4Facet &cgo)
void SetSize(int32_t inSize)
int32_t GetSize() const
Definition: C4ValueArray.h:36
void SetPropList(C4PropList *PropList)
Definition: C4Value.h:141
StdStrBuf GetDataString(int depth=10, const class C4PropListStatic *ignore_reference_parent=nullptr) const
Definition: C4Value.cpp:131
C4PropList * _getPropList() const
Definition: C4Value.h:129
C4String * getStr() const
Definition: C4Value.h:117
C4V_Type GetType() const
Definition: C4Value.h:161
void Set0()
Definition: C4Value.h:332
int32_t _getInt() const
Definition: C4Value.h:122
C4String * _getStr() const
Definition: C4Value.h:126
void SetString(C4String *Str)
Definition: C4Value.h:138
void Denumerate(C4ValueNumbers *)
Definition: C4Value.cpp:251
void Denumerate()
Definition: C4Value.cpp:281
bool FreeScroll(C4Vec2D scroll_by)
bool ViewportNextPlayer()
void RecalculateViewports()
C4Viewport * GetViewport(int32_t player_nr, C4Viewport *prev=nullptr)
bool CreateViewport(int32_t player_nr, bool silent=false)
bool ViewportZoomOut()
bool ViewportZoomIn()
void ClearPointers(C4Object *obj)
void Clear()
Definition: C4Weather.cpp:89
void Default()
Definition: C4Weather.cpp:105
void Execute()
Definition: C4Weather.cpp:58
void Init(bool fScenario)
Definition: C4Weather.cpp:39
bool GetSize(C4Rect *pRect)
Definition: C4AppT.cpp:108
C4Surface * pSurface
Definition: C4Window.h:275
bool Active
Definition: C4Window.h:274
int GetLineHeight() const
Definition: C4FontLoader.h:125
bool GetTextExtent(const char *szText, int32_t &rsx, int32_t &rsy, bool fCheckMarkup=true)
void Value(const T &rStruct)
Definition: StdCompiler.h:161
virtual void NameEnd(bool fBreak=false)
Definition: StdCompiler.h:78
bool isSerializer()
Definition: StdCompiler.h:54
virtual bool isDeserializer()
Definition: StdCompiler.h:53
virtual bool Name(const char *szName)
Definition: StdCompiler.h:77
const StdMeshBox & GetBoundingBox() const
Definition: StdMesh.h:206
bool ScheduleProcs(int iTimeout=1000/36)
void Remove(StdSchedulerProc *pProc)
void Add(StdSchedulerProc *pProc)
size_t getSize() const
Definition: StdBuf.h:444
void Ref(const char *pnData)
Definition: StdBuf.h:455
const char * getData() const
Definition: StdBuf.h:442
void Copy()
Definition: StdBuf.h:467
bool LoadFromFile(const char *szFile)
Definition: StdBuf.cpp:73
void Clear()
Definition: StdBuf.h:466
size_t getLength() const
Definition: StdBuf.h:445
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:174
int32_t GetScreenHgt()
Definition: C4Gui.h:2825
int32_t GetScreenWdt()
Definition: C4Gui.h:2824
@ Ico_Controller_X
Definition: C4Gui.h:719
@ Ico_Controller_Back
Definition: C4Gui.h:721
@ Ico_Controller_LeftStick
Definition: C4Gui.h:732
@ Ico_Controller_LeftTrigger
Definition: C4Gui.h:730
@ Ico_Lobby
Definition: C4Gui.h:675
@ Ico_NetWait
Definition: C4Gui.h:644
@ Ico_Ex_LockedFrontal
Definition: C4Gui.h:711
@ Ico_Controller_DpadUp
Definition: C4Gui.h:727
@ Ico_Controller_DpadRight
Definition: C4Gui.h:725
@ Ico_Controller_DpadDown
Definition: C4Gui.h:726
@ Ico_Controller_RightStick
Definition: C4Gui.h:733
@ Ico_Controller_Dpad
Definition: C4Gui.h:723
@ Ico_Ex_League
Definition: C4Gui.h:706
@ Ico_Controller_A
Definition: C4Gui.h:717
@ Ico_RuntimeJoin
Definition: C4Gui.h:676
@ Ico_Controller_Start
Definition: C4Gui.h:722
@ Ico_Controller_LeftShoulder
Definition: C4Gui.h:728
@ Ico_Controller_RightShoulder
Definition: C4Gui.h:729
@ Ico_Controller_DpadLeft
Definition: C4Gui.h:724
@ Ico_Controller_RightTrigger
Definition: C4Gui.h:731
@ Ico_Controller_B
Definition: C4Gui.h:718
@ Ico_GameRunning
Definition: C4Gui.h:674
@ Ico_Controller_Y
Definition: C4Gui.h:720
void Any(T &keys)
void Ok(T &keys)
void Left(T &keys)
void Down(T &keys)
void Up(T &keys)
void Cancel(T &keys)
void Right(T &keys)
float y2
Definition: StdMesh.h:147
float x2
Definition: StdMesh.h:147
float y1
Definition: StdMesh.h:146
float x1
Definition: StdMesh.h:146
float Zoom
Definition: C4Draw.h:70