1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef CRYOMNI3D_VERSAILLES_ENGINE_H 24 #define CRYOMNI3D_VERSAILLES_ENGINE_H 25 26 #include "common/events.h" 27 #include "common/random.h" 28 #include "common/array.h" 29 #include "common/hashmap.h" 30 #include "common/str.h" 31 32 #include "cryomni3d/cryomni3d.h" 33 #include "cryomni3d/omni3d.h" 34 #include "cryomni3d/sprites.h" 35 #include "cryomni3d/wam_parser.h" 36 37 #include "cryomni3d/versailles/documentation.h" 38 #include "cryomni3d/versailles/toolbar.h" 39 #include "cryomni3d/versailles/dialogs_manager.h" 40 41 namespace Graphics { 42 class ManagedSurface; 43 struct Surface; 44 } 45 46 namespace CryOmni3D { 47 struct FixedImageConfiguration; 48 class ZonFixedImage; 49 } 50 51 namespace CryOmni3D { 52 namespace Versailles { 53 struct PlaceStateActionKey { 54 uint placeId; 55 uint placeState; 56 uint actionId; PlaceStateActionKeyPlaceStateActionKey57 PlaceStateActionKey(uint placeId_, uint placeState_, uint actionId_) : 58 placeId(placeId_), placeState(placeState_), actionId(actionId_) {} 59 60 bool operator==(const PlaceStateActionKey &other) const { 61 return other.placeId == placeId && other.placeState == placeState && other.actionId == actionId; 62 } 63 }; 64 65 struct PlaceActionKey { 66 uint placeId; 67 uint actionId; PlaceActionKeyPlaceActionKey68 PlaceActionKey(uint placeId_, uint actionId_) : 69 placeId(placeId_), actionId(actionId_) {} 70 71 bool operator==(const PlaceActionKey &other) const { 72 return other.placeId == placeId && other.actionId == actionId; 73 } 74 }; 75 } 76 } 77 78 namespace Common { 79 template<> 80 struct Hash<CryOmni3D::Versailles::PlaceStateActionKey> { 81 uint operator()(const CryOmni3D::Versailles::PlaceStateActionKey &k) const { 82 // placeState shouldn't be greater than 8 and placeId shouldn't be greater than 100 83 // originalActionId shouldn't be greater than 65536 84 return (k.placeId << 24 | k.placeState << 16) ^ k.actionId; 85 } 86 }; 87 template<> 88 struct Hash<CryOmni3D::Versailles::PlaceActionKey> { 89 uint operator()(const CryOmni3D::Versailles::PlaceActionKey &k) const { 90 // placeId shouldn't be greater than 100 91 // originalActionId shouldn't be greater than 65536 92 return (k.placeId << 16) ^ k.actionId; 93 } 94 }; 95 } 96 97 namespace CryOmni3D { 98 namespace Versailles { 99 100 class CryOmni3DEngine_Versailles; 101 102 enum AbortCommand { 103 kAbortNoAbort = 0, 104 kAbortQuit = 1, 105 kAbortLoadGame = 2, 106 kAbortNewGame = 3, 107 kAbortNextLevel = 5, 108 kAbortFinished = 6, 109 kAbortGameOver = 7 110 }; 111 112 struct GameVariables { 113 enum Var { 114 kCollectScore = 0, // 0 115 kUnlockHiddenDoor, 116 kAlreadyWent3_19, 117 kMedalsDrawerStatus, 118 kCurrentTime, 119 kGotMedalsSolution, 120 kCabinetDrawerStatus, 121 kDecipherScore, 122 kCollectLampoonArchitecture, 123 kGotRevealedPaper, 124 kCollectKey, // 10 125 kCollectPortfolio, 126 kSketchState, 127 kFakeSketchChatState, 128 kCollectFood, 129 kCollectQuill, 130 kStateLampoonReligion, 131 kCollectSmallKey3, 132 kCollectEngraving, 133 kCollectCord, 134 kCollectVaubanBlueprint1, // 20 135 kCollectVaubanBlueprint2, 136 kLadderState, 137 kOpenedCurtain, 138 kLoweredChandelier, 139 kCombedOrangeTree, 140 kMaineTalked, 141 kUsedLitCandle, 142 kBombState, 143 kInkSpilled, 144 kCollectedPaperOnTable, // 30 145 kSafeUnlocked, 146 //kUselessVar, 147 kCollectedPaperInTrunk = 33, 148 kBrushColor, 149 kUsedScissors, 150 kUnlockedAttic, 151 kHasPlayedLebrun, 152 kWarnedIncomplete, 153 kUsedVaubanBlueprint1, 154 kUsedVaubanBlueprint2, // 40 155 kSeenMemorandum, 156 kCollectScissors, 157 kSavedCountdown, 158 kMax 159 }; 160 }; 161 162 // For random sounds we set a constant ID and avoid to use it elsewhere 163 struct SoundIds { 164 enum { 165 kOrgue = 0, 166 kLeb001, 167 kMax 168 }; 169 }; 170 171 struct LocalizedFilenames { 172 enum { 173 kDialogs = 0, 174 kAllDocs, 175 kLinksDocs, 176 kCredits, 177 kLeb001, 178 kMax 179 }; 180 }; 181 182 struct PlaceState { 183 typedef void (CryOmni3DEngine_Versailles::*InitFunc)(); 184 typedef bool (CryOmni3DEngine_Versailles::*FilterEventFunc)(uint *event); 185 186 PlaceState() : initPlace(nullptr), filterEvent(nullptr), docImage(nullptr), state(0) {} 187 PlaceState(InitFunc initPlace_, FilterEventFunc filterEvent_, const char *docImage_) : 188 initPlace(initPlace_), filterEvent(filterEvent_), docImage(docImage_), state(0) {} 189 190 InitFunc initPlace; 191 FilterEventFunc filterEvent; 192 const char *docImage; 193 uint state; 194 }; 195 196 struct LevelInitialState { 197 uint placeId; 198 double alpha; 199 double beta; 200 }; 201 202 struct FakeTransitionActionPlace { 203 uint actionId; 204 uint placeId; 205 }; 206 207 typedef void (CryOmni3DEngine_Versailles::*FixedImgCallback)(ZonFixedImage *); 208 209 struct MsgBoxParameters { 210 int font; 211 byte foreColor; 212 uint lineHeight; 213 uint spaceWidth; 214 uint charSpacing; 215 uint initialWidth; 216 uint incrementWidth; 217 uint initialHeight; 218 uint incrementHeight; 219 uint timeoutChar; 220 }; 221 222 class CryOmni3DEngine_Versailles : public CryOmni3DEngine { 223 friend class Versailles_DialogsManager; 224 protected: 225 Common::Error run() override; 226 227 public: 228 CryOmni3DEngine_Versailles(OSystem *syst, const CryOmni3DGameDescription *gamedesc); 229 virtual ~CryOmni3DEngine_Versailles(); 230 231 bool hasFeature(EngineFeature f) const override; 232 virtual Common::Error loadGameState(int slot) override; 233 virtual Common::Error saveGameState(int slot, const Common::String &desc) override; 234 235 Common::String prepareFileName(const Common::String &baseName, const char *extension) const { 236 const char *const extensions[] = { extension, nullptr }; 237 return prepareFileName(baseName, extensions); 238 } 239 virtual Common::String prepareFileName(const Common::String &baseName, 240 const char *const *extensions) const override; 241 242 void setupPalette(const byte *colors, uint start, uint num) override { setupPalette(colors, start, num, true); } 243 void makeTranslucent(Graphics::Surface &dst, const Graphics::Surface &src) const override; 244 245 virtual bool displayToolbar(const Graphics::Surface *original) override { return _toolbar.displayToolbar(original); }; 246 virtual bool hasPlaceDocumentation() override; 247 virtual bool displayPlaceDocumentation() override; 248 virtual uint displayOptions() override; 249 virtual bool shouldAbort() override; 250 251 private: 252 void setupFonts(); 253 void setupSprites(); 254 void loadCursorsPalette(); 255 void calculateTransparentMapping(); 256 void setupObjects(); 257 void setupDialogVariables(); 258 void setupImgScripts(); 259 void loadStaticData(); 260 261 void syncOmni3DSettings(); 262 void syncSoundSettings(); 263 264 void playTransitionEndLevel(int level); 265 void changeLevel(int level); 266 void initNewLevel(int level); 267 void setupLevelWarps(int level); 268 void initPlacesStates(); 269 void initWhoSpeaksWhere(); 270 void initDocPeopleRecord(); 271 void setupLevelActionsMask(); 272 273 uint currentGameTime() const { return _gameVariables[GameVariables::kCurrentTime]; } 274 void setGameTime(uint newTime, uint level); 275 void updateGameTimeDialVariables(); 276 277 void gameStep(); 278 void doGameOver(); 279 280 void setPlaceState(uint placeId, uint newState); 281 void doPlaceChange(); 282 void executeTransition(uint nextPlaceId); 283 void fakeTransition(uint dstPlaceId); 284 uint determineTransitionAnimation(uint srcId, uint dstId, 285 const Transition **transition); 286 287 uint getFakeTransition(uint actionId) const; 288 void fixActionId(uint *actionId) const; 289 290 int handleWarp(); 291 bool handleWarpMouse(uint *actionId, uint movingCuror); 292 void animateWarpTransition(const Transition *transition); 293 void redrawWarp(); 294 295 void handleFixedImg(const FixedImgCallback &callback); 296 void executeSeeAction(uint actionId); 297 298 void executeSpeakAction(uint actionId); 299 void setupDialogShows(); 300 bool preprocessDialog(const Common::String &sequence); 301 void postprocessDialog(const Common::String &sequence); 302 303 void executeDocAction(uint actionId); 304 305 void drawMenuTitle(Graphics::ManagedSurface *surface, byte color); 306 uint displayFilePicker(const Graphics::Surface *bgFrame, bool saveMode, 307 Common::String &saveName); 308 uint displayYesNoBox(Graphics::ManagedSurface &surface, const Common::Rect &position, 309 uint msg_id); 310 void displayMessageBox(const MsgBoxParameters ¶ms, const Graphics::Surface *surface, 311 uint msg_id, const Common::Point &position, 312 const Common::Functor0<void> &callback) { displayMessageBox(params, surface, _messages[msg_id], position, callback); } 313 void displayMessageBox(const MsgBoxParameters ¶ms, const Graphics::Surface *surface, 314 const Common::String &msg, const Common::Point &position, 315 const Common::Functor0<void> &callback); 316 void displayMessageBoxWarp(const Common::String &message); 317 void displayMessageBoxWarp(uint msg_id) { displayMessageBoxWarp(_messages[msg_id]); } 318 void displayCredits(); 319 320 void warpMsgBoxCB(); 321 322 bool canVisit() const; 323 Common::String getSaveFileName(bool visit, uint saveNum) const; 324 void getSavesList(bool visit, Common::Array<Common::String> &saveNames); 325 void saveGame(bool visit, uint saveNum, const Common::String &saveName); 326 bool loadGame(bool visit, uint saveNum); 327 328 void animateCursor(const Object *object); 329 void collectObject(Object *object, const ZonFixedImage *fimg = nullptr, 330 bool showObject = true); 331 void collectObject(uint nameID, const ZonFixedImage *fimg = nullptr, 332 bool showObject = true) { collectObject(_objects.findObjectByNameID(nameID), fimg, showObject); } 333 typedef void (CryOmni3DEngine_Versailles::*DisplayObjectHook)(Graphics::ManagedSurface &surface); 334 void displayObject(const Common::String &imgName, DisplayObjectHook hook = nullptr); 335 336 void setMainPaletteColor(byte color, byte red, byte green, byte blue); 337 void setupPalette(const byte *colors, uint start, uint num, bool commit); 338 339 bool showSubtitles() const; 340 341 void playInGameVideo(const Common::String &filename, bool restoreCursorPalette = true); 342 343 void loadBMPs(const char *pattern, Graphics::Surface *bmps, uint count); 344 345 uint getMusicId(uint level, uint placeId) const; 346 bool musicWouldChange(uint level, uint placeId) const; 347 void musicUpdate(); 348 void musicPause(); 349 void musicResume(); 350 void musicStop(); 351 void musicSetQuiet(bool quiet); 352 353 Common::StringArray _localizedFilenames; 354 Common::StringArray _messages; 355 static const uint kSpritesMapTable[]; 356 static const uint kSpritesMapTableSize; 357 static const LevelInitialState kLevelInitialStates[]; 358 static const FakeTransitionActionPlace kFakeTransitions[]; 359 Common::HashMap<uint, FixedImgCallback> _imgScripts; 360 Common::Array<Common::String> _paintingsTitles; 361 362 Toolbar _toolbar; 363 364 byte *_mainPalette; 365 byte *_cursorPalette; 366 bool _fadedPalette; 367 bool _forcePaletteUpdate; 368 bool _forceRedrawWarp; 369 370 byte *_transparentPaletteMap; 371 uint _transparentSrcStart; 372 uint _transparentSrcStop; 373 uint _transparentDstStart; 374 uint _transparentDstStop; 375 uint _transparentNewStart; 376 uint _transparentNewStop; 377 378 bool _isPlaying; 379 bool _isVisiting; 380 AbortCommand _abortCommand; 381 uint _loadedSave; 382 383 int _omni3dSpeed; 384 385 uint _currentLevel; 386 Versailles_DialogsManager _dialogsMan; 387 388 Omni3DManager _omni3dMan; 389 ZonFixedImage *_fixedImage; 390 391 Common::Array<uint> _gameVariables; 392 Common::Array<PlaceState> _placeStates; 393 Common::HashMap<PlaceStateActionKey, uint> _actionMasks; 394 Common::HashMap<PlaceActionKey, Common::String> _whoSpeaksWhere; 395 Common::HashMap<uint, const char *> _docPeopleRecord; 396 bool _transitionAnimateWarp; 397 uint _nextPlaceId; 398 WAMParser _wam; 399 uint _currentPlaceId; 400 const Place *_currentPlace; 401 const Image::ImageDecoder *_currentWarpImage; 402 403 const char *_musicCurrentFile; 404 Audio::SoundHandle _musicHandle; 405 float _musicVolumeFactor; 406 static const char *kMusicFiles[8][8]; 407 408 Versailles_Documentation _docManager; 409 410 static const MsgBoxParameters kWarpMsgBoxParameters; 411 static const MsgBoxParameters kFixedimageMsgBoxParameters; 412 static const FixedImageConfiguration kFixedImageConfiguration; 413 414 // Countdown 415 void initCountdown(); 416 void syncCountdown(); 417 inline bool countDown() { if (_countingDown) { return doCountDown(); } else { return false; } } 418 inline void drawCountdown(Graphics::ManagedSurface *surface = nullptr) { if (_countingDown) { doDrawCountdown(surface); } } 419 void drawCountdownVideo(uint frameNum) { drawCountdown(); } 420 421 bool _countingDown; 422 uint _countdownNextEvent; 423 char _countdownValue[6]; 424 Graphics::ManagedSurface _countdownSurface; 425 bool doCountDown(); 426 void doDrawCountdown(Graphics::ManagedSurface *surface); 427 428 // Objects 429 template<uint ID> 430 void genericDisplayObject(); 431 void obj_105(); 432 void obj_106(); 433 void obj_107(); 434 void obj_118(); 435 void obj_121(); 436 void obj_125(); 437 void obj_126(); 438 void obj_126hk(Graphics::ManagedSurface &surface); 439 void obj_142(); 440 void obj_142hk(Graphics::ManagedSurface &surface); 441 442 // Fixed image 443 template<uint ID> 444 void genericDumbImage(ZonFixedImage *fimg); 445 template<uint ID> 446 void genericPainting(ZonFixedImage *fimg); 447 #define IMG_CB(name) void img_ ## name(ZonFixedImage *fimg) 448 IMG_CB(31101); 449 IMG_CB(31101b); 450 IMG_CB(31142); 451 IMG_CB(31142b); 452 IMG_CB(31142c); 453 IMG_CB(31142d); 454 IMG_CB(31143); 455 IMG_CB(31143b); 456 IMG_CB(31143c); 457 IMG_CB(31143d); 458 IMG_CB(32120); 459 IMG_CB(32120b); 460 IMG_CB(32120c); 461 IMG_CB(32201); 462 IMG_CB(32202); 463 IMG_CB(32203); 464 IMG_CB(32204); 465 IMG_CB(32204b); 466 IMG_CB(34131); 467 IMG_CB(34132); 468 IMG_CB(34172); 469 IMG_CB(34173); 470 IMG_CB(34173b); 471 IMG_CB(34173c); 472 IMG_CB(34174); 473 IMG_CB(34174b); 474 IMG_CB(34174c); 475 IMG_CB(34174d); 476 IMG_CB(34174e); 477 IMG_CB(34174f); 478 static const uint kSafeDigitsCount = 12; 479 static const uint16 kSafeDigitsX[]; 480 static const uint16 kSafeDigitsY[]; 481 static const char *kSafeDates[]; 482 bool handleSafe(ZonFixedImage *fimg); 483 void drawSafeDigits(Graphics::ManagedSurface &surface, const Graphics::Surface(&bmpDigits)[10], 484 const unsigned char (&safeDigits)[kSafeDigitsCount]); 485 bool checkSafeDigits(unsigned char (&safeDigits)[kSafeDigitsCount]); 486 487 IMG_CB(41202); 488 IMG_CB(41202b); 489 IMG_CB(41801); 490 IMG_CB(41801b); 491 IMG_CB(41801c); 492 IMG_CB(41802); 493 IMG_CB(41802b); 494 IMG_CB(41802c); 495 IMG_CB(41802d); 496 IMG_CB(43143); 497 IMG_CB(43143b); 498 IMG_CB(43145); 499 IMG_CB(43145b); 500 IMG_CB(43145c); 501 IMG_CB(43146); 502 IMG_CB(43146b); 503 IMG_CB(43146c); 504 IMG_CB(43160); 505 IMG_CB(43160b); 506 IMG_CB(43160c); 507 IMG_CB(43160d); 508 IMG_CB(43190); 509 IMG_CB(43190b); 510 IMG_CB(43190c); 511 IMG_CB(43190d); 512 IMG_CB(43190e); 513 IMG_CB(43190f); 514 IMG_CB(44071); 515 IMG_CB(44071b); 516 IMG_CB(44161); 517 IMG_CB(44161b); 518 IMG_CB(44161c); 519 IMG_CB(44161d); 520 IMG_CB(44161e); 521 IMG_CB(44161f); 522 static const uint kEpigraphMaxLetters = 32; 523 Common::String _epigraphContent; 524 Common::String _epigraphPassword; 525 bool handleEpigraph(ZonFixedImage *fimg); 526 void drawEpigraphLetters(Graphics::ManagedSurface &surface, 527 const Graphics::Surface(&bmpLetters)[28], const Common::String &letters); 528 IMG_CB(45130); 529 IMG_CB(45270); 530 IMG_CB(45270b); 531 IMG_CB(45270c); 532 IMG_CB(45270d); 533 IMG_CB(45280); 534 535 IMG_CB(88001); 536 IMG_CB(88001b); 537 IMG_CB(88001c); 538 IMG_CB(88002); 539 IMG_CB(88003); 540 IMG_CB(88003b); 541 IMG_CB(88003c); 542 IMG_CB(88003d); 543 IMG_CB(88003e); 544 IMG_CB(88003f); 545 Common::String _bombPassword; 546 static const uint kBombPasswordSmallLength = 40; 547 static const uint kBombPasswordMaxLength = 60; 548 static const uint16 kBombLettersPos[2][kBombPasswordMaxLength][2]; 549 bool handleBomb(ZonFixedImage *fimg); 550 void drawBombLetters(Graphics::ManagedSurface &surface, const Graphics::Surface(&bmpLetters)[28], 551 const uint bombPasswordLength, 552 const unsigned char (&bombPossibilites)[kBombPasswordMaxLength][5], 553 const unsigned char (&bombCurrentLetters)[kBombPasswordMaxLength]); 554 IMG_CB(88004); 555 IMG_CB(88004b); 556 #undef IMG_CB 557 558 #define FILTER_EVENT(level, place) bool filterEventLevel ## level ## Place ## place(uint *event) 559 #define INIT_PLACE(level, place) void initPlaceLevel ## level ## Place ## place() 560 FILTER_EVENT(1, 1); 561 FILTER_EVENT(1, 2); 562 INIT_PLACE(1, 3); 563 FILTER_EVENT(1, 3); 564 //FILTER_EVENT(1, 7); // Not used 565 FILTER_EVENT(1, 14); 566 567 FILTER_EVENT(2, 1); 568 FILTER_EVENT(2, 2); 569 FILTER_EVENT(2, 5); 570 INIT_PLACE(2, 9); 571 FILTER_EVENT(2, 9); 572 FILTER_EVENT(2, 11); 573 FILTER_EVENT(2, 12); 574 FILTER_EVENT(2, 14); 575 576 FILTER_EVENT(3, 3); 577 FILTER_EVENT(3, 10); 578 FILTER_EVENT(3, 13); 579 FILTER_EVENT(3, 15); 580 FILTER_EVENT(3, 17); 581 FILTER_EVENT(3, 18); 582 FILTER_EVENT(3, 19); 583 FILTER_EVENT(3_5, 20); 584 FILTER_EVENT(3, 22); 585 FILTER_EVENT(3, 23); 586 bool filterEventLevel3Obj23151(); 587 void collectLampoonArchitecture(const ZonFixedImage *fimg = nullptr); 588 589 INIT_PLACE(4, 9); 590 FILTER_EVENT(4, 10); 591 FILTER_EVENT(4, 12_13_14); 592 FILTER_EVENT(4, 15); 593 FILTER_EVENT(4, 16); 594 FILTER_EVENT(4, 17); 595 596 INIT_PLACE(5, 6); 597 FILTER_EVENT(5, 9); 598 FILTER_EVENT(5, 14); 599 FILTER_EVENT(5, 15); 600 FILTER_EVENT(5, 16); 601 void filterEventLevel5UpdatePlaceStates(); 602 //FILTER_EVENT(3_5, 20); 603 FILTER_EVENT(5, 23); 604 FILTER_EVENT(5, 27); 605 FILTER_EVENT(5, 28); 606 FILTER_EVENT(5, 29); 607 FILTER_EVENT(5, 33); 608 FILTER_EVENT(5, 34); 609 610 FILTER_EVENT(6, 1); 611 FILTER_EVENT(6, 3); 612 FILTER_EVENT(6, Orangery); 613 FILTER_EVENT(6, 19); 614 615 FILTER_EVENT(7, 2); 616 FILTER_EVENT(7, 9); 617 FILTER_EVENT(7, 10_11_13); 618 FILTER_EVENT(7, 20); 619 #undef FILTER_EVENT 620 #undef INIT_PLACE 621 622 // Dialogs shows 623 void dialogShowBontempsShowThird(); 624 void dialogShowHuissierShowPamphlet(); 625 void dialogShowMonseigneurSorts(); 626 void dialogShowLeBrunWatches(); 627 void dialogShowDoorsOpen(); 628 void dialogShowSwissGuardGives(); 629 void dialogShowLullyCorrects(); 630 void dialogShowBontempsGivesAuth(); 631 void dialogShowCroissyLeave(); 632 void dialogShowMaintenonGives(); 633 void dialogShowLaChaizeGivesBack(); 634 void dialogShowLaChaizeWrites(); 635 void dialogShowLaChaizeGivesPamphlet(); 636 void dialogShowBontempsGivesKey(); 637 void dialogShowDuMaineLeaves(); 638 void dialogShowTransitionScene(); 639 void dialogShowEndOfGame(); 640 void dialogShowLeBrunGives(); 641 void dialogShowLeBrunLeave(); 642 }; 643 644 } // End of namespace Versailles 645 } // End of namespace CryOmni3D 646 647 #endif 648