void Entity::setup(ChapterIndex index) { switch(index) { case kChapterAll: getSavePoints()->setCallback(_entityIndex, _callbacks[_data->getCurrentCallback()]); break; case kChapter1: setup_chapter1(); break; case kChapter2: setup_chapter2(); break; case kChapter3: setup_chapter3(); break; case kChapter4: setup_chapter4(); break; case kChapter5: setup_chapter5(); break; default: break; } }
void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, bool keepIndex) { #define LOAD_ENTRY(name, func, val) { \ uint32 _prevPosition = (uint32)_savegame->pos(); \ func; \ uint32 _count = (uint32)_savegame->pos() - _prevPosition; \ debugC(kLastExpressDebugSavegame, "Savegame: Reading " #name ": %d bytes", _count); \ if (_count != val) \ error("SaveLoad::readEntry: Number of bytes read (%d) differ from expected count (%d)", _count, val); \ } #define LOAD_ENTRY_ONLY(name, func) { \ uint32 _prevPosition = (uint32)_savegame->pos(); \ func; \ uint32 _count = (uint32)_savegame->pos() - _prevPosition; \ debugC(kLastExpressDebugSavegame, "Savegame: Reading " #name ": %d bytes", _count); \ } if (!type || !entity || !val) error("SaveLoad::readEntry: Invalid parameters passed!"); // Load entry header SavegameEntryHeader entry; Common::Serializer ser(_savegame, NULL); entry.saveLoadWithSerializer(ser); if (!entry.isValid()) error("SaveLoad::readEntry: entry header is invalid!"); // Init type, entity & value *type = entry.type; *val = entry.value; // Save position uint32 originalPosition = (uint32)_savegame->pos(); // Load game data LOAD_ENTRY("entity index", ser.syncAsUint32LE(*entity), 4); LOAD_ENTRY("state", getState()->saveLoadWithSerializer(ser), 4 + 4 + 4 + 4 + 1 + 4 + 4); LOAD_ENTRY("selected item", getInventory()->saveSelectedItem(ser), 4); LOAD_ENTRY("positions", getEntities()->savePositions(ser), 4 * 1000); LOAD_ENTRY("compartments", getEntities()->saveCompartments(ser), 4 * 16 * 2); LOAD_ENTRY("progress", getProgress().saveLoadWithSerializer(ser), 4 * 128); LOAD_ENTRY("events", getState()->syncEvents(ser), 512); LOAD_ENTRY("inventory", getInventory()->saveLoadWithSerializer(ser), 7 * 32); LOAD_ENTRY("objects", getObjects()->saveLoadWithSerializer(ser), 5 * 128); LOAD_ENTRY("entities", getEntities()->saveLoadWithSerializer(ser), 1262 * 40); LOAD_ENTRY_ONLY("sound", getSound()->saveLoadWithSerializer(ser)); LOAD_ENTRY_ONLY("savepoints", getSavePoints()->saveLoadWithSerializer(ser)); // Update chapter getProgress().chapter = entry.chapter; // Skip padding uint32 offset = _savegame->pos() - originalPosition; if (offset & 0xF) { _savegame->seek((~offset & 0xF) + 1, SEEK_SET); } }
bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { bool clicked = (type == Common::EVENT_LBUTTONUP); switch(action) { default: hideOverlays(); break; ////////////////////////////////////////////////////////////////////////// case kMenuCredits: if (hasTimeDelta()) { hideOverlays(); break; } if (clicked) { showFrame(kOverlayEggButtons, kButtonCreditsPushed, true); showFrame(kOverlayTooltip, -1, true); getSound()->playSound(kEntityPlayer, "LIB046"); hideOverlays(); _isShowingCredits = true; _creditsSequenceIndex = 0; showFrame(kOverlayCredits, 0, true); } else { // TODO check flags ? showFrame(kOverlayEggButtons, kButtonCredits, true); showFrame(kOverlayTooltip, kTooltipCredits, true); } break; ////////////////////////////////////////////////////////////////////////// case kMenuQuitGame: showFrame(kOverlayTooltip, kTooltipQuit, true); if (clicked) { showFrame(kOverlayButtons, kButtonQuitPushed, true); getSound()->clearStatus(); getSound()->updateQueue(); getSound()->playSound(kEntityPlayer, "LIB046"); // FIXME uncomment when sound queue is properly implemented /*while (getSound()->isBuffered("LIB046")) getSound()->updateQueue();*/ getFlags()->shouldRedraw = false; Engine::quitGame(); return false; } else { showFrame(kOverlayButtons, kButtonQuit, true); } break; ////////////////////////////////////////////////////////////////////////// case kMenuCase4: if (clicked) _index = 0; // fall down to kMenuContinue ////////////////////////////////////////////////////////////////////////// case kMenuContinue: { if (hasTimeDelta()) { hideOverlays(); break; } // Determine the proper CD archive ArchiveIndex cd = kArchiveCd1; if (getProgress().chapter > kChapter1) cd = (getProgress().chapter > kChapter3) ? kArchiveCd3 : kArchiveCd2; // Show tooltips & buttons to start a game, continue a game or load the proper cd if (ResourceManager::isArchivePresent(cd)) { if (_isGameStarted) { showFrame(kOverlayEggButtons, kButtonContinue, true); if (_lastIndex == _index) { showFrame(kOverlayTooltip, getSaveLoad()->isGameFinished(_index, _lastIndex) ? kTooltipViewGameEnding : kTooltipContinueGame, true); } else { showFrame(kOverlayTooltip, kTooltipContinueRewoundGame, true); } } else { showFrame(kOverlayEggButtons, kButtonShield, true); showFrame(kOverlayTooltip, kTooltipPlayNewGame, true); } } else { showFrame(kOverlayEggButtons, -1, true); showFrame(kOverlayTooltip, cd - 1, true); } if (!clicked) break; // Try loading the archive file if (!_engine->getResourceManager()->loadArchive(cd)) break; // Load the train data file and setup game getScenes()->loadSceneDataFile(cd); showFrame(kOverlayTooltip, -1, true); getSound()->playSound(kEntityPlayer, "LIB046"); // Setup new game getSavePoints()->reset(); setLogicEventHandlers(); if (_index) { getSound()->processEntry(SoundManager::kSoundType11); } else { if (!getFlags()->mouseRightClick) { getScenes()->loadScene((SceneIndex)(5 * _gameId + 3)); if (!getFlags()->mouseRightClick) { getScenes()->loadScene((SceneIndex)(5 * _gameId + 4)); if (!getFlags()->mouseRightClick) { getScenes()->loadScene((SceneIndex)(5 * _gameId + 5)); if (!getFlags()->mouseRightClick) { getSound()->processEntry(SoundManager::kSoundType11); // Show intro Animation animation; if (animation.load(getArchive("1601.nis"))) animation.play(); getEvent(kEventIntro) = 1; } } } } if (!getEvent(kEventIntro)) { getEvent(kEventIntro) = 1; getSound()->processEntry(SoundManager::kSoundType11); } } // Setup game getFlags()->isGameRunning = true; startGame(); if (!_isShowingMenu) getInventory()->show(); return false; } ////////////////////////////////////////////////////////////////////////// case kMenuSwitchSaveGame: if (hasTimeDelta()) { hideOverlays(); break; } if (clicked) { showFrame(kOverlayAcorn, 1, true); showFrame(kOverlayTooltip, -1, true); getSound()->playSound(kEntityPlayer, "LIB047"); // Setup new menu screen switchGame(); setup(); // Set fight state to 0 getFight()->resetState(); return true; } // TODO Check for flag showFrame(kOverlayAcorn, 0, true); if (_isGameStarted) { showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true); break; } if (_gameId == kGameGold) { showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true); break; } if (!SaveLoad::isSavegameValid(getNextGameId())) { showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true); break; } // Stupid tooltips ids are not in order, so we can't just increment them... switch(_gameId) { default: break; case kGameBlue: showFrame(kOverlayTooltip, kTooltipSwitchRedGame, true); break; case kGameRed: showFrame(kOverlayTooltip, kTooltipSwitchGreenGame, true); break; case kGameGreen: showFrame(kOverlayTooltip, kTooltipSwitchPurpleGame, true); break; case kGamePurple: showFrame(kOverlayTooltip, kTooltipSwitchTealGame, true); break; case kGameTeal: showFrame(kOverlayTooltip, kTooltipSwitchGoldGame, true); break; } break; ////////////////////////////////////////////////////////////////////////// case kMenuRewindGame: if (!_index || _currentTime < _time) { hideOverlays(); break; } if (clicked) { if (hasTimeDelta()) _handleTimeDelta = false; showFrame(kOverlayEggButtons, kButtonRewindPushed, true); showFrame(kOverlayTooltip, -1, true); getSound()->playSound(kEntityPlayer, "LIB046"); rewindTime(); _handleTimeDelta = false; } else { showFrame(kOverlayEggButtons, kButtonRewind, true); showFrame(kOverlayTooltip, kTooltipRewind, true); } break; ////////////////////////////////////////////////////////////////////////// case kMenuForwardGame: if (_lastIndex <= _index || _currentTime > _time) { hideOverlays(); break; } if (clicked) { if (hasTimeDelta()) _handleTimeDelta = false; showFrame(kOverlayEggButtons, kButtonForwardPushed, true); showFrame(kOverlayTooltip, -1, true); getSound()->playSound(kEntityPlayer, "LIB046"); forwardTime(); _handleTimeDelta = false; } else { showFrame(kOverlayEggButtons, kButtonForward, true); showFrame(kOverlayTooltip, kTooltipFastForward, true); } break; ////////////////////////////////////////////////////////////////////////// case kMenuParis: moveToCity(kParis, clicked); break; ////////////////////////////////////////////////////////////////////////// case kMenuStrasBourg: moveToCity(kStrasbourg, clicked); break; ////////////////////////////////////////////////////////////////////////// case kMenuMunich: moveToCity(kMunich, clicked); break; ////////////////////////////////////////////////////////////////////////// case kMenuVienna: moveToCity(kVienna, clicked); break; ////////////////////////////////////////////////////////////////////////// case kMenuBudapest: moveToCity(kBudapest, clicked); break; ////////////////////////////////////////////////////////////////////////// case kMenuBelgrade: moveToCity(kBelgrade, clicked); break; ////////////////////////////////////////////////////////////////////////// case kMenuConstantinople: moveToCity(kConstantinople, clicked); break; ////////////////////////////////////////////////////////////////////////// case kMenuDecreaseVolume: if (hasTimeDelta()) { hideOverlays(); break; } // Cannot decrease volume further if (getVolume() == 0) { showFrame(kOverlayButtons, kButtonVolume, true); showFrame(kOverlayTooltip, -1, true); break; } showFrame(kOverlayTooltip, kTooltipVolumeDown, true); // Show highlight on button & adjust volume if needed if (clicked) { showFrame(kOverlayButtons, kButtonVolumeDownPushed, true); getSound()->playSound(kEntityPlayer, "LIB046"); setVolume(getVolume() - 1); getSaveLoad()->saveVolumeBrightness(); uint32 nextFrameCount = getFrameCount() + 15; while (nextFrameCount > getFrameCount()) { _engine->pollEvents(); getSound()->updateQueue(); } } else { showFrame(kOverlayButtons, kButtonVolumeDown, true); } break; ////////////////////////////////////////////////////////////////////////// case kMenuIncreaseVolume: if (hasTimeDelta()) { hideOverlays(); break; } // Cannot increase volume further if (getVolume() >= 7) { showFrame(kOverlayButtons, kButtonVolume, true); showFrame(kOverlayTooltip, -1, true); break; } showFrame(kOverlayTooltip, kTooltipVolumeUp, true); // Show highlight on button & adjust volume if needed if (clicked) { showFrame(kOverlayButtons, kButtonVolumeUpPushed, true); getSound()->playSound(kEntityPlayer, "LIB046"); setVolume(getVolume() + 1); getSaveLoad()->saveVolumeBrightness(); uint32 nextFrameCount = getFrameCount() + 15; while (nextFrameCount > getFrameCount()) { _engine->pollEvents(); getSound()->updateQueue(); } } else { showFrame(kOverlayButtons, kButtonVolumeUp, true); } break; ////////////////////////////////////////////////////////////////////////// case kMenuDecreaseBrightness: if (hasTimeDelta()) { hideOverlays(); break; } // Cannot increase brightness further if (getBrightness() == 0) { showFrame(kOverlayButtons, kButtonBrightness, true); showFrame(kOverlayTooltip, -1, true); break; } showFrame(kOverlayTooltip, kTooltipBrightnessDown, true); // Show highlight on button & adjust brightness if needed if (clicked) { showFrame(kOverlayButtons, kButtonBrightnessDownPushed, true); getSound()->playSound(kEntityPlayer, "LIB046"); setBrightness(getBrightness() - 1); getSaveLoad()->saveVolumeBrightness(); // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager) _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true); showFrame(kOverlayTooltip, kTooltipBrightnessDown, false); showFrame(kOverlayButtons, kButtonBrightnessDownPushed, false); } else { showFrame(kOverlayButtons, kButtonBrightnessDown, true); } break; ////////////////////////////////////////////////////////////////////////// case kMenuIncreaseBrightness: if (hasTimeDelta()) { hideOverlays(); break; } // Cannot increase brightness further if (getBrightness() >= 6) { showFrame(kOverlayButtons, kButtonBrightness, true); showFrame(kOverlayTooltip, -1, true); break; } showFrame(kOverlayTooltip, kTooltipBrightnessUp, true); // Show highlight on button & adjust brightness if needed if (clicked) { showFrame(kOverlayButtons, kButtonBrightnessUpPushed, true); getSound()->playSound(kEntityPlayer, "LIB046"); setBrightness(getBrightness() + 1); getSaveLoad()->saveVolumeBrightness(); // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager) _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true); showFrame(kOverlayTooltip, kTooltipBrightnessUp, false); showFrame(kOverlayButtons, kButtonBrightnessUpPushed, false); } else { showFrame(kOverlayButtons, kButtonBrightnessUp, true); } break; } return true; }
void Logic::eventMouse(const Common::Event &ev) { bool hotspotHandled = false; // Reset mouse flags getFlags()->mouseLeftClick = false; getFlags()->mouseRightClick = false; // Process event flags if (ev.type == Common::EVENT_LBUTTONDOWN) { if (getFlags()->frameInterval) _ignoreFrameInterval = false; getFlags()->frameInterval = false; } if (getFlags()->flag_0) { if (ev.type == Common::EVENT_LBUTTONDOWN || ev.type == Common::EVENT_RBUTTONDOWN) { getFlags()->flag_0 = false; getFlags()->shouldRedraw = true; updateCursor(true); getFlags()->frameInterval = true; } return; } if (_ignoreFrameInterval && getScenes()->checkCurrentPosition(true) && _engine->getCursor()->getStyle() == kCursorForward) { getFlags()->shouldRedraw = false; getFlags()->flag_0 = true; return; } // Update coordinates getGameState()->setCoordinates(ev.mouse); // Handle inventory getInventory()->handleMouseEvent(ev); // Stop processing is inside the menu if (getMenu()->isShown()) return; // Handle whistle case if (getInventory()->getSelectedItem() == kItemWhistle && !getProgress().isEggOpen && !getEntities()->isPlayerPosition(kCarGreenSleeping, 59) && !getEntities()->isPlayerPosition(kCarGreenSleeping, 76) && !getInventory()->isPortraitHighlighted() && !getInventory()->isOpened() && !getInventory()->isEggHighlighted() && !getInventory()->isMagnifierInUse()) { // Update cursor _engine->getCursor()->setStyle(getInventory()->get(kItemWhistle)->cursor); // Check if clicked if (ev.type == Common::EVENT_LBUTTONUP && !getSoundQueue()->isBuffered("LIB045")) { getSound()->playSoundEvent(kEntityPlayer, 45); if (getEntities()->isPlayerPosition(kCarGreenSleeping, 26) || getEntities()->isPlayerPosition(kCarGreenSleeping, 25) || getEntities()->isPlayerPosition(kCarGreenSleeping, 23)) { getSavePoints()->push(kEntityPlayer, kEntityMertens, kAction226078300); } else if (getEntities()->isPlayerPosition(kCarRedSleeping, 26) || getEntities()->isPlayerPosition(kCarRedSleeping, 25) || getEntities()->isPlayerPosition(kCarRedSleeping, 23)) { getSavePoints()->push(kEntityPlayer, kEntityCoudert, kAction226078300); } if (!getState()->sceneUseBackup) getInventory()->unselectItem(); } REDRAW_CURSOR() }
////////////////////////////////////////////////////////////////////////// // Entries ////////////////////////////////////////////////////////////////////////// void SaveLoad::writeEntry(SavegameType type, EntityIndex entity, uint32 value) { #define WRITE_ENTRY(name, func, val) { \ uint32 _prevPosition = (uint32)_savegame->pos(); \ func; \ uint32 _count = (uint32)_savegame->pos() - _prevPosition; \ debugC(kLastExpressDebugSavegame, "Savegame: Writing " #name ": %d bytes", _count); \ if (_count != val)\ error("SaveLoad::writeEntry: Number of bytes written (%d) differ from expected count (%d)", _count, val); \ } if (!_savegame) error("SaveLoad::writeEntry: savegame stream is invalid"); SavegameEntryHeader header; header.type = type; header.time = (uint32)getState()->time; header.chapter = getProgress().chapter; header.value = value; // Save position uint32 originalPosition = (uint32)_savegame->pos(); // Write header Common::Serializer ser(NULL, _savegame); header.saveLoadWithSerializer(ser); // Write game data WRITE_ENTRY("entity index", ser.syncAsUint32LE(entity), 4); WRITE_ENTRY("state", getState()->saveLoadWithSerializer(ser), 4 + 4 + 4 + 4 + 1 + 4 + 4); WRITE_ENTRY("selected item", getInventory()->saveSelectedItem(ser), 4); WRITE_ENTRY("positions", getEntities()->savePositions(ser), 4 * 1000); WRITE_ENTRY("compartments", getEntities()->saveCompartments(ser), 4 * 16 * 2); WRITE_ENTRY("progress", getProgress().saveLoadWithSerializer(ser), 4 * 128); WRITE_ENTRY("events", getState()->syncEvents(ser), 512); WRITE_ENTRY("inventory", getInventory()->saveLoadWithSerializer(ser), 7 * 32); WRITE_ENTRY("objects", getObjects()->saveLoadWithSerializer(ser), 5 * 128); WRITE_ENTRY("entities", getEntities()->saveLoadWithSerializer(ser), 1262 * 40); WRITE_ENTRY("sound", getSound()->saveLoadWithSerializer(ser), 3 * 4 + getSound()->count() * 64); WRITE_ENTRY("savepoints", getSavePoints()->saveLoadWithSerializer(ser), 128 * 16 + 4 + getSavePoints()->count() * 16); header.offset = (uint32)_savegame->pos() - (originalPosition + 32); // Add padding if necessary while (header.offset & 0xF) { _savegame->writeByte(0); header.offset++; } // Save end position uint32 endPosition = (uint32)_savegame->pos(); // Validate entry header if (!header.isValid()) error("SaveLoad::writeEntry: entry header is invalid"); // Save the header with the updated info _savegame->seek(originalPosition); header.saveLoadWithSerializer(ser); // Move back to the end of the entry _savegame->seek(endPosition); }