| 1 | /* |
| 2 | * LegacyClonk |
| 3 | * |
| 4 | * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design) |
| 5 | * Copyright (c) 2017-2021, The LegacyClonk Team and contributors |
| 6 | * |
| 7 | * Distributed under the terms of the ISC license; see accompanying file |
| 8 | * "COPYING" for details. |
| 9 | * |
| 10 | * "Clonk" is a registered trademark of Matthes Bender, used with permission. |
| 11 | * See accompanying file "TRADEMARK" for details. |
| 12 | * |
| 13 | * To redistribute this file separately, substitute the full license texts |
| 14 | * for the above references. |
| 15 | */ |
| 16 | |
| 17 | /* Main class to run the game */ |
| 18 | |
| 19 | #pragma once |
| 20 | |
| 21 | #include <C4Def.h> |
| 22 | #include <C4Texture.h> |
| 23 | #include <C4RankSystem.h> |
| 24 | #include <C4GraphicsSystem.h> |
| 25 | #include <C4GraphicsResource.h> |
| 26 | #include <C4GameMessage.h> |
| 27 | #include <C4MouseControl.h> |
| 28 | #include <C4MessageInput.h> |
| 29 | #include <C4Weather.h> |
| 30 | #include <C4Material.h> |
| 31 | #include <C4GameObjects.h> |
| 32 | #include <C4Landscape.h> |
| 33 | #include <C4Scenario.h> |
| 34 | #include <C4MassMover.h> |
| 35 | #include <C4PXS.h> |
| 36 | #include <C4PlayerList.h> |
| 37 | #include <C4Teams.h> |
| 38 | #include <C4PlayerInfo.h> |
| 39 | #include <C4Control.h> |
| 40 | #include <C4PathFinder.h> |
| 41 | #include <C4ComponentHost.h> |
| 42 | #include <C4ScriptHost.h> |
| 43 | #include <C4Particles.h> |
| 44 | #include <C4GroupSet.h> |
| 45 | #include <C4Extra.h> |
| 46 | #include <C4GameControl.h> |
| 47 | #include <C4Effects.h> |
| 48 | #include <C4Fonts.h> |
| 49 | #include "C4LangStringTable.h" |
| 50 | #include "C4Scoreboard.h" |
| 51 | #include <C4Network2.h> |
| 52 | #include <C4Scenario.h> |
| 53 | #include <C4Client.h> |
| 54 | #include <C4Network2Reference.h> |
| 55 | #include <C4RoundResults.h> |
| 56 | #include <C4NetworkRestartInfos.h> |
| 57 | #include "C4FileMonitor.h" |
| 58 | |
| 59 | class C4Game |
| 60 | { |
| 61 | private: |
| 62 | // used as StdCompiler-parameter |
| 63 | struct CompileSettings |
| 64 | { |
| 65 | bool fScenarioSection; |
| 66 | bool fPlayers; |
| 67 | bool fExact; |
| 68 | |
| 69 | CompileSettings(bool fScenarioSection, bool fPlayers, bool fExact) |
| 70 | : fScenarioSection(fScenarioSection), fPlayers(fPlayers), fExact(fExact) {} |
| 71 | }; |
| 72 | |
| 73 | // struct of keyboard set and indexed control key |
| 74 | struct C4KeySetCtrl |
| 75 | { |
| 76 | int32_t iKeySet, iCtrl; |
| 77 | |
| 78 | C4KeySetCtrl(int32_t iKeySet, int32_t iCtrl) : iKeySet(iKeySet), iCtrl(iCtrl) {} |
| 79 | }; |
| 80 | |
| 81 | public: |
| 82 | C4Game(); |
| 83 | ~C4Game(); |
| 84 | |
| 85 | public: |
| 86 | C4DefList Defs; |
| 87 | C4TextureMap TextureMap; |
| 88 | C4RankSystem Rank; |
| 89 | C4GraphicsSystem GraphicsSystem; |
| 90 | C4MessageInput MessageInput; |
| 91 | C4GraphicsResource GraphicsResource; |
| 92 | C4Network2 Network; |
| 93 | C4ClientList &Clients; // Shortcut |
| 94 | C4GameParameters Parameters; |
| 95 | C4TeamList &Teams; // Shortcut |
| 96 | C4PlayerInfoList &PlayerInfos; // Shortcut |
| 97 | C4PlayerInfoList &RestorePlayerInfos; // Shortcut |
| 98 | C4RoundResults RoundResults; |
| 99 | C4GameMessageList Messages; |
| 100 | C4MouseControl MouseControl; |
| 101 | C4Weather Weather; |
| 102 | C4MaterialMap Material; |
| 103 | C4GameObjects Objects; |
| 104 | C4ObjectList BackObjects; // objects in background (C4D_Background) |
| 105 | C4ObjectList ForeObjects; // objects in foreground (C4D_Foreground) |
| 106 | C4Landscape Landscape; |
| 107 | C4Scenario C4S; |
| 108 | C4ComponentHost Info; |
| 109 | C4ComponentHost Title; |
| 110 | C4ComponentHost Names; |
| 111 | C4ComponentHost GameText; |
| 112 | C4AulScriptEngine ScriptEngine; |
| 113 | C4GameScriptHost Script; |
| 114 | C4LangStringTable MainSysLangStringTable, ScenarioLangStringTable, ScenarioSysLangStringTable; |
| 115 | C4MassMoverSet MassMover; |
| 116 | C4PXSSystem PXS; |
| 117 | C4ParticleSystem Particles; |
| 118 | C4PlayerList Players; |
| 119 | StdStrBuf PlayerNames; |
| 120 | C4GameControl Control; |
| 121 | C4Control &Input; // shortcut |
| 122 | |
| 123 | C4PathFinder PathFinder; |
| 124 | C4TransferZones TransferZones; |
| 125 | C4Group ScenarioFile; |
| 126 | C4GroupSet GroupSet; |
| 127 | C4Group *pParentGroup; |
| 128 | C4Extra ; |
| 129 | C4GUI::Screen *pGUI; |
| 130 | C4ScenarioSection *pScenarioSections, *pCurrentScenarioSection; |
| 131 | C4Effect *pGlobalEffects; |
| 132 | #ifndef USE_CONSOLE |
| 133 | // We don't need fonts when we don't have graphics |
| 134 | C4FontLoader FontLoader; |
| 135 | #endif |
| 136 | C4Scoreboard Scoreboard; |
| 137 | class C4Network2Stats *pNetworkStatistics; // may be nullptr if no statistics are recorded |
| 138 | class C4KeyboardInput &KeyboardInput; |
| 139 | char CurrentScenarioSection[C4MaxName + 1]; |
| 140 | char ScenarioFilename[_MAX_PATH + 1]; |
| 141 | char PlayerFilenames[20 * _MAX_PATH + 1]; |
| 142 | std::vector<std::string> DefinitionFilenames; |
| 143 | bool FixedDefinitions; |
| 144 | char DirectJoinAddress[_MAX_PATH + 1]; |
| 145 | class C4Network2Reference *pJoinReference; |
| 146 | int32_t FPS, cFPS; |
| 147 | int32_t HaltCount; |
| 148 | bool GameOver; |
| 149 | bool Evaluated; |
| 150 | bool GameOverDlgShown; |
| 151 | bool fScriptCreatedObjects; |
| 152 | bool fLobby; |
| 153 | int32_t iLobbyTimeout; |
| 154 | bool fObserve; |
| 155 | bool NetworkActive; |
| 156 | StdStrBuf RecordDumpFile; |
| 157 | StdStrBuf RecordStream; |
| 158 | bool TempScenarioFile; |
| 159 | bool fPreinited; // set after PreInit has been called; unset by Clear and Default |
| 160 | int32_t FrameCounter; |
| 161 | int32_t iTick2, iTick3, iTick5, iTick10, iTick35, iTick255, iTick500, iTick1000; |
| 162 | bool TimeGo; |
| 163 | int32_t Time; |
| 164 | int32_t StartTime; |
| 165 | int32_t InitProgress; int32_t LastInitProgress; |
| 166 | int32_t ObjectEnumerationIndex; |
| 167 | int32_t Rules; |
| 168 | bool GameGo; |
| 169 | bool FullSpeed; |
| 170 | int32_t FrameSkip; bool DoSkipFrame; |
| 171 | uint32_t FoWColor; // FoW-color; may contain transparency |
| 172 | bool fResortAnyObject; // if set, object list will be checked for unsorted objects next frame |
| 173 | bool IsRunning; // (NoSave) if set, the game is running; if not, just the startup message board is painted |
| 174 | bool PointersDenumerated; // (NoSave) set after object pointers have been denumerated |
| 175 | bool fQuitWithError; // if set, game shut down irregularly |
| 176 | bool IsMusicEnabled; |
| 177 | int32_t iMusicLevel; // scenario-defined music level |
| 178 | // current play list |
| 179 | StdStrBuf PlayList; |
| 180 | bool DebugMode; |
| 181 | // next mission to be played after this one |
| 182 | StdStrBuf NextMission, NextMissionText, NextMissionDesc; |
| 183 | C4NetworkRestartInfos::Infos RestartRestoreInfos; |
| 184 | |
| 185 | public: |
| 186 | // Init and execution |
| 187 | void Default(); |
| 188 | void Clear(); |
| 189 | void Abort(bool fApproved = false); // hard-quit on Esc+Y (/J/O) |
| 190 | void Evaluate(); |
| 191 | void ShowGameOverDlg(); |
| 192 | void Sec1Timer(); |
| 193 | bool DoKeyboardInput(C4KeyCode vk_code, C4KeyEventType eEventType, bool fAlt, bool fCtrl, bool fShift, bool fRepeated, class C4GUI::Dialog *pForDialog = nullptr, bool fPlrCtrlOnly = false); |
| 194 | void DrawCursors(C4FacetEx &cgo, int32_t iPlayer); |
| 195 | bool LocalControlKey(C4KeyCodeEx key, C4KeySetCtrl Ctrl); |
| 196 | bool LocalControlKeyUp(C4KeyCodeEx key, C4KeySetCtrl Ctrl); |
| 197 | void LocalPlayerControl(int32_t iPlayer, int32_t iCom); |
| 198 | void FixRandom(int32_t iSeed); |
| 199 | bool Init(); |
| 200 | bool PreInit(); |
| 201 | void InitLogger(); |
| 202 | void ParseCommandLine(const char *szCmdLine); |
| 203 | bool Execute(); |
| 204 | class C4Player *JoinPlayer(const char *szFilename, int32_t iAtClient, const char *szAtClientName, C4PlayerInfo *pInfo); |
| 205 | bool DoGameOver(); |
| 206 | bool CanQuickSave(); |
| 207 | bool QuickSave(const char *strFilename, const char *strTitle, bool fForceSave = false); |
| 208 | void SetInitProgress(float fToProgress); |
| 209 | void OnResolutionChanged(); // update anything that's dependent on screen resolution |
| 210 | void InitFullscreenComponents(bool fRunning); |
| 211 | bool ToggleChat(); |
| 212 | // Pause |
| 213 | bool TogglePause(); |
| 214 | bool Pause(); |
| 215 | bool Unpause(); |
| 216 | bool IsPaused(); |
| 217 | // Network |
| 218 | void Synchronize(bool fSavePlayerFiles); |
| 219 | void SyncClearance(); |
| 220 | // Editing |
| 221 | bool DropFile(const char *szFilename, int32_t iX, int32_t iY); |
| 222 | bool CreateViewport(int32_t iPlayer, bool fSilent = false); |
| 223 | bool DropDef(C4ID id, int32_t iX, int32_t iY); |
| 224 | void ReloadFile(const char *path); |
| 225 | bool ReloadDef(C4ID id, uint32_t reloadWhat = C4D_Load_RX); |
| 226 | bool ReloadParticle(const char *szName); |
| 227 | // Object functions |
| 228 | void ClearPointers(C4Object *cobj); |
| 229 | C4Object *CreateObject(C4ID type, C4Object *pCreator, int32_t owner = NO_OWNER, |
| 230 | int32_t x = 50, int32_t y = 50, int32_t r = 0, |
| 231 | C4Fixed xdir = Fix0, C4Fixed ydir = Fix0, C4Fixed rdir = Fix0, int32_t iController = NO_OWNER); |
| 232 | C4Object *CreateObjectConstruction(C4ID type, |
| 233 | C4Object *pCreator, |
| 234 | int32_t owner, |
| 235 | int32_t ctx = 0, int32_t bty = 0, |
| 236 | int32_t con = 1, bool terrain = false); |
| 237 | C4Object *CreateInfoObject(C4ObjectInfo *cinf, int32_t owner, |
| 238 | int32_t tx = 50, int32_t ty = 50); |
| 239 | void BlastObjects(int32_t tx, int32_t ty, int32_t level, C4Object *inobj, int32_t iCausedBy, C4Object *pByObj); |
| 240 | void ShakeObjects(int32_t tx, int32_t ry, int32_t range, int32_t iCausedBy); |
| 241 | C4Object *OverlapObject(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, |
| 242 | int32_t category); |
| 243 | C4Object *FindObject(C4ID id, |
| 244 | int32_t iX = 0, int32_t iY = 0, int32_t iWdt = 0, int32_t iHgt = 0, |
| 245 | uint32_t ocf = OCF_All, |
| 246 | const char *szAction = nullptr, C4Object *pActionTarget = nullptr, |
| 247 | C4Object *pExclude = nullptr, |
| 248 | C4Object *pContainer = nullptr, |
| 249 | int32_t iOwner = ANY_OWNER, |
| 250 | C4Object *pFindNext = nullptr); |
| 251 | C4Object *FindVisObject( // find object in view at pos, regarding parallaxity and visibility (but not distance) |
| 252 | int32_t tx, int32_t ty, int32_t iPlr, const C4Facet &fctViewport, |
| 253 | int32_t iX = 0, int32_t iY = 0, int32_t iWdt = 0, int32_t iHgt = 0, |
| 254 | uint32_t ocf = OCF_All, |
| 255 | C4Object *pExclude = nullptr, |
| 256 | int32_t iOwner = ANY_OWNER, |
| 257 | C4Object *pFindNext = nullptr); |
| 258 | int32_t ObjectCount(C4ID id, |
| 259 | int32_t x = 0, int32_t y = 0, int32_t wdt = 0, int32_t hgt = 0, |
| 260 | uint32_t ocf = OCF_All, |
| 261 | const char *szAction = nullptr, C4Object *pActionTarget = nullptr, |
| 262 | C4Object *pExclude = nullptr, |
| 263 | C4Object *pContainer = nullptr, |
| 264 | int32_t iOwner = ANY_OWNER); |
| 265 | C4Object *FindBase(int32_t iPlayer, int32_t iIndex); |
| 266 | C4Object *FindFriendlyBase(int32_t iPlayer, int32_t iIndex); |
| 267 | C4Object *FindObjectByCommand(int32_t iCommand, C4Object *pTarget = nullptr, C4Value iTx = C4VNull, int32_t iTy = 0, C4Object *pTarget2 = nullptr, C4Object *pFindNext = nullptr); |
| 268 | void CastObjects(C4ID id, C4Object *pCreator, int32_t num, int32_t level, int32_t tx, int32_t ty, int32_t iOwner = NO_OWNER, int32_t iController = NO_OWNER); |
| 269 | void BlastCastObjects(C4ID id, C4Object *pCreator, int32_t num, int32_t tx, int32_t ty, int32_t iController = NO_OWNER); |
| 270 | C4Object *PlaceVegetation(C4ID id, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iGrowth); |
| 271 | C4Object *PlaceAnimal(C4ID idAnimal); |
| 272 | |
| 273 | bool LoadScenarioSection(const char *szSection, uint32_t dwFlags); |
| 274 | |
| 275 | bool DrawTextSpecImage(C4FacetExSurface &fctTarget, const char *szSpec, uint32_t dwClr = 0xff); |
| 276 | bool SpeedUp(); |
| 277 | bool SlowDown(); |
| 278 | bool InitKeyboard(); // register main keyboard input functions |
| 279 | |
| 280 | protected: |
| 281 | bool InitSystem(); |
| 282 | void InitInEarth(); |
| 283 | void InitVegetation(); |
| 284 | void InitAnimals(); |
| 285 | void InitGoals(); |
| 286 | void InitRules(); |
| 287 | void InitValueOverloads(); |
| 288 | void InitEnvironment(); |
| 289 | void UpdateRules(); |
| 290 | void CloseScenario(); |
| 291 | void DeleteObjects(bool fDeleteInactive); |
| 292 | void ExecObjects(); |
| 293 | void Ticks(); |
| 294 | std::vector<std::string> FoldersWithLocalsDefs(std::string path); |
| 295 | bool CheckObjectEnumeration(); |
| 296 | bool DefinitionFilenamesFromSaveGame(); |
| 297 | bool LoadScenarioComponents(); |
| 298 | void LoadScenarioScripts(); |
| 299 | |
| 300 | public: |
| 301 | bool SaveGameTitle(C4Group &hGroup); |
| 302 | bool Preload(); |
| 303 | bool CanPreload() const; |
| 304 | |
| 305 | protected: |
| 306 | bool InitGame(C4Group &hGroup, C4ScenarioSection *section, bool fLoadSky); |
| 307 | bool InitGameFirstPart(); |
| 308 | bool InitGameSecondPart(C4Group &hGroup, C4ScenarioSection *section, bool fLoadSky, bool preloading); |
| 309 | bool InitGameFinal(); |
| 310 | bool InitNetworkFromAddress(const char *szAddress); |
| 311 | bool InitNetworkFromReference(const C4Network2Reference &Reference); |
| 312 | bool InitNetworkHost(); |
| 313 | bool InitControl(); |
| 314 | bool InitScriptEngine(); |
| 315 | void LinkScriptEngine(); |
| 316 | bool InitPlayers(); |
| 317 | bool OpenScenario(); |
| 318 | bool InitDefs(); |
| 319 | bool InitMaterialTexture(); |
| 320 | bool EnumerateMaterials(); |
| 321 | bool GameOverCheck(); |
| 322 | bool PlaceInEarth(C4ID id); |
| 323 | bool Compile(const char *szSource); |
| 324 | bool Decompile(std::string &buf, bool fSaveSection, bool fSaveExact); |
| 325 | |
| 326 | public: |
| 327 | void CompileFunc(StdCompiler *pComp, CompileSettings comp); |
| 328 | bool SaveData(C4Group &hGroup, bool fSaveSection, bool fInitial, bool fSaveExact); |
| 329 | |
| 330 | protected: |
| 331 | bool CompileRuntimeData(C4ComponentHost &rGameData); |
| 332 | |
| 333 | // Object function internals |
| 334 | C4Object *NewObject(C4Def *ndef, C4Object *pCreator, |
| 335 | int32_t owner, C4ObjectInfo *info, |
| 336 | int32_t tx, int32_t ty, int32_t tr, |
| 337 | C4Fixed xdir, C4Fixed ydir, C4Fixed rdir, |
| 338 | int32_t con, int32_t iController); |
| 339 | void ClearObjectPtrs(C4Object *tptr); |
| 340 | void ObjectRemovalCheck(); |
| 341 | |
| 342 | bool ToggleDebugMode(); // dbg modeon/off if allowed |
| 343 | |
| 344 | public: |
| 345 | bool ToggleChart(); // chart dlg on/off |
| 346 | void SetMusicLevel(int32_t iToLvl); // change game music volume; multiplied by config volume for real volume |
| 347 | bool ToggleMusic(); // music on / off |
| 348 | bool ToggleSound(); // sound on / off |
| 349 | void AddDirectoryForMonitoring(const char *directory); |
| 350 | |
| 351 | protected: |
| 352 | enum class PreloadLevel |
| 353 | { |
| 354 | None, |
| 355 | Scenario, |
| 356 | Basic, |
| 357 | LandscapeObjects |
| 358 | }; |
| 359 | std::thread PreloadThread; |
| 360 | PreloadLevel PreloadStatus; |
| 361 | CStdCSecEx PreloadMutex; |
| 362 | bool LandscapeLoaded; |
| 363 | std::unique_ptr<C4FileMonitor> FileMonitor; |
| 364 | }; |
| 365 | |
| 366 | const int32_t C4RULE_StructuresNeedEnergy = 1, |
| 367 | C4RULE_ConstructionNeedsMaterial = 2, |
| 368 | C4RULE_FlagRemoveable = 4, |
| 369 | C4RULE_StructuresSnowIn = 8, |
| 370 | C4RULE_TeamHombase = 16; |
| 371 | |
| 372 | extern C4Game Game; |
| 373 | |
| 374 | // a global wrapper |
| 375 | inline std::string GetKeyboardInputName(const char *szKeyName, bool fShort = false, int32_t iIndex = 0) |
| 376 | { |
| 377 | return Game.KeyboardInput.GetKeyCodeNameByKeyName(szKeyName, fShort, iIndex); |
| 378 | } |
| 379 | |