/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "common/config-manager.h" #include "common/debug-channels.h" #include "common/events.h" #include "common/scummsys.h" #include "common/system.h" #include "common/compression/unzip.h" #include "common/translation.h" #include "engines/util.h" #include "darkseed/darkseed.h" #include "darkseed/console.h" #include "darkseed/detection.h" #include "darkseed/debugconsole.h" #include "darkseed/nsp.h" #include "darkseed/pal.h" #include "darkseed/pic.h" #include "darkseed/room.h" #include "darkseed/kofont.h" namespace Darkseed { DarkseedEngine *g_engine; DarkseedEngine::DarkseedEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _randomSource("Darkseed") { g_engine = this; } DarkseedEngine::~DarkseedEngine() { delete _screen; delete _sound; delete _menu; } uint32 DarkseedEngine::getFeatures() const { return _gameDescription->flags; } Common::String DarkseedEngine::getGameId() const { return _gameDescription->gameId; } Common::Error DarkseedEngine::run() { // Initialise engine data for the game if (getLanguage() == Common::ZH_ANY) { // currently only the Chinese version requires external bundled data. Common::Archive *archive = Common::makeZipArchive("darkseed.dat"); if (!archive) { GUIErrorMessage(_("Unable to locate the darkseed.dat engine data file.")); return Common::kPathDoesNotExist; } SearchMan.add("darkseed.dat", archive); } initGraphics(640, 350); _canSaveGame = false; _sound = new Sound(_mixer); if (_sound->init() > 0) { return Common::kAudioDeviceInitFailed; } _screen = new Graphics::Screen(); _tosText = new TosText(); _tosText->load(); _objectVar.loadObjectNames(); _console = new Console(_tosText, _sound); _menu = new Menu(); _player = new Player(); _useCode = new UseCode(_console, _player, _objectVar, _inventory); _animation = new Animation(_player, _objectVar); // Set the engine's debugger console setDebugger(new DebugConsole(_tosText)); _frame.load("cframe.pic"); _baseSprites.load("cbase.nsp"); _cursor.updatePosition(0x140, 0xaf); _cursor.setCursorType(Pointer); _cursor.showCursor(true); _player->_position.x = 0x87; _player->_position.y = 0x5b; _player->_direction = 1; _player->_frameIdx = 0; _room = new Room(isDosDemo() ? 4 : 0); // If a savegame was selected from the launcher, load it int saveSlot = ConfMan.getInt("save_slot"); if (isDosDemo()) { newGame(); } else if (saveSlot != -1) { (void)loadGameState(saveSlot); } else { _cutscene.play('I'); } while (!shouldQuit()) { gameLoop(); _restartGame = false; if (!shouldQuit()) { _cutscene.play('I'); } } delete _room; delete _player; return Common::kNoError; } Common::Error DarkseedEngine::syncGame(Common::Serializer &s) { if (_room == nullptr) { _room = new Room(0); } if (_objectVar.sync(s).getCode() != Common::kNoError) { error("Failed to sync objects"); } if (_inventory.sync(s).getCode() != Common::kNoError) { error("Failed to sync inventory"); } s.syncAsUint32LE(_currentTimeInSeconds); s.syncAsByte(_currentDay); s.syncAsByte(_room->_roomNumber); s.syncAsByte(_previousRoomNumber); s.syncAsSint16LE(_player->_position.x); s.syncAsSint16LE(_player->_position.y); if (_sound->sync(s).getCode() != Common::kNoError) { error("Failed to sync sound"); } return Common::kNoError; } void DarkseedEngine::fadeOut() { _fadeDirection = FadeDirection::OUT; _fadeStepCounter = 0; _fadeTempPalette.loadFromScreen(); } void DarkseedEngine::fadeIn(const Pal &palette) { _fadeDirection = FadeDirection::IN; _fadeStepCounter = 0; _fadeTargetPalette.load(palette); _fadeTempPalette.clear(); _fadeTempPalette.installPalette(); } bool DarkseedEngine::fadeStep() { if (_fadeStepCounter < 64) { _fadeTempPalette.updatePalette(_fadeDirection == FadeDirection::OUT ? -4 : 4, _fadeTargetPalette); _fadeStepCounter++; } return _fadeStepCounter < 64; } void DarkseedEngine::gameLoop() { while (!shouldQuit() && !_restartGame) { updateEvents(); if (_redrawFrame) { _redrawFrame = false; _screen->makeAllDirty(); _frame.draw(); } if (_fullscreenPic) { if (_isLeftMouseClicked || _isRightMouseClicked) { _isRightMouseClicked = false; _isLeftMouseClicked = false; removeFullscreenPic(); } } _counter_2c85_888b = (_counter_2c85_888b + 1) & 0xff; if (_cutscene.isPlaying()) { _cutscene.update(); } else if (_systemTimerCounter == 5) { if (_objectVar[1] != 0) { if (_room->_roomNumber == 30) { if (!_inventory.hasObject(18)) { _objectVar[1]--; } } else { _objectVar[1]--; } } closeShops(); if (_room->_roomNumber == 57 && _previousRoomNumber == 54) { if (_objectVar.getMoveObjectRoom(28) == 255) { if (_objectVar[56] == 4) { playSound(21, 5, -1); } if (_objectVar[56] == 6) { _sound->playMusic(MusicId::kDth); playSound(0, 6, -1); _animation->stuffPlayer(); } } else { if (_objectVar[56] > 0) { _animation->dCopAnim(); changeToRoom(59, true); _player->_position = {320, 200}; _player->updateSprite(); _inventory.gotoJailLogic(); playSound(0, 6, -1); } } } if (_currentTimeInSeconds > 35999 && _currentTimeInSeconds < 36005 && ((_currentDay == 1 || (_currentDay == 2 && _objectVar[6] != 0)) || (_currentDay == 3 && _objectVar[29] != 0))) { _objectVar.setObjectRunningCode(140, 1); // package delivered. } if (_room->_roomNumber == 52 && _objectVar[79] == 0) { _objectVar.setObjectRunningCode(79, 1); } if (_room->_roomNumber == 55) { _objectVar.setObjectRunningCode(58, 1); } int prevTime = _currentTimeInSeconds; if (_currentTimeInSeconds * 2 != _fttime) { _fttime = _currentTimeInSeconds * 2; } if (!isDosDemo()) { if (!_room->isGiger()) { _fttime += 4; } else { _fttime += 9; } } _currentTimeInSeconds = _fttime / 2; if ((_currentTimeInSeconds == 46800 || _currentTimeInSeconds == 46801) && _currentDay == 2 && _room->_roomNumber != 34) { _objectVar[62] = 0; } if (_currentDay == 2 && _currentTimeInSeconds > 64799 && prevTime < 64800 && _objectVar[141] == 4) { initDelbertAtSide(); } if (_currentDay == 1 && _currentTimeInSeconds == 64800 && _room->_roomNumber != 16) { _objectVar.setMoveObjectRoom(7, 253); // remove scotch from shop. } if (_timeAdvanceEventSelected && _currentTimeInSeconds < 79200 && !_animation->_isPlayingAnimation_maybe && !_player->_isAutoWalkingToBed && !_player->_heroWaiting) { _timeAdvanceEventSelected = false; if (((_room->_roomNumber == 30) || ((0 < _objectVar[141] && (_objectVar[141] < 4)))) || (((_room->_roomNumber == 31 || (_room->_roomNumber == 32)) && (((((_objectVar[141] == 9 || (_objectVar[141] == 6)) || (_objectVar[141] == 8)) || ((_objectVar[141] == 7 || (_objectVar[141] == 12)))) || ((_objectVar[141] == 10 || (_objectVar[141] == 5)))))))) { if (_room->_roomNumber == 30) { _console->printTosText(943); } } else { _currentTimeInSeconds += 3600; _currentTimeInSeconds -= (_currentTimeInSeconds % 3600); _console->printTosText(942); if (_currentDay == 2 && _currentTimeInSeconds == 64800 && _objectVar[141] == 4) { initDelbertAtSide(); } } } if ((_room->_roomNumber < 10 || _room->_roomNumber == 61 || _room->_roomNumber == 62) && _currentTimeInSeconds % 3600 == 0) { if (_room->_roomNumber == 7) { playSound(45, 5, -1); } else { playSound(46, 5, -1); } } _room->darkenSky(); if (_currentDay < 3 && _currentTimeInSeconds > 79199 && !_player->_isAutoWalkingToBed && (_room->_roomNumber < 10 || _room->_roomNumber == 13 || _room->_roomNumber == 61 || _room->_roomNumber == 62)) { _player->_walkToSequence = false; _player->_actionToPerform = false; _player->_isAutoWalkingToBed = true; _player->setPlayerTowardsBedroom(); _console->printTosText(944); } if (_currentTimeInSeconds > 79199 && !_player->_isAutoWalkingToBed) { if (_room->isOutside() && _room->_roomNumber != 30) { _inventory.endOfDayOutsideLogic(); } if (!_animation->_isPlayingAnimation_maybe) { if (_room->_roomNumber == 30) { gotoSleepInJail(); } else { if (_room->_roomNumber != 10) { // TODO release memory. } // makeroomname(); TODO // GetLocationSprites((int)&_file_name); if (!_room->isGiger()) { if (_currentDay == 3) { _console->printTosText(749); } _player->loadAnimations("cliedown.nsp"); } else { _player->loadAnimations("gliedown.nsp"); } _animation->setupOtherNspAnimation(0, 3); } } } if (_room->_roomNumber == 30 && _objectVar[1] == 0 && (_animation->_otherNspAnimationType_maybe != 40 || !_animation->_isPlayingAnimation_maybe || _currentTimeInSeconds > 79199)) { gotoSleepInJail(); } updateDisplay(); // Aka serviceRoom() _screen->addDirtyRect({{0x45, 0x28}, 501, 200}); if (!_cutscene.isPlaying()) { if (_fullscreenPic) { _fullscreenPic->draw(0x45, 0x28); } else { _room->draw(); _inventory.draw(); _sprites.drawSprites(); _player->draw(); _console->draw(); } } // if (((*(int *)&_CursorX < 70) || (570 < *(int *)&_CursorX)) && (*(int *)&_DrawCursorNum < 90)) { TODO do we need this restriction? // zeroMouseButtons(); // } if (_player->_isAutoWalkingToBed || (_room->_roomNumber == 10 && _player->_position.x < 369 && ((_currentDay == 3 && _currentTimeInSeconds > 43200) || _objectVar[88] != 0))) { zeroMouseButtons(); } if ((_objectVar[141] > 0 && _objectVar[141] < 4) || _objectVar[141] == 9 || _player->_heroWaiting || _objectVar[141] == 10 || _objectVar[141] == 8) { zeroMouseButtons(); } if (_room->_roomNumber == 32 && _currentDay == 2 && _currentTimeInSeconds > 64799 && _currentTimeInSeconds < 68401 && (_objectVar[141] == 5 || _objectVar[141] == 6 || _objectVar[141] == 4 || _objectVar[141] == 12) && !_animation->_isPlayingAnimation_maybe) { zeroMouseButtons(); } updateHeadache(); handleInput(); _isRightMouseClicked = false; _isLeftMouseClicked = false; } _room->update(); _screen->update(); wait(); } } void DarkseedEngine::updateEvents() { Common::Event event; // _isRightMouseClicked = false; // _isLeftMouseClicked = false; while (g_system->getEventManager()->pollEvent(event)) { switch (event.type) { case Common::EVENT_MOUSEMOVE: _cursor.updatePosition(event.mouse.x, event.mouse.y); break; case Common::EVENT_KEYDOWN: _lastKeyPressed = event.kbd.keycode; if (isDosDemo() && _lastKeyPressed == Common::KEYCODE_q) { quitGame(); } break; case Common::EVENT_CUSTOM_ENGINE_ACTION_START: if (event.customType == kDarkseedActionSelect) { _isLeftMouseClicked = true; } else if (event.customType == kDarkseedActionChangeCommand) { _isRightMouseClicked = true; } else if (event.customType == kDarkseedActionTimeAdvance) { if (!isDosDemo()) { _timeAdvanceEventSelected = true; } } else if (event.customType == kDarkseedActionQuit) { quitGame(); } break; default: break; } } } void DarkseedEngine::wait() { g_system->delayMillis(16); _systemTimerCounter++; if (_systemTimerCounter == 6) { _systemTimerCounter = 0; } } void DarkseedEngine::syncSoundSettings() { Engine::syncSoundSettings(); _sound->syncSoundSettings(); } void DarkseedEngine::pauseEngineIntern(bool pause) { _sound->pauseMusic(pause); Engine::pauseEngineIntern(pause); } static constexpr uint8 walkToDirTbl[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x01, 0x04, 0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x00, 0x03, 0x01, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04, 0x00, 0x04, 0x01, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x04, 0x03, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x01, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x01, 0x04, 0x04, 0x03, 0x04, 0x04, 0x00, 0x01, 0x00, 0x04, 0x04, 0x04, 0x03, 0x04, 0x01, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x04, 0x04, 0x04, 0x01, 0x04, 0x03, 0x00, 0x04 }; static constexpr int16 walkToXTbl[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 253, 0, 0, 0, 0, 464, 0, 405, 325, 325, 325, 0, 505, 0, 0, 0, 0, 0, 0, 0, 0, 489, 0, 340, 300, 340, 0, 0, 0, 218, 0, 0, 391, 0, 308, 0, 0, 0, 484, 0, 0, 0, 0, 288, 288, 288, 0, 0, 0, 0, 0, 0, 0, 0, 437, 0, 0, 437, 0, 0, 0, 0, 0, 0, 338, 480, 159, 316, 387, 390, 466, 218, 331, 316, 230, 346, 0, 153, 534, 0, 156, 0, 0, 0, 0, 0, 0, 297, 0, 0, 0, 0, 201, 0, 457, 327, 0, 0, 0, 0, 223, 0, 0, 0, 477, 0, 0, 202, 0, 0, 221, 464, 369, 0, 0, 0, 179, 0, 142, 0, 156, 293, 359, 0, 260, 463, 269, 208, 156, 0, 0, 0, 0, 251, 0, 357, 0, 428, 0, 357, 0, 0, 0, 0, 0, 0, 0, 210, 244, 212, 202, 348, 0, 0, 0, 0, 0, 389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 465, 0, 0, 0, 458, 0, 210, 260, 0 }; static constexpr uint8 walkToYTbl[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0xaa, 0xe1, 0xe1, 0xe1, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x00, 0xd4, 0xb7, 0xd9, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0xd3, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcd, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0xdf, 0xbc, 0xa2, 0xa0, 0xa1, 0xaa, 0xdd, 0xcd, 0xd1, 0xd8, 0xe2, 0x00, 0xd7, 0xd5, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0xbd, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0xee, 0x00, 0x00, 0xc5, 0xd9, 0xd8, 0x00, 0x00, 0x00, 0xcc, 0x00, 0xd8, 0x00, 0xb6, 0xc6, 0xc8, 0x00, 0xd3, 0xba, 0xd2, 0xd2, 0xaa, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0xd6, 0x00, 0xe0, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xb9, 0xd7, 0xcf, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xec, 0x00, 0xe8, 0xd3, 0x00 }; void DarkseedEngine::handleInput() { // FUN_2022_762b_handles_mouse_click_action int currentRoomNumber = _room->_roomNumber; if (_player->_isAutoWalkingToBed && currentRoomNumber == 0 && _player->isAtPosition(0xdf, 0xbe)) { _player->_isAutoWalkingToBed = false; _currentTimeInSeconds = 0x7e90; _player->loadAnimations("bedsleep.nsp"); _animation->setupOtherNspAnimation(1, 5); } if (_animation->_isPlayingAnimation_maybe) { _animation->updateAnimation(); if (!_animation->_isPlayingAnimation_maybe && _player->_isAutoWalkingToBed) { _player->setPlayerTowardsBedroom(); } return; } if (_player->_playerIsChangingDirection) { // turn player around. _player->_playerSpriteWalkIndex_maybe = (int16)((_player->_playerSpriteWalkIndex_maybe + _player->_playerWalkFrameDeltaOffset) & 7); if (_player->_playerSpriteWalkIndex_maybe == _player->_playerNewFacingDirection_maybe) { _player->_playerIsChangingDirection = false; _player->_direction = _player->_playerNewFacingDirection_maybe / 2; } _player->updateSprite(); return; } if (currentRoomNumber == 0x39 && _previousRoomNumber == 0x36) { _player->updateSprite(); return; } if (_player->isAtWalkTarget() && !_player->_heroMoving) { _player->updateSprite(); } else { if (_counter_2c85_888b >= 0 && !_player->isAtWalkTarget()) { _counter_2c85_888b = 0; _player->_playerWalkFrameIdx = (_player->_playerWalkFrameIdx + 1) % 8; if ((_player->_playerWalkFrameIdx == 0 || _player->_playerWalkFrameIdx == 4) && currentRoomNumber != 0x22 && currentRoomNumber != 0x13 && currentRoomNumber != 0x14 && currentRoomNumber != 0x15 && currentRoomNumber != 16) { //TODO // FUN_1208_0dac_sound_related(0x5c,CONCAT11((char)(uVar7 >> 8),5)); } } _player->updateSprite(); } if (_isLeftMouseClicked && _cursor.getY() > 0x28 && !_player->_actionToPerform) { // prevLeftMouseButtonState == 0 && if (_actionMode == kPointerAction) { _player->calculateWalkTarget(); _player->playerFaceWalkTarget(); } else { int roomObjIdx = _room->getObjectUnderCursor(); if (roomObjIdx != -1) { // 2022:77ce // TODO walk player to object. _player->_walkToSequence = true; _player->_walkToSequencePoint = _cursor.getPosition(); _player->_sequenceRotation = -1; Common::Point currentCursorPos = _cursor.getPosition(); // TODO check this logic with original it looks like there might be a buffer overrun // in the original logic when roomObjIdx >= 30 eg package. int objNum = roomObjIdx >= 30 ? 0 : _room->_roomObj[roomObjIdx].objNum; if (walkToDirTbl[objNum] != 4) { _player->_sequenceRotation = walkToDirTbl[objNum]; _cursor.updatePosition(walkToXTbl[objNum], walkToYTbl[objNum]); } if (objNum == 142 && _room->_roomNumber == 2) { _player->_sequenceRotation = 0; _cursor.updatePosition(347, 189); } else if (objNum == 53 && _room->_roomNumber == 15) { _player->_sequenceRotation = 0; _cursor.updatePosition(369, 216); } else if (objNum == 114) { if (_cursor.getX() < 321) { _player->_sequenceRotation = 3; _cursor.updatePosition(169, 178); } else { _player->_sequenceRotation = 1; _cursor.updatePosition(362, 198); } } else if (objNum == 189 || (objNum == 64 && _room->_roomNumber == 30)) { _player->_sequenceRotation = 1; _cursor.updatePosition(405, 208); } else if (objNum == 50 || objNum == 85 || (objNum >= 163 && objNum <= 168)) { _player->_sequenceRotation = 3; _cursor.updatePosition(228, 211); } else if (objNum == 51 || objNum == 187) { _player->_sequenceRotation = 1; _cursor.updatePosition(380, 211); } else if (objNum == 116 && _actionMode == kUseStickAction) { _player->_sequenceRotation = 1; _cursor.updatePosition(285, 233); } else if (objNum == 137) { _player->_sequenceRotation = 1; if (_actionMode == kUseHammerAction) { _cursor.updatePosition(354, 175); } else { _cursor.updatePosition(409, 173); } } else if (objNum == 112 || objNum == 111) { _player->_sequenceRotation = 1; _cursor.updatePosition(464, 191); } else if (objNum == 138 || objNum == 7 || objNum == 152) { _player->_sequenceRotation = 1; _cursor.updatePosition(292, 208); } else if (objNum == 22 || objNum == 42 || (objNum == 35 && _objectVar[22] < 2 && _cursor.getY() > 40)) { _player->_sequenceRotation = 1; if (_objectVar[22] == 0 || _objectVar[22] == 1) { _cursor.updatePosition(437, 203); } if (_objectVar[22] == 2) { _cursor.updatePosition(427, 196); } if (_objectVar[22] > 2) { _cursor.updatePosition(394, 175); } } if (objNum == 102 && _objectVar[23] != 0 && _actionMode == kHandAction) { _player->_sequenceRotation = 0; _cursor.updatePosition(331, 195); } else if (objNum < 104 || objNum > 108) { if (objNum == 78) { if (_room->_roomNumber == 2) { _player->_sequenceRotation = 3; _cursor.updatePosition(152, 239); } else { _player->_sequenceRotation = 1; _cursor.updatePosition(497, 220); } } else if (objNum == 59) { if (_room->_roomNumber == 3) { _player->_sequenceRotation = 3; _cursor.updatePosition(145, 239); } else { _player->_sequenceRotation = 1; _cursor.updatePosition(520, 229); } } } else { _player->_sequenceRotation = 3; _cursor.updatePosition(_room->_roomObj[roomObjIdx].xOffset + 30, 206); } if (_room->_roomNumber == 34 || (_room->_roomNumber > 18 && _room->_roomNumber < 24)) { _player->_walkTarget = _player->_position; } else if (_cursor.getPosition() != _player->_position) { _player->calculateWalkTarget(); } _cursor.updatePosition(currentCursorPos.x, currentCursorPos.y); _player->playerFaceWalkTarget(); _player->_actionToPerform = true; } } } int xDistToTarget = ABS(_player->_walkTarget.x - _player->_position.x); int yDistToTarget = ABS(_player->_walkTarget.y - _player->_position.y); if (_isRightMouseClicked && !_player->_actionToPerform) { if (_actionMode == kLookAction) { _actionMode = kPointerAction; } else if (_actionMode == kPointerAction) { _actionMode = kHandAction; } else if (_actionMode == kHandAction) { _actionMode = kLookAction; } else { _actionMode = kPointerAction; } _cursor.setCursorType((CursorType)_actionMode); } if (_player->isAtWalkTarget() && _player->_heroMoving && _player->_walkPathIndex != -1) { _player->walkToNextConnector(); } if (_isLeftMouseClicked && _cursor.getY() < 41) { _inventory.handleClick(); return; } _room->calculateScaledSpriteDimensions(_player->getWidth(), _player->getHeight(), _player->_position.y); if (_player->isAtWalkTarget() && _player->_heroMoving && !_player->_actionToPerform) { if (_useDoorTarget) { _player->changeDirection(_player->_direction, _targetPlayerDirection); _useDoorTarget = false; _doorEnabled = true; return; } _player->_heroMoving = false; if (_doorEnabled) { for (unsigned int i = 0; i < _room->_room1.size(); i++) { RoomExit &roomExit = _room->_room1[i]; if (roomExit.roomNumber != 0xff && roomExit.x < _scaledSpriteWidth / 2 + _player->_position.x && _player->_position.x - _scaledSpriteWidth / 2 < roomExit.x + roomExit.width && roomExit.y < _player->_position.y && _player->_position.y - _scaledSpriteHeight < roomExit.y + roomExit.height && roomExit.direction == _player->_direction) { bool bVar = true; if (currentRoomNumber == 64 && roomExit.roomNumber == 64) { bVar = false; _console->printTosText(703); } if (currentRoomNumber == 67 && roomExit.roomNumber == 0) { bVar = false; _console->printTosText(902); } if ((currentRoomNumber == 59 && _objectVar[190] < 2) || (currentRoomNumber == 61 && _objectVar[22] < 3 && roomExit.roomNumber == 13) || (currentRoomNumber == 7 && roomExit.roomNumber == 38 && _objectVar[137] == 0) || (currentRoomNumber == 46 && roomExit.roomNumber == 60 && _objectVar[57] == 1) || (currentRoomNumber == 7 && roomExit.roomNumber == 38 && _objectVar[57] == 1) || (currentRoomNumber == 13 && roomExit.roomNumber == 31 && _objectVar[23] != 1) || (currentRoomNumber == 2 && roomExit.roomNumber == 0 && _objectVar[78] != 2) || (currentRoomNumber == 0 && roomExit.roomNumber == 2 && _objectVar[78] != 2) || (currentRoomNumber == 32 && roomExit.roomNumber == 13 && _objectVar[23] != 1) || (currentRoomNumber == 13 && roomExit.roomNumber == 32 && _objectVar[23] != 1) || (currentRoomNumber == 39 && roomExit.roomNumber == 46 && _objectVar[117] == 0) || (currentRoomNumber == 3 && roomExit.roomNumber == 9 && _objectVar[59] != 2) || (currentRoomNumber == 9 && roomExit.roomNumber == 3 && _objectVar[59] != 2)) { bVar = false; } if (_currentTimeInSeconds > 64800 && ((currentRoomNumber == 11 && roomExit.roomNumber == 15) || (currentRoomNumber == 11 && roomExit.roomNumber == 16) || (currentRoomNumber == 12 && roomExit.roomNumber == 17))) { bVar = false; _console->printTosText(936); } if (currentRoomNumber == 7 && roomExit.roomNumber == 38 && bVar) { _player->loadAnimations("mirror.nsp"); _animation->setupOtherNspAnimation(0, 27); return; } if ((currentRoomNumber == 41 && roomExit.roomNumber == 44 && bVar) || (currentRoomNumber == 44 && roomExit.roomNumber == 41 && bVar)) { _player->loadAnimations("beamer.nsp"); _animation->setupOtherNspAnimation(0, 57); return; } if (currentRoomNumber == 10 && roomExit.roomNumber == 6 && bVar && !_player->_isAutoWalkingToBed) { _player->loadAnimations("rm10strs.nsp"); _animation->setupOtherNspAnimation(0, 53); return; } if (currentRoomNumber == 38 && roomExit.roomNumber == 7 && bVar) { _player->loadAnimations("darkin.nsp"); _animation->setupOtherNspAnimation(0, 41); return; } if (_objectVar[52] == 1 && ((currentRoomNumber == 12 && roomExit.roomNumber == 17) || (currentRoomNumber == 11 && (roomExit.roomNumber == 15 || roomExit.roomNumber == 16))) ) { _console->printTosText(437); bVar = false; // TODO the original sets roomExit to number 8 here. } else if (currentRoomNumber == 11 && roomExit.roomNumber == 15 && bVar) { _player->loadAnimations("rm11strs.nsp"); _animation->setupOtherNspAnimation(0, 55); return; } if (currentRoomNumber == 14 && roomExit.roomNumber == 35 && _objectVar[99] != 1) { bVar = false; _console->printTosText(937); } if (bVar && ( (currentRoomNumber == 6 && roomExit.roomNumber == 10) || (currentRoomNumber == 11 && roomExit.roomNumber == 16) || (currentRoomNumber == 12 && roomExit.roomNumber == 17) ) ) { _player->loadAnimations("opendoor.nsp"); _animation->setupOtherNspAnimation(0, 14); // FUN_1208_0dac_sound_related(10,CONCAT11(extraout_AH,5)); playSound(1, 5, -1); return; } if (currentRoomNumber == 6 && roomExit.roomNumber == 5 && bVar) { _player->_position.x = 346; _player->_position.y = 176; _player->loadAnimations("stairs.nsp"); _animation->setupOtherNspAnimation(1, 6); return; } if (currentRoomNumber == 33 && roomExit.roomNumber == 34 && bVar) { _player->loadAnimations("opendoor.nsp"); _animation->setupOtherNspAnimation(0, 25); // FUN_1208_0dac_sound_related(24,CONCAT11(extraout_AH,5)); playSound(15, 5, -1); //open car door return; } if (currentRoomNumber == 5 && roomExit.roomNumber == 6 && bVar) { if (_player->_position.x == 466 && _player->_position.y == 195) { _player->loadAnimations("stairs.nsp"); _player->_position.x -= 35; _animation->setupOtherNspAnimation(3, 7); return; } bVar = false; } if (currentRoomNumber == 40 && roomExit.roomNumber == 41 && _objectVar[59] != 2) { _console->printTosText(775); bVar = false; } if (currentRoomNumber == 44 && roomExit.roomNumber == 43 && _objectVar[78] != 2) { _console->printTosText(775); bVar = false; } if (bVar) { if (currentRoomNumber != 0x22 && (currentRoomNumber < 0x13 || currentRoomNumber > 0x17)) { _player->_playerIsChangingDirection = false; _player->_heroMoving = false; _player->updateSprite(); updateDisplay(); _previousRoomNumber = currentRoomNumber; // currentRoomNumber = *(byte *)((int)&roomExitTbl[0].roomNumber + iVar7 * 0xb); // if (((isAutoWalkingToBed != False) && (DAT_2c85_8254 == 2)) && (currentRoomNumber == 10)) { // FUN_171d_0c6e(); // } changeToRoom(roomExit.roomNumber); // if ((isAutoWalkingToBed != False) && // ((currentRoomNumber != 5 || // (lVar9 = CONCAT22(playerSpriteX_long._2_2_,(uint)playerSpriteX_long), // lVar10 = CONCAT22(playerSpriteY_long._2_2_,(uint)playerSpriteY_long), previousRoomNumber != 0x3d )))) // { // _player->updateBedAutoWalkSequence(); // uVar4 = playerSpriteX_maybe; // uVar3 = playerSpriteY_maybe; // lVar9 = CONCAT22(playerSpriteX_long._2_2_,(uint)playerSpriteX_long); // lVar10 = CONCAT22(playerSpriteY_long._2_2_,(uint)playerSpriteY_long); // } return; } } } } } } if (_player->isAtWalkTarget() && _player->_actionToPerform) { if (_player->_sequenceRotation != -1) { _player->changeDirection(_player->_direction, _player->_sequenceRotation); _player->updateSprite(); _player->_sequenceRotation = -1; return; } _player->_heroMoving = false; _player->_actionToPerform = false; // TODO complete at final destination logic. 2022:879d Common::Point currentCursorPos = _cursor.getPosition(); if (_player->_walkToSequence) { _cursor.setPosition(_player->_walkToSequencePoint); _player->_walkToSequence = false; } int objIdx = _room->getObjectUnderCursor(); _cursor.setPosition(currentCursorPos); if (objIdx != -1) { int objType = objIdx >= 30 ? 0 : _room->_roomObj[objIdx].type; int objNum = objIdx >= 30 ? 0 : _room->_roomObj[objIdx].objNum; if (((objType != 4 && objType != 0 && objType < 10) || objNum > 5 || _room->_collisionType != 0)) { if (_room->_collisionType == 0) { handleObjCollision(objNum); } else { handleObjCollision(objIdx); // TODO is this correct? } } } if (objIdx == -1) { _console->printTosText(938); if (_actionMode > 3) { _actionMode = kPointerAction; _cursor.setCursorType((CursorType)_actionMode); } } else { if (_actionMode > 3) { _actionMode = kPointerAction; _cursor.setCursorType((CursorType)_actionMode); } } } if (!_animation->_isPlayingAnimation_maybe) { // walk to destination point int walkXDelta; int walkYDelta; int local_a = _scaledWalkSpeed_maybe * 16; if (_player->_direction == 0 || _player->_direction == 2) { local_a = local_a / 3; } if (local_a < 1000) { local_a = 1000; } if (yDistToTarget < xDistToTarget) { walkXDelta = local_a; if (yDistToTarget == 0) { walkYDelta = 0; } else { walkYDelta = (local_a * yDistToTarget) / xDistToTarget; } } else { walkYDelta = local_a; if (xDistToTarget == 0) { walkXDelta = 0; } else { walkXDelta = (local_a * xDistToTarget) / yDistToTarget; } } if (walkXDelta != 0) { walkXDelta = walkXDelta / 1000; } if (walkYDelta != 0) { walkYDelta = walkYDelta / 1000; } if (!_room->canWalkAtLocation(_player->_walkTarget.x, _player->_walkTarget.y) || _player->isAtWalkTarget()) { bool bVar1 = false; bool bVar2 = false; if ((walkYDelta == 0 && _player->_position.y != _player->_walkTarget.y) || _player->_position.y == _player->_walkTarget.y) { bVar2 = true; } if ((walkXDelta == 0 && _player->_position.x != _player->_walkTarget.x) || _player->_position.x == _player->_walkTarget.x) { bVar1 = true; } int local_6; int local_4; if (_player->_walkTarget.x < _player->_position.x) { if (_player->_position.x - _player->_walkTarget.x <= walkXDelta) { local_6 = _player->_position.x - _player->_walkTarget.x; } else { local_6 = walkXDelta; } while (!bVar1 && local_6 > 0) { if (!_room->canWalkAtLocation(_player->_position.x - local_6 - 1, _player->_position.y)) { local_6--; } else { _player->_position.x -= local_6; _player->_heroMoving = true; bVar1 = true; } } } else if (_player->_position.x < _player->_walkTarget.x) { if (_player->_walkTarget.x - _player->_position.x <= walkXDelta) { local_6 = _player->_walkTarget.x - _player->_position.x; } else { local_6 = walkXDelta; } while (!bVar1 && local_6 > 0) { if (!_room->canWalkAtLocation(_player->_position.x + local_6 + 1, _player->_position.y)) { local_6--; } else { _player->_position.x += local_6; _player->_heroMoving = true; bVar1 = true; } } } if (_player->_walkTarget.y < _player->_position.y) { if (walkYDelta < _player->_position.y - _player->_walkTarget.y) { local_4 = walkYDelta; } else { local_4 = _player->_position.y - _player->_walkTarget.y; } while (!bVar2 && local_4 > 0) { int local_34 = (_player->_position.y - local_4) - 1; if (local_34 > 0xee) { local_34 = 0xee; } if (!_room->canWalkAtLocation(_player->_position.x, (local_34 - local_4) - 2)) { local_4--; } else { _player->_position.y -= local_4; _player->_heroMoving = true; bVar2 = true; } } } else if (_player->_position.y < _player->_walkTarget.y) { if (walkYDelta < _player->_walkTarget.y - _player->_position.y) { local_4 = walkYDelta; } else { local_4 = _player->_walkTarget.y - _player->_position.y; } while (!bVar2 && local_4 > 0) { if (!_room->canWalkAtLocation(_player->_position.x, _player->_position.y + local_4 + 2)) { local_4--; } else { _player->_position.y += local_4; _player->_heroMoving = true; bVar2 = true; } } } if (!bVar1 || !bVar2) { _player->_walkTarget = _player->_position; } _doorEnabled = false; if (_player->_isAutoWalkingToBed && _player->isAtWalkTarget()) { _player->setPlayerTowardsBedroom(); } } else { if (_player->_walkTarget.x < _player->_position.x) { if (_player->_position.x - _player->_walkTarget.x < walkXDelta) { walkXDelta = _player->_position.x - _player->_walkTarget.x; } _player->_positionLong.x -= walkXDelta; } else if (_player->_position.x < _player->_walkTarget.x) { if (_player->_walkTarget.x - _player->_position.x < walkXDelta) { walkXDelta = _player->_walkTarget.x - _player->_position.x; } _player->_positionLong.x += walkXDelta; } if (_player->_walkTarget.y < _player->_position.y) { if (_player->_position.y - _player->_walkTarget.y < walkYDelta) { walkYDelta = _player->_position.y - _player->_walkTarget.y; } _player->_positionLong.y -= walkYDelta; } else if (_player->_position.y < _player->_walkTarget.y) { if (_player->_walkTarget.y - _player->_position.y < walkYDelta) { walkYDelta = _player->_walkTarget.y - _player->_position.y; } _player->_positionLong.y += walkYDelta; } if (!_room->canWalkAtLocation(_player->_positionLong.x, _player->_positionLong.y)) { _player->_walkTarget = _player->_position; _player->_positionLong = _player->_position; } else { _player->_position = _player->_positionLong; } } } // else if (_isLeftMouseClicked) { // // TODO do actions here. // handlePointerAction(); // } } void DarkseedEngine::handlePointerAction() { if (_cursor.getCursorType() == ConnectorEntrance) { int newRoomNumber = _room->getExitRoomNumberAtPoint(_cursor.getX(), _cursor.getY()); if (newRoomNumber >= 0) { changeToRoom(newRoomNumber); } } } void DarkseedEngine::loadRoom(int roomNumber) { // *(undefined *)&_erasemenu = 1; TODO do we need these? // *(undefined2 *)&_gShipOff = 0; waitForSpeech(); if (roomNumber == 33 && _objectVar[62] == 101) { _objectVar[62] = 0; } _printedcomeheredawson = false; _objectVar.setObjectRunningCode(53, 0); _objectVar[56] = 0; // evil sergeant anim spriteNumber _objectVar.setObjectRunningCode(72, 0); for (int i = 31; i < 34; i++) { if (_objectVar.getMoveObjectRoom(i) == 99) { _objectVar.setMoveObjectRoom(i, 10); } } if (_objectVar[28] == 1) { _objectVar[28] = 2; } if (_objectVar[29] == 1) { _objectVar[29] = 2; } if (_objectVar[141] == 10) { _objectVar[141] = 11; } delete _room; _room = new Room(roomNumber); // getroomstuff updateBaseSprites(); if (roomNumber == 46 && _previousRoomNumber == 60 && _objectVar[57] == 1) { return; } if (roomNumber == 15 && _objectVar.getMoveObjectRoom(28) != 255) { _animation->setupOtherNspAnimation(1, 39); } } void DarkseedEngine::changeToRoom(int newRoomNumber, bool placeDirectly) { // AKA LoadNewRoom if (isDosDemo()) { if (newRoomNumber == 0 || newRoomNumber == 1) { newRoomNumber = 43; _previousRoomNumber = 44; } else if (newRoomNumber == 44) { newRoomNumber = 4; _previousRoomNumber = 0; } } MusicId newMusicId = Room::getMusicIdForRoom(newRoomNumber); if (g_engine->_sound->isPlayingMusic() && Room::getMusicIdForRoom(_room->_roomNumber) != newMusicId) { g_engine->_sound->startFadeOut(); while (g_engine->_sound->isFading()) { waitxticks(1); } g_engine->_sound->stopMusic(); } _objectVar[99] = 0; _objectVar[66] = 0; _objectVar[67] = 0; _objectVar[68] = 0; if (_objectVar[53] == 3) { _objectVar[53] = 0; } loadRoom(newRoomNumber); _room->darkenSky(); if (_room->_roomNumber == 54) { _objectVar[21] = 0; } if ((_room->_roomNumber == 9 && _previousRoomNumber == 3) || (_room->_roomNumber == 3 && _previousRoomNumber == 9)) { _objectVar[59] = 1; } if ((_room->_roomNumber == 0 && _previousRoomNumber == 2) || (_room->_roomNumber == 2 && _previousRoomNumber == 0)) { _objectVar[78] = 1; } if (newRoomNumber == 5 && _previousRoomNumber == 6) { _player->loadAnimations("stairs.nsp"); _player->_position.x = 0x174; _player->_position.y = 0x100; _animation->setupOtherNspAnimation(2, 6); } else if (newRoomNumber == 6 && _previousRoomNumber == 5) { _player->loadAnimations("stairs.nsp"); _player->_position.x = 0x19f; _player->_position.y = 0x8c; _animation->setupOtherNspAnimation(0, 7); } else if (newRoomNumber == 32 && _previousRoomNumber == 13) { _player->loadAnimations("slide.nsp"); _animation->setupOtherNspAnimation(0, 16); } else if (newRoomNumber == 10 && _previousRoomNumber == 6) { _player->loadAnimations("rm10strs.nsp"); _animation->setupOtherNspAnimation(1, 54); // walk down front steps } else if (newRoomNumber == 11 && _previousRoomNumber == 15) { _player->loadAnimations("rm11strs.nsp"); _animation->setupOtherNspAnimation(1, 56); } else if (newRoomNumber == 46 && _previousRoomNumber == 60 && _objectVar[57] == 1) { _console->printTosText(62); // TODO wait logic here. _cutscene.play('E'); return; } else if (newRoomNumber == 7 && _previousRoomNumber == 38) { _player->loadAnimations("mirror.nsp"); _animation->setupOtherNspAnimation(1, 28); if (_objectVar[47] == 0 && _currentDay == 3 && _objectVar[51] == 1) { _objectVar.setObjectRunningCode(47, 2); } } else if ((newRoomNumber == 38) && (_previousRoomNumber == 7)) { _player->loadAnimations("darkout.nsp"); _animation->setupOtherNspAnimation(1, 42); } else if ((_previousRoomNumber == 2) && (newRoomNumber == 3)) { _player->loadAnimations("rtladder.nsp"); _animation->setupOtherNspAnimation(1, 13); } else if ((_previousRoomNumber == 61) && (newRoomNumber == 5)) { _player->loadAnimations("ltladder.nsp"); _animation->setupOtherNspAnimation(1, 11); } else if ((_previousRoomNumber == 41 && newRoomNumber == 44) || (_previousRoomNumber == 44 && newRoomNumber == 41)) { _player->loadAnimations("beamer.nsp"); _animation->setupOtherNspAnimation(1, 58); for (auto &exit : _room->_room1) { if (exit.roomNumber == _previousRoomNumber) { _player->_position.x = exit.x + exit.width / 2; _player->_position.y = exit.y; _player->_direction = exit.direction; _player->updatePlayerPositionAfterRoomChange(); _player->_walkTarget = _player->_position; } } } else if (!placeDirectly && newRoomNumber != 0x22 && (newRoomNumber < 0x13 || newRoomNumber > 0x17)) { for (unsigned int i = 0; i < _room->_room1.size(); i++) { const RoomExit &roomExit = _room->_room1[i]; if (roomExit.roomNumber == _previousRoomNumber) { _player->_position.x = roomExit.x + roomExit.width / 2; _player->_position.y = roomExit.y; _player->_direction = roomExit.direction ^ 2; _player->updatePlayerPositionAfterRoomChange(); _player->_walkTarget = _player->_position; } } if (_previousRoomNumber == 10 && newRoomNumber == 6 && _objectVar[47] == 0 && _currentDay == 1) { _objectVar.setObjectRunningCode(47, 2); } } if (!g_engine->_animation->_isPlayingAnimation_maybe) { g_engine->_player->updateSprite(); } _room->initRoom(); updateDisplay(); _room->loadRoomMusic(); _room->printRoomDescriptionText(); } void DarkseedEngine::debugTeleportToRoom(int newRoomNumber, int entranceNumber) { delete _room; _room = new Room(newRoomNumber); updateBaseSprites(); if (entranceNumber < (int) _room->_room1.size()) { const RoomExit &roomExit = _room->_room1[entranceNumber]; _player->_position.x = roomExit.x + roomExit.width / 2; _player->_position.y = roomExit.y; _player->_direction = roomExit.direction ^ 2; _player->updatePlayerPositionAfterRoomChange(); _player->_walkTarget = _player->_position; } g_engine->updateDisplay(); } void DarkseedEngine::updateDisplay() { // AKA ServiceRoom int currentRoomNumber = _room->_roomNumber; _sprites.clearSpriteDrawList(); _room->runRoomObjects(); runObjects(); if (_animation->_isPlayingAnimation_maybe == 0 || (_animation->_otherNspAnimationType_maybe != 6 && _animation->_otherNspAnimationType_maybe != 7) || currentRoomNumber != 5) { _frameBottom = 240; } else { _frameBottom = 208; } if (currentRoomNumber != 0x22 && currentRoomNumber != 0x13 && currentRoomNumber != 0x14 && currentRoomNumber != 0x15 && currentRoomNumber != 0x16 && _objectVar[141] != 9 && (currentRoomNumber != 0x35 || _objectVar[45] != 2)) { if (((_animation->_otherNspAnimationType_maybe == 60) || (_animation->_otherNspAnimationType_maybe == 61)) && _animation->_isPlayingAnimation_maybe) { const Sprite &sprite = _room->_locationSprites.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(431, 66, &sprite, 255, sprite._width, sprite._height, false); } if (_objectVar[OBJ_21_HEADBAND] == 0 || (_headAcheMessageCounter & 1) != 0) { if (!_animation->_isPlayingAnimation_maybe || _animation->_otherNspAnimationType_maybe == 19 || _animation->_otherNspAnimationType_maybe == 23) { const Sprite &playerSprite = _player->getSprite(_player->_frameIdx); _room->calculateScaledSpriteDimensions(playerSprite._width, playerSprite._height, _player->_position.y); if ((currentRoomNumber != 53) || (_objectVar[79] != 2)) { _sprites.addSpriteToDrawList( _player->_position.x - (_scaledSpriteWidth / 2), _player->_position.y - _scaledSpriteHeight, &playerSprite, 240 - _player->_position.y, _scaledSpriteWidth, _scaledSpriteHeight, _player->_flipSprite); } } else { if (_animation->_otherNspAnimationType_maybe == 37) { const Sprite &playerSprite = _player->getSprite(26); _room->calculateScaledSpriteDimensions(playerSprite._width, playerSprite._height, _player->_position.y); _sprites.addSpriteToDrawList( _player->_position.x, _player->_position.y - _scaledSpriteHeight, &playerSprite, 240 - _player->_position.y, _scaledSpriteWidth, _scaledSpriteHeight, _player->_flipSprite); } if (_animation->_otherNspAnimationType_maybe == 39 || _animation->_otherNspAnimationType_maybe == 59 || _animation->_otherNspAnimationType_maybe == 60 || _animation->_otherNspAnimationType_maybe == 61) { const Sprite &playerSprite = _player->getSprite(26); _room->calculateScaledSpriteDimensions(playerSprite._width, playerSprite._height, _player->_position.y); _sprites.addSpriteToDrawList( _player->_position.x - _scaledSpriteWidth / 2, _player->_position.y - _scaledSpriteHeight, &playerSprite, 240 - _player->_position.y, _scaledSpriteWidth, _scaledSpriteHeight, _player->_flipSprite); if (_animation->_otherNspAnimationType_maybe == 60 || _animation->_otherNspAnimationType_maybe == 61) { _sprite_y_scaling_threshold_maybe = 240; // DrawObjectsMenu(); TODO do we need this logic? // UpdateAllVideo(); // *(undefined2 *)&_LastTickCursorY = *(undefined2 *)&_CursorY; return; } } // iVar9 = *(int *)((int)otherNspWidthTbl + _player->_frameIdx * 2); // iVar8 = *(int *)((int)&otherNspHeightTbl + _player->_frameIdx * 2); if (_animation->_otherNspAnimationType_maybe == 18) { if (_objectVar[22] == 0) { _sprite_y_scaling_threshold_maybe = 0xcb; } else if (_objectVar[22] == 1) { _sprite_y_scaling_threshold_maybe = 0xcb; } else if (_objectVar[22] == 2) { _sprite_y_scaling_threshold_maybe = 0xc4; } else { _sprite_y_scaling_threshold_maybe = 0xaf; } } if (_player->_animations.containsSpriteAt(_player->_frameIdx)) { // we need this check as the original logic calls the function below when it isn't initialised _room->calculateScaledSpriteDimensions( _player->_animations.getSpriteAt(_player->_frameIdx)._width, _player->_animations.getSpriteAt(_player->_frameIdx)._height, _animation->_nsp_sprite_scaling_y_position != 0 ? _animation->_nsp_sprite_scaling_y_position : _player->_position.y); } if (_animation->_otherNspAnimationType_maybe == 3) { // fall unconscious outside. int curScaledWidth = g_engine->_scaledSpriteWidth; int curScaledHeight = g_engine->_scaledSpriteHeight; _room->calculateScaledSpriteDimensions( _player->_animations.getSpriteAt(_player->_frameIdx + 1)._width, _player->_animations.getSpriteAt(_player->_frameIdx + 1)._height, _player->_position.y); const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(_player->_position.x - (curScaledWidth + g_engine->_scaledSpriteWidth) / 2, _player->_position.y - curScaledHeight, &animSprite, 240 - _player->_position.y, curScaledWidth, curScaledHeight, false); } else if (!_animation->_scaleSequence) { if (_animation->_otherNspAnimationType_maybe == 17) { // open trunk const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(_player->_position.x - animSprite._width / 2, _player->_position.y - animSprite._height, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 5 || _animation->_otherNspAnimationType_maybe == 1) { int x = 0xa6; int y = 0x69; if (_player->_frameIdx < 4) { x = 0x75; y = 0x71; } else if (_player->_frameIdx == 4) { x = 0x75; } else if (_player->_frameIdx == 7) { y = 0x5b; } /* bed wake sequence is played here. */ const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(x, y, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 43 || _animation->_otherNspAnimationType_maybe == 44) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(303, 105, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 62) { // sergeant approaches jail cell. const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(_player->_position.x - animSprite._width / 2, _player->_position.y - animSprite._height, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 45 || _animation->_otherNspAnimationType_maybe == 46) { // pull lever const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(446, 124, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 36) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(339, 78, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 59) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(433, 91, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 37) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(428, 78, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 10 || _animation->_otherNspAnimationType_maybe == 11) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(118, 62, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, false); } else if (_animation->_otherNspAnimationType_maybe == 12 || _animation->_otherNspAnimationType_maybe == 13) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(407, 73, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, false); } else if (_animation->_otherNspAnimationType_maybe == 20) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList((_player->_position.x - animSprite._width / 2) - 4, _player->_position.y - animSprite._height, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe < 30 || _animation->_otherNspAnimationType_maybe > 34) { if (_animation->_otherNspAnimationType_maybe == 40) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(373, 99, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); const Sprite &legsSprite = _player->_animations.getSpriteAt(12); _sprites.addSpriteToDrawList(373, 99 + animSprite._height, &legsSprite, 240 - _player->_position.y, legsSprite._width, legsSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe < 48 || _animation->_otherNspAnimationType_maybe > 52) { if (_animation->_otherNspAnimationType_maybe == 35) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(_player->_position.x - 10, _player->_position.y - animSprite._height, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe >= 53 && _animation->_otherNspAnimationType_maybe <= 56) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(_player->_position.x, _player->_position.y, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 57 || _animation->_otherNspAnimationType_maybe == 58) { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); Common::Point spritePos = {344, 57}; if (_room->_roomNumber == 41) { spritePos = {295, 46}; } _sprites.addSpriteToDrawList(spritePos.x, spritePos.y, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } else { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(_player->_position.x, _player->_position.y, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } } else { const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(_player->_position.x - animSprite._width / 2, _player->_position.y - animSprite._height, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); } } else { // drinking water in bathroom const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(448, 97, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); const Sprite &legsSprite = _player->_animations.getSpriteAt(0); _sprites.addSpriteToDrawList(451, 160, &legsSprite, 240 - _player->_position.y, legsSprite._width, legsSprite._height, _player->_flipSprite); } } else if (_animation->_otherNspAnimationType_maybe == 6) { // stairs up _sprites.addSpriteToDrawList( _player->_position.x - _scaledSpriteWidth / 2, _player->_position.y - _scaledSpriteHeight, &_player->_animations.getSpriteAt(_player->_frameIdx), 0xff, _scaledSpriteWidth, _scaledSpriteHeight, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 22) { // dig grave _sprites.addSpriteToDrawList( _player->_position.x - ((_scaledWalkSpeed_maybe * 30) / 1000), _player->_position.y - _scaledSpriteHeight, &_player->_animations.getSpriteAt(_player->_frameIdx), 240 - _player->_position.y, _scaledSpriteWidth, _scaledSpriteHeight, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 4 || _animation->_otherNspAnimationType_maybe == 21) { // dig grave _sprites.addSpriteToDrawList( _player->_position.x - ((_scaledWalkSpeed_maybe * 95) / 1000), _player->_position.y - _scaledSpriteHeight, &_player->_animations.getSpriteAt(_player->_frameIdx), 240 - _player->_position.y, _scaledSpriteWidth, _scaledSpriteHeight, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 39) { // Mike arrested by cop. int16 spriteX = 110; int16 spriteY = _player->_position.y; if (_room->_roomNumber == 10) { spriteX = 330; spriteY = 224; } const Sprite &sprite = _room->_locationSprites.getSpriteAt(_player->_frameIdx); _room->calculateScaledSpriteDimensions( sprite._width, sprite._height, spriteY); _sprites.addSpriteToDrawList( spriteX - _scaledSpriteWidth / 2, spriteY - _scaledSpriteHeight, &sprite, 240 - _player->_position.y, _scaledSpriteWidth, _scaledSpriteHeight, _player->_flipSprite); } else if (_animation->_otherNspAnimationType_maybe == 47) { // Mike stick throw const Sprite &sprite = _room->_locationSprites.getSpriteAt(_player->_frameIdx); _room->calculateScaledSpriteDimensions( sprite._width, sprite._height, _player->_position.y); _sprites.addSpriteToDrawList( _player->_position.x - _scaledSpriteWidth / 2, _player->_position.y - _scaledSpriteHeight, &sprite, 240 - _player->_position.y, _scaledSpriteWidth, _scaledSpriteHeight, _player->_flipSprite); } else { _sprites.addSpriteToDrawList( _player->_position.x - _scaledSpriteWidth / 2, _player->_position.y - _scaledSpriteHeight, &_player->_animations.getSpriteAt(_player->_frameIdx), 240 - _player->_position.y, _scaledSpriteWidth, _scaledSpriteHeight, _player->_flipSprite); } if (_animation->_isPlayingAnimation_maybe && _animation->_otherNspAnimationType_maybe == 14 && _animation->_animIndexTbl[0] > 1) { // opening doors. if (_objectVar.getObjectRunningCode(140) == 0 || _room->_roomNumber != 6) { if (_room->_roomNumber == 6 && _player->_isAutoWalkingToBed) { const Sprite &animSprite = _player->_animations.getSpriteAt(8); _sprites.addSpriteToDrawList(132, 70, &animSprite, 255, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_room->_roomNumber == 6) { const Sprite &animSprite = _player->_animations.getSpriteAt(2); _sprites.addSpriteToDrawList(132, 70, &animSprite, 255, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_room->_roomNumber == 11) { const Sprite &animSprite = _player->_animations.getSpriteAt(6); _sprites.addSpriteToDrawList(369, 119, &animSprite, 255, animSprite._width, animSprite._height, _player->_flipSprite); } else if (_room->_roomNumber == 12) { const Sprite &animSprite = _player->_animations.getSpriteAt(7); _sprites.addSpriteToDrawList(252, 121, &animSprite, 255, animSprite._width, animSprite._height, _player->_flipSprite); } } else { const Sprite &animSprite = _player->_animations.getSpriteAt(3); _sprites.addSpriteToDrawList(132, 70, &animSprite, 255, animSprite._width, animSprite._height, _player->_flipSprite); } } } } } } Common::Path DarkseedEngine::getRoomFilePath(const Common::Path &filename) const { if (isCdVersion()) { return Common::Path("room").join(filename); } return filename; } Common::Path DarkseedEngine::getPictureFilePath(const Common::Path &filename) const { if (isCdVersion()) { return Common::Path("picture").join(filename); } return filename; } void DarkseedEngine::handleObjCollision(int targetObjNum) { if (targetObjNum == 35 && _objectVar[22] < 2 && _cursor.getY() > 40) { targetObjNum = 22; } if (_actionMode == kLookAction || _actionMode == kHandAction || targetObjNum != 115) { if (_cursor.getY() < 40 && _actionMode > kLookAction) { if (_objectVar[80] < 2 || ((_actionMode != 25 || targetObjNum != 19) && (_actionMode != 19 || targetObjNum != 25))) { if ((_actionMode == 25 && targetObjNum == 20) || (_actionMode == 20 && targetObjNum == 25)) { if (_objectVar[25] > 99) { // Assemble special hammer _console->printTosText(969); _inventory.removeItem(20); _inventory.removeItem(25); updateDisplay(); playSound(17, 5, -1); _inventory.addItem(27); // waitxticks(30); TODO do we need to add delay here? return; } _useCode->genericResponse(_actionMode, targetObjNum, 999); } else { _useCode->genericResponse(_actionMode, targetObjNum, 999); } } else { _console->printTosText(695); } return; } else { switch (_actionMode) { case kHandAction: _useCode->useCode(targetObjNum); break; case kLookAction: lookCode(targetObjNum); break; case 5: _useCode->useCrowBar(targetObjNum); break; case 6: case 12: case 29: _useCode->useCodeJournal(_actionMode, targetObjNum); break; case 7: case 36: case 37: case 38: case 39: case 40: _useCode->useCodeShopItems(_actionMode, targetObjNum); break; case 8: _useCode->useCodeMoney(targetObjNum); break; case 9: _useCode->useCodeNewspaper(targetObjNum); break; case 10: _useCode->useCodeLibraryCard(targetObjNum); break; case 11: _useCode->useCodeBobbyPin(targetObjNum); break; case 13: case 26: _useCode->useCodeKeys(_actionMode, targetObjNum); break; case 14: _useCode->useCodeGloves(targetObjNum); break; case 15: _useCode->useCodeMirrorShard(targetObjNum); break; case 16: _useCode->useCodeBinoculars(targetObjNum); break; case 17: _useCode->useCodeShovel(targetObjNum); break; case 18: _useCode->useCodeDelbertsCard(targetObjNum); break; case 19: _useCode->useCodeStick(targetObjNum); break; case 20: _useCode->useCodeAxeHandle(targetObjNum); break; case 23: _useCode->useCodeRope(targetObjNum); break; case 24: _useCode->useCodeMicroFilm(targetObjNum); break; case 25: case 27: _useCode->useCodeSpecialHammer(_actionMode, targetObjNum); break; case 28: _useCode->useCodeGun(targetObjNum); break; case 30: _useCode->useCodeMoversNote(targetObjNum); break; case 34: _useCode->useCodeBluePrints(targetObjNum); break; case 35: _useCode->useCodeWatch(targetObjNum); break; case 41: _useCode->useCodeTinCup(targetObjNum); break; case 85: // this code appears to be wrong and unused. _useCode->useCodeEmptyUrn(targetObjNum); break; default: break; } } } else { _player->loadAnimations("pownex.nsp"); _animation->_animIndexTbl[0] = 0; _animation->_spriteAnimCountdownTimer[0] = _player->_animations.getAnimAt(0)._frameDuration[0]; _animation->_objRestarted = false; int16 frameIdx = 0; int16 prevFrameIdx = 0; while (!_animation->_objRestarted) { prevFrameIdx = frameIdx; for (int i = 0; i < 6; i++) { wait(); } _sprites.clearSpriteDrawList(); _frame.draw(); _console->draw(); _animation->advanceAnimationFrame(0); frameIdx = _player->_animations.getAnimAt(0)._frameNo[_animation->_animIndexTbl[0]]; const Sprite &sprite = _player->_animations.getSpriteAt(frameIdx); _sprites.addSpriteToDrawList(152, 89, &sprite, 255, sprite._width, sprite._height, false); _room->draw(); _sprites.drawSprites(); _screen->makeAllDirty(); _screen->update(); } _animation->_objRestarted = false; while (!_animation->_objRestarted) { for (int i = 0; i < 6; i++) { wait(); } _sprites.clearSpriteDrawList(); _frame.draw(); _console->draw(); _animation->advanceAnimationFrame(1); const Sprite &sprite = _player->_animations.getSpriteAt(_player->_animations.getAnimAt(1)._frameNo[_animation->_animIndexTbl[1]]); _sprites.addSpriteToDrawList(152, 129, &sprite, 255, sprite._width, sprite._height, false); const Sprite &mikeSprite = _player->_animations.getSpriteAt(prevFrameIdx); _sprites.addSpriteToDrawList(152, 89, &mikeSprite, 255, mikeSprite._width, mikeSprite._height, false); _room->draw(); _sprites.drawSprites(); _screen->makeAllDirty(); _screen->update(); } if (_actionMode == 25) { if (_objectVar[25] < 100) { _objectVar[25] = _objectVar[25] + 100; } _console->printTosText(930); } else if (_actionMode == 27) { _console->printTosText(929); } else { _console->printTosText(967); // The if (g_engine->getLanguage() == Common::KO_KOR) { _console->addToCurrentLine(KoFont::getObjectString(_objectVar.getObjectName(_actionMode))); } else { _console->addToCurrentLine(_objectVar.getObjectName(_actionMode)); } _console->printTosText(968, true); // was disintegrated. _inventory.removeItem(_actionMode); } if (_actionMode > 4) { _cursor.setCursorType(Pointer); } } } void DarkseedEngine::lookCode(int objNum) { if (objNum == 71 && _objectVar[71] == 2) { _console->addI18NText(kI18N_CarKeysIgnitionText); return; } if (objNum == 189) { _console->addI18NText(kI18N_YouSeeIronBarsText); return; } if (objNum == 141) { _console->addI18NText(kI18N_YouSeeDelbertText); return; } if (objNum == 42) { switch (_objectVar[42]) { case 0: case 4: _console->printTosText(652); break; case 1: _console->printTosText(659); _objectVar[42] = 2; break; case 2: _console->printTosText(659); break; case 3: _console->printTosText(658); break; default: break; } return; } if (objNum == 101) { switch (_objectVar[101]) { case 0: case 4: _console->printTosText(732); break; case 1: case 2: _console->printTosText(734); _objectVar[101] = 2; break; case 3: _console->printTosText(735); break; default: break; } return; } if (objNum == 25 && _cursor.getY() > 40) { if (_objectVar[80] > 1) { if (_objectVar[25] == 0 || _objectVar[25] == 100) { _console->printTosText(691); } else if (_objectVar[25] == 1 || _objectVar[25] == 2) { _objectVar[25] = 2; _console->printTosText(697); } else { _console->printTosText(693); } } return; } if (objNum == 138) { _console->addI18NText(kI18N_YouSeeTheClerkText); return; } if (objNum == 86 && _objectVar[86] != 0) { _console->addI18NText(kI18N_YouSeeTheOpenGloveBoxText); return; } if (objNum == 9) { _room->_collisionType = 0; _room->removeObjectFromRoom(9); _objectVar.setMoveObjectRoom(9, 100); showFullscreenPic(g_engine->isCdVersion() ? "paper_c.pic" : "paper-c.pic"); return; } if (objNum == 30) { _objectVar[30] = 1; _room->_collisionType = 0; _room->removeObjectFromRoom(30); _objectVar.setMoveObjectRoom(30, 100); showFullscreenPic(g_engine->isCdVersion() ? "note_c.pic" : "note-c.pic"); return; } if (objNum == 194) { if (_objectVar[53] == 2) { _console->printTosText(494); } else { _console->printTosText(496); } return; } if (objNum > 103 && objNum < 111) { int baseIdx = 370; if (objNum == 108) { baseIdx = 382; } else if (objNum == 110) { baseIdx = 388; } _console->printTosText(baseIdx + _objectVar[objNum] * 2); return; } if (objNum == 137) { if (_objectVar[30] == 0) { _console->printTosText(293); } else { _console->printTosText(295); } return; } if (objNum == 59) { if (_objectVar[59] == 2) { _console->printTosText(408); } else { _console->printTosText(31); } } if (objNum == 78) { if (_objectVar[78] == 2) { _console->printTosText(408); } else { _console->printTosText(406); } } if (objNum == 48 && _objectVar[48] == 0) { _animation->sargoAnim(); return; } if (objNum == 35 && _cursor.getY() < 40) { if (_objectVar[35] == 0) { _console->printTosText(670); } else { printTime(); } return; } if (objNum == 46) { if (_objectVar[46] == 1) { _console->printTosText(538); } else { _console->printTosText(536); } } if (objNum == 84) { _console->printTosText(565); } if ((objNum == 14) && (_objectVar[86] == 0)) { return; } if (objNum == 51) { if (_objectVar[187] == 0) { _console->printTosText(851); } else if (_objectVar[51] == 0) { _console->printTosText(853); _objectVar[51] = 1; _animation->keeperAdmin(); _objectVar.setObjectRunningCode(72, 1); _inventory.addItem(24); _console->printTosText(959); } else { _console->printTosText(960); } } if (objNum == 55) { _console->printTosText(776); showFullscreenPic("diagram.pic"); return; } if (objNum == 34) { _objectVar[34] = 1; showFullscreenPic(_room->isGiger() ? "gbprint1.pic" : "bprint1.pic"); return; } if (objNum == 18 && _cursor.getY() < 40) { showFullscreenPic(_room->isGiger() ? "gbcard01.pic" : "cbcard01.pic"); return; } if (objNum == 6 && _cursor.getY() < 40) { showFullscreenPic(_room->isGiger() ? "gdiary.pic" : "cdiary.pic"); _objectVar[6] = 1; return; } if (objNum == 12) { if (_cursor.getY() < 40) { showFullscreenPic(_room->isGiger() ? "gjourn01.pic" : "cjourn01.pic"); _objectVar[12] = 2; } else if (_objectVar[12] < 2) { _console->printTosText(567); } else { _console->printTosText(566); } return; } if (objNum == 29) { showFullscreenPic(_room->isGiger() ? "gjour201.pic" : "cjour201.pic"); if (_objectVar[29] == 0) { _objectVar[29] = 1; } return; } if (objNum == 10) { showFullscreenPic(_room->isGiger() ? "glcard.pic" : "clcard.pic"); return; } if (objNum == 100) { if (_objectVar[100] == 0) { _console->printTosText(139); _objectVar[100] = 1; } else if (_objectVar[100] == 1 || _objectVar[100] == 2) { _objectVar[100] = 2; _console->printTosText(141); } else if (_objectVar[100] == 3) { _console->printTosText(143); } return; } if (objNum == 103) { printTime(); } if (_cursor.getY() > 39 && objNum != 77 && (!isDosDemo() || objNum == 120)) { int eyeTosIdx = _objectVar.getEyeDescriptionTosIdx(objNum); if (eyeTosIdx < 979 && eyeTosIdx != 0) { _console->printTosText(eyeTosIdx); } if (eyeTosIdx > 978) { _useCode->genericResponse(3, objNum, eyeTosIdx); } return; } if (g_engine->getLanguage() == Common::KO_KOR) { _console->addTextLine(formatInjectStrings(getI18NText(kI18N_youSeeTheText).c_str(), KoFont::getObjectString(_objectVar.getObjectName(objNum)).c_str())); } else { _console->addTextLine(formatInjectStrings(getI18NText(kI18N_youSeeTheText).c_str(), _objectVar.getObjectName(objNum).c_str())); } } void DarkseedEngine::printTime() { _console->printTosText(958); int hour = g_engine->_currentTimeInSeconds / 60 / 60 + 1; if (g_engine->getLanguage() == Common::ZH_ANY) { _console->addToCurrentLineU32(convertToU32String(hour < 12 ? "\xa4\x57\xa4\xc8" : "\xa4\x55\xa4\xc8", Common::ZH_ANY)); _console->addToCurrentLine(Common::String::format("%d:%02d", hour % 12, (g_engine->_currentTimeInSeconds / 60) % 60)); } else { _console->addToCurrentLine(Common::String::format("%d: %02d %s", hour % 12, (g_engine->_currentTimeInSeconds / 60) % 60, hour < 12 ? "a.m." : "p.m.")); } } void DarkseedEngine::showFullscreenPic(const Common::Path &filename) { delete _fullscreenPic; _fullscreenPic = new Pic(); if (!_fullscreenPic->load(filename)) { delete _fullscreenPic; _fullscreenPic = nullptr; error("DarkseedEngine::showFullscreenPic(): Failed to load %s", filename.toString().c_str()); } Common::String filePathStr = filename.toString(); debug("Loaded %s", filePathStr.c_str()); Common::Path palFilename = Common::Path(filePathStr.substr(0, filePathStr.size() - 4) + ".pal"); Pal pal; pal.load(g_engine->getPictureFilePath(palFilename)); drawFullscreenPic(); } void DarkseedEngine::drawFullscreenPic() { if (_fullscreenPic) { _fullscreenPic->draw(0x45, 0x28); _screen->addDirtyRect({{0x45, 0x28}, 501, 200}); } } void DarkseedEngine::getPackageObj(int packageType) { _console->printTosText(424); if (packageType == 1) { _cutscene.play('D'); } if (packageType == 2) { _inventory.addItem(15); showFullscreenPic("shard.pic"); } if (packageType == 3) { _inventory.addItem(20); showFullscreenPic("handle.pic"); } } void DarkseedEngine::playSound(uint8 sfxId, uint8 unk1, int16 unk2) { debug("Play SFX: %d", sfxId); _sound->playSfx(sfxId, unk1, unk2); } void DarkseedEngine::nextFrame(int nspAminIdx) { _animation->_objRestarted = false; _animation->_spriteAnimCountdownTimer[nspAminIdx]--; _animation->_frameAdvanced = false; if (_animation->_spriteAnimCountdownTimer[nspAminIdx] < 1) { const Obt &anim = _player->_animations.getAnimAt(nspAminIdx); _animation->_animIndexTbl[nspAminIdx]++; _animation->_frameAdvanced = true; if (_animation->_animIndexTbl[nspAminIdx] == anim._numFrames) { _animation->_animIndexTbl[nspAminIdx] = 0; _animation->_objRestarted = true; } _animation->_spriteAnimCountdownTimer[nspAminIdx] = anim._frameDuration[_animation->_animIndexTbl[nspAminIdx]]; } } void DarkseedEngine::updateHeadache() { _headAcheMessageCounter++; _headAcheMessageCounter &= 63; if (_headAcheMessageCounter == 0) { _headacheMessageIdx++; if (_headacheMessageIdx > 4) { _headacheMessageIdx = 0; } if (_objectVar[112] == 0 && !_sound->isPlayingSpeech()) { _console->printTosText(_headacheMessageIdx + 9); } } } void DarkseedEngine::gotoSleepInJail() { gotoNextMorning(); playDayChangeCutscene(); } void DarkseedEngine::gotoNextMorning() { _currentDay++; _objectVar[47] = 0; _objectVar[62] = 0; _objectVar[112] = 0; _objectVar[52] = 1; _currentTimeInSeconds = 32400; _sound->resetSpeech(); if (_currentDay == 2) { _objectVar.setMoveObjectRoom(7, 253); } else if (_currentDay == 3) { _objectVar.setMoveObjectRoom(7, 255); } } void DarkseedEngine::playDayChangeCutscene() { if (_currentDay == 4) { _cutscene.play('Y'); } else if (_currentDay == 2) { _cutscene.play('B'); } else if (_currentDay == 3) { _cutscene.play('C'); } } void DarkseedEngine::closeShops() { if (_currentTimeInSeconds > 68400) { if (_room->_roomNumber == 15) { _previousRoomNumber = 15; _console->printTosText(79); changeToRoom(11); } if (_room->_roomNumber == 16) { _previousRoomNumber = 16; _console->printTosText(80); changeToRoom(11); } if (_room->_roomNumber == 28 || (_room->_roomNumber > 16 && _room->_roomNumber < 24)) { _previousRoomNumber = 17; _console->printTosText(98); changeToRoom(12); } } } void DarkseedEngine::initDelbertAtSide() { _objectVar[141] = 12; _objectVar.setMoveObjectX(141, 563); if (!_animation->_isPlayingAnimation_maybe || _animation->_otherNspAnimationType_maybe != 26) { _player->_heroMoving = false; _player->_walkTarget = _player->_position; _player->_actionToPerform = false; } } void DarkseedEngine::throwmikeinjail() { _console->printTosText(912); if (_room->_roomNumber == 15) { playSound(0, 6, -1); } _player->_position = {250, 200}; _animation->_isPlayingAnimation_maybe = false; _player->_frameIdx = 26; changeToRoom(30); _objectVar.setMoveObjectRoom(28, 255); _inventory.removeItem(28); _objectVar[1] = 500; _objectVar[88] = 0; _objectVar.setObjectRunningCode(72, 0); } void DarkseedEngine::runObjects() { if (((g_engine->_objectVar[44] != 0) && (g_engine->_objectVar[71] == 2))) { g_engine->_objectVar[44] -= 2; if (g_engine->_objectVar[44] == 0) { g_engine->_objectVar[71] = 2; } } if (g_engine->_objectVar[35] != 0) { g_engine->_objectVar[35]--; } if (((_room->_roomNumber == 46) || (_room->_roomNumber == 60)) && (((_soundTimer & 15) == 0 && (g_engine->_objectVar[57] == 1)))) { playSound(9, 5, -1); } if ((_room->_roomNumber == 12) && (_soundTimer > 5)) { _soundTimer = 0; } if (((_room->_roomNumber == 8) && (_soundTimer > 5)) && (g_engine->_objectVar[110] != 0)) { _soundTimer = 0; } if ((_room->_roomNumber == 38) && ((_soundTimer & 31) == 0)) { playSound(23, 5, -1); } if ((_room->_roomNumber == 45) && ((_soundTimer & 63) == 0)) { playSound(10, 5, -1); } int16 delbertSpriteIdx = 0; if (_objectVar[141] == 8 && _room->_roomNumber == 31) { // Fido brings back stick after player gives delbert the scotch. _player->_heroWaiting = true; if (_objectVar[45] == 3) { _room->loadLocationSprites("deldrink.nsp"); _objectVar[141] = 9; _room->_locObjFrame[0] = 0; _room->_locObjFrameTimer[0] = 2; delbertSpriteIdx = _room->_locationSprites.getAnimAt(0)._frameNo[_room->_locObjFrame[0]]; } else { delbertSpriteIdx = _room->_locationSprites.getAnimAt(0)._frameNo[_room->_locObjFrame[0]]; if (delbertSpriteIdx != 9) { _room->advanceFrame(0); delbertSpriteIdx = _room->_locationSprites.getAnimAt(0)._frameNo[_room->_locObjFrame[0]]; delbertThrowStick(delbertSpriteIdx); } if (_objectVar[141] == 8) { const Sprite &sprite = _room->_locationSprites.getSpriteAt(delbertSpriteIdx); delbertThrowStick(delbertSpriteIdx); g_engine->_sprites.addSpriteToDrawList(145, 140, &sprite, 240 - (sprite._height + 140), sprite._width, sprite._height, false); } } } if (_objectVar[141] == 9) { // delbert drinks scotch _room->advanceFrame(0); delbertSpriteIdx = _room->_locationSprites.getAnimAt(0)._frameNo[_room->_locObjFrame[0]]; if (_animation->_frameAdvanced && delbertSpriteIdx == 5) { playSound(32, 5, -1); } if (_animation->_objRestarted) { _objectVar[141] = 10; _console->printTosText(910); _inventory.removeItem(7); } Common::Point delbertPos = {125, 140}; _objectVar.setMoveObjectPosition(141, delbertPos); if (_objectVar[141] == 9) { const Sprite &sprite = _room->_locationSprites.getSpriteAt(delbertSpriteIdx); g_engine->_sprites.addSpriteToDrawList(125, 140, &sprite, 240 - (sprite._height + 140), sprite._width, sprite._height, false); } } if (_objectVar[141] == 10 && _room->_roomNumber == 31) { // delbert walks off screen. _room->advanceFrame(1); delbertSpriteIdx = _room->_locationSprites.getAnimAt(1)._frameNo[_room->_locObjFrame[1]]; Common::Point delbertPos = _objectVar.getMoveObjectPosition(141); if (_animation->_frameAdvanced) { delbertPos.x += 10; _objectVar.setMoveObjectPosition(141, delbertPos); } if (delbertPos.x < 560) { const Sprite &sprite = _room->_locationSprites.getSpriteAt(delbertSpriteIdx); g_engine->_sprites.addSpriteToDrawList(delbertPos.x, 140, &sprite, 240 - (sprite._height + 140), sprite._width, sprite._height, false); _room->updateRoomObj(141, delbertPos.x, sprite._width, 140, sprite._height); } else { _objectVar[141] = 11; _room->removeObjectFromRoom(141); _player->_heroWaiting = false; } } if (_objectVar[141] == 7 && _room->_roomNumber == 31) { _room->advanceFrame(0); delbertSpriteIdx = _room->_locationSprites.getAnimAt(0)._frameNo[_room->_locObjFrame[0]]; const Sprite &sprite = _room->_locationSprites.getSpriteAt(delbertSpriteIdx); delbertThrowStick(delbertSpriteIdx); g_engine->_sprites.addSpriteToDrawList(145, 140, &sprite, 240 - (sprite._height + 140), sprite._width, sprite._height, false); _room->updateRoomObj(141, 145, sprite._width, 140, sprite._height); } if ((_objectVar[141] == 7 || _objectVar[141] == 8) && _room->_roomNumber == 31) { if (delbertSpriteIdx > 7 && _objectVar[45] == 0) { Common::Point stickPosition = _objectVar.getMoveObjectPosition(19); if (stickPosition.y < 205 && _yvec != 100) { stickPosition.x += 12; stickPosition.y += _yvec; _objectVar.setMoveObjectPosition(19, stickPosition); _yvec++; } if (stickPosition.y > 205) { stickPosition = {495, 205}; _objectVar.setMoveObjectPosition(19, stickPosition); _yvec = 100; } } if (_objectVar[45] < 3 && _room->_roomNumber == 31 && _objectVar[141] > 6) { _objectVar.setMoveObjectRoom(19, 100); _room->advanceFrame(_objectVar[45] + 1); Common::Point stickPosition = _objectVar.getMoveObjectPosition(19); if (_animation->_objRestarted && _objectVar[45] < 2) { _objectVar[45] = (_objectVar[45] == 0) ? 1 : 0; if (_objectVar[45] == 0) { stickPosition = {230, 205}; } else { stickPosition.x = 1000; } _objectVar.setMoveObjectPosition(19, stickPosition); } if (stickPosition.x < 1000) { const Sprite &stickSprite = _baseSprites.getSpriteAt(19); g_engine->_sprites.addSpriteToDrawList(stickPosition.x, stickPosition.y, &stickSprite, 255, stickSprite._width, stickSprite._height, false); } Common::Point fidoPosition = _objectVar.getMoveObjectPosition(45); int16 fidoSpriteIdx = _room->_locationSprites.getAnimAt(_objectVar[45] + 1)._frameNo[_room->_locObjFrame[_objectVar[45] + 1]]; if (_animation->_frameAdvanced) { if (_objectVar[45] == 2) { fidoPosition.x += 30; _objectVar.setMoveObjectPosition(45, fidoPosition); if (fidoPosition.x > 564) { _objectVar.setMoveObjectRoom(19, 31); _objectVar[45]++; } } else if (_objectVar[45] == 0) { if (fidoSpriteIdx > 11 && fidoSpriteIdx < 18) { fidoPosition.x += 30; _objectVar.setMoveObjectPosition(45, fidoPosition); } } else if (fidoSpriteIdx > 19 && fidoSpriteIdx < 26) { fidoPosition.x -= 30; _objectVar.setMoveObjectPosition(45, fidoPosition); } } if (_objectVar[45] < 3) { bool flipFidoSprite = false; if ((_objectVar[45] == 0) && (_room->_locObjFrame[1] < 6)) { flipFidoSprite = true; } if ((_objectVar[45] == 1) && (7 < _room->_locObjFrame[2])) { flipFidoSprite = true; } if (((_objectVar[45] == 1) && (_room->_locObjFrame[2] == 9)) && (_objectVar[141] == 8)) { stickPosition = {230, 205}; _objectVar.setMoveObjectPosition(19, stickPosition); _objectVar[45] = 2; } const Sprite &fidoSprite = _room->_locationSprites.getSpriteAt(fidoSpriteIdx); g_engine->_sprites.addSpriteToDrawList(fidoPosition.x, 173, &fidoSprite, 240 - (fidoSprite._height + 173), fidoSprite._width, fidoSprite._height, flipFidoSprite); } } } if (_objectVar[141] > 0 && _objectVar[141] < 4) { _player->_heroWaiting = true; if (_player->_walkToSequence == false && _player->_position.x != 290 && _player->_position.y != 209) { _player->_walkTarget = {290, 209}; // TODO reset walk path here _player->playerFaceWalkTarget(); } if (_player->_position.x == 290 && _player->_position.y == 209 && !_player->_playerIsChangingDirection && _player->_direction != 3) { _player->changeDirection(_player->_direction, 3); } _animation->_objRestarted = false; if (!_sound->isPlayingSpeech() && (_objectVar[141] != 2 || _delbertspeech > 64)) { nextFrame(_objectVar[141] - 1); } if (_animation->_objRestarted) { _objectVar[141]++; if (_objectVar[141] == 2) { _delbertspeech = 63; _console->printTosText(907); // if (_gGameSound == 0) { TODO // waitxticks(240); // } } else if (_objectVar[141] == 4) { _player->_heroWaiting = false; } _animation->_objRestarted = false; } if (!_sound->isPlayingSpeech() && _objectVar[141] == 2) { if (_delbertspeech < 65) { _delbertspeech++; } if (_delbertspeech == 64) { _console->printTosText(908); waitForSpeech(); } else if (_delbertspeech == 65) { _animation->setupOtherNspAnimation(3, 20); _animation->_spriteAnimCountdownTimer[1] = 3; _delbertspeech = 72; } } const Sprite &sprite = _player->_animations.getSpriteAt(_player->_animations.getAnimAt(_objectVar[141] - 1)._frameNo[_animation->_animIndexTbl[_objectVar[141] - 1]]); Common::Point delbertPosition = _objectVar.getMoveObjectPosition(141); if (_animation->_frameAdvanced) { if (_objectVar[141] == 1) { delbertPosition.x += 15; delbertPosition.y -= 1; } else if (_objectVar[141] == 3) { delbertPosition.x -= 15; delbertPosition.y += 1; } _objectVar.setMoveObjectPosition(141, delbertPosition); } int spriteX = delbertPosition.x; if (_objectVar[141] == 2) { spriteX += 23; } int spriteY = delbertPosition.y - sprite._height; if (_objectVar[141] < 4) { g_engine->_sprites.addSpriteToDrawList(spriteX, spriteY, &sprite, 240 - delbertPosition.y, sprite._width, sprite._height, _objectVar[141] == 3); } } if (_room->_roomNumber == 32 && _currentDay == 2 && _currentTimeInSeconds > 64799 && (_objectVar[141] == 5 || _objectVar[141] == 6)) { // walk delbert off into garden. _room->advanceFrame(_objectVar[141] - 4); if (_animation->_objRestarted) { _objectVar[141]++; if (_objectVar[141] == 7) { _player->_heroWaiting = false; } } Common::Point delbertPosition = _objectVar.getMoveObjectPosition(141); const Sprite &sprite = _room->_locationSprites.getSpriteAt(_room->_locationSprites.getAnimAt(_objectVar[141] - 4)._frameNo[_room->_locObjFrame[_objectVar[141] - 4]]); if (_animation->_frameAdvanced && _objectVar[141] > 5) { delbertPosition.x += 8; _objectVar.setMoveObjectX(141, delbertPosition.x); } if (_objectVar[141] != 7) { g_engine->_sprites.addSpriteToDrawList(delbertPosition.x, 135, &sprite, 240 - (sprite._height + 132), sprite._width, sprite._height, false); } } if (_room->_roomNumber == 32 && _currentDay == 2 && _currentTimeInSeconds > 64799 && _objectVar[141] == 4) { _objectVar.setMoveObjectX(141, 395); const Sprite &sprite = _room->_locationSprites.getSpriteAt(0); g_engine->_sprites.addSpriteToDrawList(395, 132, &sprite, 240 - (sprite._height + 132), sprite._width, sprite._height, false); movePlayerToDelbert(); if (!_player->_playerIsChangingDirection && !_player->_heroMoving) { _console->printTosText(909); _objectVar[141]++; _player->_heroWaiting = true; } } if (_room->_roomNumber == 32 && _currentDay == 2 && _objectVar[141] == 12) { Common::Point delbertPosition = _objectVar.getMoveObjectPosition(141); if (_room->advanceFrame(2)) { delbertPosition.x -= 8; _objectVar.setMoveObjectX(141, delbertPosition.x); } const Sprite &sprite = _room->_locationSprites.getSpriteAt(_room->_locationSprites.getAnimAt(2)._frameNo[_room->_locObjFrame[2]]); g_engine->_sprites.addSpriteToDrawList(delbertPosition.x, 135, &sprite, 240 - (sprite._height + 135), sprite._width, sprite._height, true); if (delbertPosition.x < 396) { _room->_locObjFrameTimer[2] = _room->_locationSprites.getAnimAt(2)._frameDuration[_room->_locObjFrame[2]]; _room->_locObjFrame[2] = 0; _objectVar[141] = 4; } movePlayerToDelbert(); } if (_objectVar.getObjectRunningCode(72) == 1 && (_room->_roomNumber < 10 || _room->_roomNumber == 60 || _room->_roomNumber == 61)) { _objectVar.setObjectRunningCode(72, 2); _console->printTosText(933); } // jail sergeant if (_room->_roomNumber == 30 && (_objectVar.getObjectRunningCode(53) == 1 || _objectVar.getObjectRunningCode(53) == 2) && (_animation->_otherNspAnimationType_maybe != 40 || !_animation->_isPlayingAnimation_maybe)) { if (_objectVar.getObjectRunningCode(53) == 1) { int oldFrame = _animation->_animIndexTbl[0]; nextFrame(0); if (_animation->_objRestarted) { _objectVar.setObjectRunningCode(53, 2); _animation->_animIndexTbl[0] = oldFrame; } } _room->removeObjectFromRoom(189); const Sprite &sprite = _player->_animations.getSpriteAt(_player->_animations.getAnimAt(0)._frameNo[_animation->_animIndexTbl[0]]); g_engine->_sprites.addSpriteToDrawList(463, 99, &sprite, 255, sprite._width, sprite._height, false); _room->updateRoomObj(64, 467, 200, 99, 200); } if ((((!_animation->_isPlayingAnimation_maybe || _animation->_otherNspAnimationType_maybe != 39) && _room->_roomNumber == 10) && _objectVar.getObjectRunningCode(72) != 0) && ((_currentDay == 3 && _currentTimeInSeconds > 39600 && _objectVar[57] == 0) || _objectVar[88] != 0)) { if (_player->_position.x == 322 && _player->_position.y == 226) { _animation->setupOtherNspAnimation(1, 39); // arrest mike. } else { const Sprite &sprite = _room->_locationSprites.getSpriteAt(4); _room->calculateScaledSpriteDimensions(sprite._width, sprite._height, 224); g_engine->_sprites.addSpriteToDrawList(348 - _scaledSpriteWidth, 224 - _scaledSpriteHeight, &sprite, 224, _scaledSpriteWidth, _scaledSpriteHeight, false); if (_player->_heroMoving && _player->_playerIsChangingDirection == 0 && _player->_direction != 1 && (_player->_position.x < 368 || _player->_position.y < 200) && (!_animation->_isPlayingAnimation_maybe || _animation->_otherNspAnimationType_maybe == 53) && _player->_walkTarget.x != 322 && _player->_walkTarget.y != 226) { _player->_heroMoving = false; } if (_player->_position.x < 369 && !_player->_heroMoving && (!_animation->_isPlayingAnimation_maybe || _animation->_otherNspAnimationType_maybe == 53) && (_player->_position.x != 322 || _player->_position.y != 226)) { if (_animation->_isPlayingAnimation_maybe && _animation->_otherNspAnimationType_maybe == 53) { _animation->_isPlayingAnimation_maybe = false; } Common::Point oldCursor = g_engine->_cursor.getPosition(); Common::Point newTarget = {322, 226}; g_engine->_cursor.setPosition(newTarget); _player->calculateWalkTarget(); g_engine->_cursor.setPosition(oldCursor); _player->playerFaceWalkTarget(); if (!_printedcomeheredawson) { _console->printTosText(934); _printedcomeheredawson = true; } } } } if (_objectVar[79] == 0 && _room->_roomNumber == 53) { // evil fido if (_player->_heroMoving && _player->_walkTarget.x > 279 && _player->_walkTarget.y < 220) { // _player->_CurrentConnector = 255; TODO do we need this? _player->_walkTarget = {323, 202}; } if (_player->_position.x == 323 && _player->_position.y == 202) { _objectVar[79] = 4; playSound(20, 5, -1); } } if (((_objectVar.getObjectRunningCode(58) != 0) && (_objectVar[21] == 0)) && (_room->_roomNumber == 55)) { if (_player->_position.x == 369) { _animation->runDrekethSequence(); } if (_player->_heroMoving && _player->_walkTarget.x > 309) { _player->_walkTarget = {369, 219}; } } // phone ringing logic if (_objectVar._objectRunningCode[47] != 0 && (_currentDay == 1 || _currentDay == 3)) { _objectVar._objectRunningCode[47] += 2; switch (_objectVar._objectRunningCode[47]) { case 120: case 300: case 480: case 660: case 900: if (_room->_roomNumber < 10 || _room->_roomNumber == 61 || _room->_roomNumber == 62) { if (_room->_roomNumber == 0) { playSound(24, 5, -1); } else { playSound(25, 5, -1); } _console->addI18NText(kI18N_ThePhoneIsRingingText); } break; case 1080: _objectVar._objectRunningCode[47] = 0; _objectVar[47] = 1; break; default: break; } } // handle package logic. if (_objectVar._objectRunningCode[140] != 0) { switch (_currentTimeInSeconds - 36000) { case 120: case 121: case 420: case 421: case 720: case 721: if (((_room->_roomNumber < 10) || (_room->_roomNumber == 61)) || (_room->_roomNumber == 62)) { if (_room->_roomNumber == 6) { // FUN_1208_0dac_sound_related(93,5); TODO floppy sound playSound(27, 5, -1); } else { playSound(29, 5, -1); // FUN_1208_0dac_sound_related(95,5); TODO floppy sound } _console->addI18NText(kI18N_TheDoorbellIsRingingText); } break; case 900: case 901: leavePackage(); break; default: break; } if (_currentTimeInSeconds - 36000 > 901 && _objectVar._objectRunningCode[140] != 0) { leavePackage(); } } } void DarkseedEngine::movePlayerToDelbert() { if (_room->_roomNumber == 32 && !_animation->_isPlayingAnimation_maybe) { _player->_heroWaiting = true; if (!_player->_heroMoving && _player->_position.x != 364 && _player->_position.y != 198) { Common::Point oldCursor = g_engine->_cursor.getPosition(); Common::Point newTarget = {364, 198}; g_engine->_cursor.setPosition(newTarget); _player->calculateWalkTarget(); g_engine->_cursor.setPosition(oldCursor); _player->playerFaceWalkTarget(); } if (_player->_position.x == 364 && _player->_position.y == 198 && !_player->_playerIsChangingDirection && _player->_direction != 1) { _player->changeDirection(_player->_direction, 1); _player->_walkTarget = _player->_position; _player->_heroMoving = false; } } } void DarkseedEngine::delbertThrowStick(int16 spriteNum) { if (_animation->_frameAdvanced && spriteNum == 8) { Common::Point stickPos = {265, 150}; _objectVar.setMoveObjectPosition(19, stickPos); _yvec = -6; playSound(3, 1, -1); } if (_room->_locObjFrame[0] == 2) { _objectVar.setMoveObjectX(19, 1000); } } void DarkseedEngine::leavePackage() { int packageObjNum = _currentDay + 30; int16 xPos = _currentDay * 10 + 299; Common::Point packagePos = {xPos, 191}; _objectVar.setMoveObjectPosition(packageObjNum, packagePos); if (_room->_roomNumber == 10) { _objectVar.setMoveObjectRoom(packageObjNum, 99); } else { _objectVar.setMoveObjectRoom(packageObjNum, 10); } // _MoveObjectDepth[packageObjNum] = 0; TODO do we need this? It doesn't appear to be used. _objectVar._objectRunningCode[140] = 0; } void DarkseedEngine::removeFullscreenPic() { if (_fullscreenPic) { delete _fullscreenPic; _fullscreenPic = nullptr; _room->restorePalette(); } } void DarkseedEngine::zeroMouseButtons() { _isLeftMouseClicked = false; _isRightMouseClicked = false; } void DarkseedEngine::updateBaseSprites() { if (_room->isGiger() != _normalWorldSpritesLoaded) { // no need to change graphics return; } if (_room->isGiger()) { _baseSprites.load("gbase.nsp"); _frame.load("gframe.pic"); _normalWorldSpritesLoaded = false; } else { _baseSprites.load("cbase.nsp"); _frame.load("cframe.pic"); _normalWorldSpritesLoaded = true; } _redrawFrame = true; } void DarkseedEngine::waitxticks(int ticks) { for (int i = 0; i < ticks * 6; i++) { updateEvents(); _room->update(); _screen->update(); wait(); } } void DarkseedEngine::doCircles() { debug("DarkseedEngine::doCircles"); if (isDosDemo()) { _player->_position.x = 320; _player->_position.y = 220; _player->_walkTarget = _player->_position; _player->_frameIdx = 28; _player->_direction = 2; _frame.draw(); _room->draw(); _console->draw(true); updateDisplay(); _sprites.drawSprites(); } else { _player->loadAnimations("bedsleep.nsp"); _player->_position.x = 0x87; _player->_position.y = 0x5b; _player->_frameIdx = 0; _player->_direction = 1; _animation->setupOtherNspAnimation(0, 1); _frame.draw(); _room->draw(); _console->draw(true); // setup & draw Mike in bed. _sprites.clearSpriteDrawList(); const Sprite &animSprite = _player->_animations.getSpriteAt(_player->_frameIdx); _sprites.addSpriteToDrawList(0x75, 0x71, &animSprite, 240 - _player->_position.y, animSprite._width, animSprite._height, _player->_flipSprite); _sprites.drawSprites(); } // Capture screen. Graphics::Surface screenCopy; screenCopy.copyFrom(*_screen); _screen->clear(0); // draw onion rings of the screen. int16 lineLengthTbl[175]; for (int i = 0; i < 175; i++) { lineLengthTbl[i] = -1; } for (int xOffset = 5; xOffset < 261; xOffset = xOffset + 5) { int16 prevLineLengthTbl[175]; for (int i = 0; i < 175; i++) { prevLineLengthTbl[i] = lineLengthTbl[i]; } int local_4 = xOffset * xOffset; for (int y = 0; y < xOffset; y++) { int local_6 = local_4 - y * y; int local_8 = 0; int iVar1 = 0; for (int local_a = 0; local_a < local_6; local_a = local_a + iVar1 + 1) { iVar1 = local_8 * 2; local_8 = local_8 + 1; } if (y < 175) { lineLengthTbl[y] = (int16)(local_8 * 3 >> 1); if (prevLineLengthTbl[y] == -1) { copyLine(screenCopy, 320 - lineLengthTbl[y],lineLengthTbl[y] + 320,175 - y); copyLine(screenCopy, 320 - lineLengthTbl[y],lineLengthTbl[y] + 320,y + 176); } else { copyLine(screenCopy, 320 - lineLengthTbl[y],320 - prevLineLengthTbl[y],175 - y); copyLine(screenCopy, prevLineLengthTbl[y] + 320,lineLengthTbl[y] + 320,175 - y); copyLine(screenCopy, 320 - lineLengthTbl[y],320 - prevLineLengthTbl[y],y + 176); copyLine(screenCopy, prevLineLengthTbl[y] + 320,lineLengthTbl[y] + 320,y + 176); } } } _screen->update(); wait(); } _screen->copyRectToSurface(screenCopy, 0, 0, {screenCopy.w, screenCopy.h}); _screen->update(); } void DarkseedEngine::copyLine(const Graphics::Surface &surface, int16 x1, int16 x2, int16 y) { auto rect = Common::Rect({x1, y}, x2 - x1, 1); _screen->blitFrom(surface, rect, rect); } void DarkseedEngine::restartGame() { _restartGame = true; } void DarkseedEngine::newGame() { _canSaveGame = false; _redrawFrame = false; _sprites.clearSpriteDrawList(); removeFullscreenPic(); _inventory.reset(); _sound->resetSpeech(); _objectVar.reset(); _room->_roomNumber = isDosDemo() ? 4 : 0; _delbertspeech = 0; _yvec = 0; _currentDay = 1; _currentTimeInSeconds = 0x7e8e; _fttime = 0; _previousRoomNumber = 0; _targetRoomNumber = 0; _headAcheMessageCounter = 0; _headacheMessageIdx = 0; _sprite_y_scaling_threshold_maybe = 0xf0; _scaledWalkSpeed_maybe = 0; _scaledSpriteWidth = 0; _scaledSpriteHeight = 0; _frameBottom = 0; _doorEnabled = false; _useDoorTarget = false; _counter_2c85_888b = 0; _targetPlayerDirection = 0; _systemTimerCounter = 0; _phoneStatus = 0; _soundTimer = 0; _printedcomeheredawson = false; _player->_isAutoWalkingToBed = false; _console->clear(); changeToRoom(_room->_roomNumber); doCircles(); _console->printTosText(8); _console->draw(); _screen->update(); waitForSpeech(); _systemTimerCounter = 4; _cursor.showCursor(true); if (!isDosDemo()) { _canSaveGame = true; } } void DarkseedEngine::waitForSpeech() { while (_sound && _sound->isPlayingSpeech()) { _console->draw(); updateEvents(); if (_room) { _room->update(); } _screen->update(); wait(); } } void DarkseedEngine::waitForSpeechOrSfx() { while (_sound && (_sound->isPlayingSpeech() || _sound->isPlayingSfx())) { _console->draw(); updateEvents(); if (_room) { _room->update(); } _screen->update(); wait(); } } } // End of namespace Darkseed