diff options
-rw-r--r-- | engines/lure/events.cpp | 37 | ||||
-rw-r--r-- | engines/lure/events.h | 14 | ||||
-rw-r--r-- | engines/lure/game.cpp | 73 | ||||
-rw-r--r-- | engines/lure/game.h | 3 | ||||
-rw-r--r-- | engines/lure/hotspots.cpp | 193 | ||||
-rw-r--r-- | engines/lure/hotspots.h | 22 | ||||
-rw-r--r-- | engines/lure/intro.cpp | 39 | ||||
-rw-r--r-- | engines/lure/intro.h | 1 | ||||
-rw-r--r-- | engines/lure/lure.cpp | 6 | ||||
-rw-r--r-- | engines/lure/lure.h | 2 | ||||
-rw-r--r-- | engines/lure/luredefs.h | 45 | ||||
-rw-r--r-- | engines/lure/menu.cpp | 16 | ||||
-rw-r--r-- | engines/lure/menu.h | 2 | ||||
-rw-r--r-- | engines/lure/res.cpp | 2 | ||||
-rw-r--r-- | engines/lure/res_struct.cpp | 14 | ||||
-rw-r--r-- | engines/lure/res_struct.h | 6 | ||||
-rw-r--r-- | engines/lure/room.cpp | 36 | ||||
-rw-r--r-- | engines/lure/room.h | 2 |
18 files changed, 358 insertions, 155 deletions
diff --git a/engines/lure/events.cpp b/engines/lure/events.cpp index dd96123256..055bfac49c 100644 --- a/engines/lure/events.cpp +++ b/engines/lure/events.cpp @@ -44,10 +44,10 @@ Mouse::Mouse() { _lButton = false; _rButton = false; - _cursorNum = 0; + _cursorNum = CURSOR_ARROW; _x = 0; _y = 0; - setCursorNum(0); + setCursorNum(CURSOR_ARROW); } Mouse::~Mouse() { @@ -84,7 +84,7 @@ void Mouse::cursorOff() { CursorMan.showMouse(false); } -void Mouse::setCursorNum(uint8 cursorNum) { +void Mouse::setCursorNum(CursorType cursorNum) { int hotspotX = 7, hotspotY = 7; if ((cursorNum == CURSOR_ARROW) || (cursorNum == CURSOR_MENUBAR)) { hotspotX = 0; @@ -94,7 +94,7 @@ void Mouse::setCursorNum(uint8 cursorNum) { setCursorNum(cursorNum, hotspotX, hotspotY); } -void Mouse::setCursorNum(uint8 cursorNum, int hotspotX, int hotspotY) { +void Mouse::setCursorNum(CursorType cursorNum, int hotspotX, int hotspotY) { Resources &res = Resources::getReference(); _cursorNum = cursorNum; @@ -102,7 +102,7 @@ void Mouse::setCursorNum(uint8 cursorNum, int hotspotX, int hotspotY) { CursorMan.replaceCursor(cursorAddr, CURSOR_WIDTH, CURSOR_HEIGHT, hotspotX, hotspotY, 0); } -void Mouse::pushCursorNum(uint8 cursorNum) { +void Mouse::pushCursorNum(CursorType cursorNum) { int hotspotX = 7, hotspotY = 7; if ((cursorNum == CURSOR_ARROW) || (cursorNum == CURSOR_MENUBAR)) { hotspotX = 0; @@ -112,7 +112,7 @@ void Mouse::pushCursorNum(uint8 cursorNum) { pushCursorNum(cursorNum, hotspotX, hotspotY); } -void Mouse::pushCursorNum(uint8 cursorNum, int hotspotX, int hotspotY) { +void Mouse::pushCursorNum(CursorType cursorNum, int hotspotX, int hotspotY) { Resources &res = Resources::getReference(); _cursorNum = cursorNum; @@ -193,4 +193,29 @@ void Events::waitForPress() { } } +// interruptableDelay +// Delays for a given number of milliseconds. If it returns true, it indicates that +// the Escape has been pressed to abort whatever sequence is being displayed + +bool Events::interruptableDelay(uint32 milliseconds) { + Events &events = Events::getReference(); + uint32 delayCtr = g_system->getMillis() + milliseconds; + + while (g_system->getMillis() < delayCtr) { + if (events.quitFlag) return true; + + if (events.pollEvent()) { + if (events.type() == Common::EVENT_KEYDOWN) + return events.event().kbd.keycode == 27; + else if (events.type() == Common::EVENT_LBUTTONDOWN) + return false; + } + + uint32 delayAmount = delayCtr - g_system->getMillis(); + if (delayAmount > 10) delayAmount = 10; + g_system->delayMillis(delayAmount); + } + return false; +} + } // end of namespace Lure diff --git a/engines/lure/events.h b/engines/lure/events.h index fcdfc343d7..1205ebe158 100644 --- a/engines/lure/events.h +++ b/engines/lure/events.h @@ -36,7 +36,7 @@ namespace Lure { class Mouse { private: - uint8 _cursorNum; + CursorType _cursorNum; int16 _x, _y; bool _lButton, _rButton; public: @@ -47,17 +47,17 @@ public: void cursorOn(); void cursorOff(); - void setCursorNum(uint8 cursorNum); - void setCursorNum(uint8 cursorNum, int hotspotX, int hotspotY); - uint8 getCursorNum() { return _cursorNum; } + void setCursorNum(CursorType cursorNum); + void setCursorNum(CursorType cursorNum, int hotspotX, int hotspotY); + CursorType getCursorNum() { return _cursorNum; } void setPosition(int x, int y); int16 x() { return _x; } int16 y() { return _y; } bool lButton() { return _lButton; } bool rButton() { return _rButton; } void waitForRelease(); - void pushCursorNum(uint8 cursorNum); - void pushCursorNum(uint8 cursorNum, int hotspotX, int hotspotY); + void pushCursorNum(CursorType cursorNum); + void pushCursorNum(CursorType cursorNum, int hotspotX, int hotspotY); void popCursor(); }; @@ -72,6 +72,8 @@ public: bool pollEvent(); void waitForPress(); + bool interruptableDelay(uint32 milliseconds); + Common::Event event() { return _event; } Common::EventType type() { return _event.type; } }; diff --git a/engines/lure/game.cpp b/engines/lure/game.cpp index 26d9c71edd..60a6a8b255 100644 --- a/engines/lure/game.cpp +++ b/engines/lure/game.cpp @@ -29,8 +29,10 @@ #include "lure/scripts.h" #include "lure/res_struct.h" #include "lure/animseq.h" +#include "lure/fights.h" #include "common/config-manager.h" +#include <sdl_keysym.h> namespace Lure { @@ -51,20 +53,14 @@ Game::~Game() { delete _debugger; } -void Game::nextFrame() { - Resources &res = Resources::getReference(); - ValueTableData &fields = res.fieldList(); - Room &room = Room::getReference(); - HotspotList::iterator i; - - res.pausedList().countdown(); - room.checkCursor(); - room.update(); - +void Game::tick() { // Call the tick method for each hotspot - this is somewaht complicated // by the fact that a tick proc can unload both itself and/or others, // so we first get a list of the Ids, and call the tick proc for each // id in sequence if it's still active + Resources &res = Resources::getReference(); + ValueTableData &fields = res.fieldList(); + HotspotList::iterator i; uint16 *idList = new uint16[res.activeHotspots().size()]; int idSize = 0; @@ -84,6 +80,20 @@ void Game::nextFrame() { debugC(ERROR_DETAILED, kLureDebugAnimations, "Hotspot ticks end"); delete[] idList; +} + +void Game::nextFrame() { + Resources &res = Resources::getReference(); + Room &room = Room::getReference(); + + if (Fights.isFighting()) + Fights.fightLoop(); + + res.pausedList().countdown(); + room.update(); + room.checkCursor(); + tick(); + Screen::getReference().update(); } @@ -137,6 +147,24 @@ void Game::execute() { break; } + // Handle special keys + bool handled = true; + switch (events.event().kbd.keycode) { + case SDLK_F5: + SaveRestoreDialog::show(true); + break; + + case SDLK_F7: + SaveRestoreDialog::show(false); + break; + + default: + handled = false; + } + if (handled) + continue; + + // Handle any remaining standard keys switch (events.event().kbd.ascii) { case 27: events.quitFlag = true; @@ -443,7 +471,7 @@ void Game::handleRightClickMenu() { strcat(statusLine, stringList.getString(S_FOR)); statusLine += strlen(statusLine); - itemId = PopupMenu::ShowItems(GET); + itemId = PopupMenu::ShowItems(GET, player->roomNumber()); breakFlag = ((itemId != 0xffff) && (itemId != 0xfffe)); break; @@ -570,6 +598,10 @@ bool Game::GetTellActions() { _tellCommands[0] = room.hotspotId(); _numTellCommands = 0; + // Set up a room transfer list + Common::List<uint16> roomList; + roomList.push_front(room.roomNumber()); + // Loop for getting tell commands while ((_numTellCommands >= 0) && (_numTellCommands < MAX_TELL_COMMANDS)) { @@ -618,9 +650,9 @@ bool Game::GetTellActions() { if (action != RETURN) { // Prompt for selection if ((action != USE) && (action != DRINK) && (action != GIVE)) - selectionId = PopupMenu::ShowItems(action); + selectionId = PopupMenu::ShowItems(action, *roomList.begin()); else - selectionId = PopupMenu::ShowItems(GET); + selectionId = PopupMenu::ShowItems(GET, *roomList.begin()); if ((selectionId == 0xffff) || (selectionId == 0xfffe)) { // Move back to prompting for action @@ -633,6 +665,7 @@ bool Game::GetTellActions() { if (selectionId < NOONE_ID) { // Must be a room selection strings.getString(selectionId, selectionName); + roomList.push_front(selectionId); } else { hotspot = res.getHotspot(selectionId); assert(hotspot); @@ -663,7 +696,7 @@ bool Game::GetTellActions() { } // Get the second parameter - selectionId = PopupMenu::ShowItems(GET); + selectionId = PopupMenu::ShowItems(GET, *roomList.begin()); if ((selectionId == 0xfffe) || (selectionId == 0xffff)) { --paramIndex; statusLine = statusLinePos[_numTellCommands][paramIndex]; @@ -712,9 +745,13 @@ bool Game::GetTellActions() { paramIndex = 0; else if ((action == ASK) || (action == GIVE) || (action == USE)) paramIndex = 2; - else + else { paramIndex = 1; - + if (action == GO_TO) + // Remove top of the cached room change list + roomList.erase(roomList.begin()); + } + statusLine = statusLinePos[_numTellCommands][paramIndex]; *statusLine = '\0'; } @@ -864,10 +901,6 @@ void Game::handleBootParam(int value) { room.setRoomNumber(2); break; - - default: - room.setRoomNumber(value); - break; } } diff --git a/engines/lure/game.h b/engines/lure/game.h index 43a146f2be..b1d1f8d21a 100644 --- a/engines/lure/game.h +++ b/engines/lure/game.h @@ -39,7 +39,7 @@ namespace Lure { -enum GameState {GS_RESTORE_RESTART = 1, GS_CAUGHT = 2}; +enum GameState {GS_RESTORE_RESTART = 1, GS_CAUGHT = 2, GS_EXIT = 3}; class Game { private: @@ -66,6 +66,7 @@ public: static Game &getReference(); + void tick(); void nextFrame(); void execute(); void setState(uint8 flags) { _state = flags; } diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp index 6cc863469a..82b4725a70 100644 --- a/engines/lure/hotspots.cpp +++ b/engines/lure/hotspots.cpp @@ -34,6 +34,7 @@ #include "lure/res_struct.h" #include "lure/events.h" #include "lure/game.h" +#include "lure/fights.h" #include "common/endian.h" namespace Lure { @@ -108,6 +109,7 @@ Hotspot::Hotspot(Hotspot *character, uint16 objType): _pathFinder(this) { _exitCtr = 0; _voiceCtr = 0; _walkFlag = false; + _skipFlag = false; switch (objType) { case VOICE_ANIM_ID: @@ -171,6 +173,9 @@ void Hotspot::setAnimation(uint16 newAnimId) { Resources &r = Resources::getReference(); HotspotAnimData *tempAnim; _animId = newAnimId; + if (_data) + _data->animRecordId = newAnimId; + if (newAnimId == 0) tempAnim = NULL; else { @@ -217,30 +222,29 @@ void Hotspot::setAnimation(HotspotAnimData *newRecord) { _anim = newRecord; MemoryBlock *src = Disk::getReference().getEntry(_anim->animId); - uint16 *numEntries = (uint16 *) src->data(); + uint16 numEntries = READ_LE_UINT16(src->data()); uint16 *headerEntry = (uint16 *) (src->data() + 2); - assert((*numEntries >= 1) && (*numEntries < 100)); + assert((numEntries >= 1) && (numEntries < 100)); // Calculate total needed size for output and create memory block to hold it uint32 totalSize = 0; - for (uint16 ctr = 0; ctr < *numEntries; ++ctr, ++headerEntry) { - totalSize += (*headerEntry + 31) / 32; + for (uint16 ctr = 0; ctr < numEntries; ++ctr, ++headerEntry) { + totalSize += (READ_LE_UINT16(headerEntry) + 31) / 32; } totalSize = (totalSize + 0x81) << 4; MemoryBlock *dest = Memory::allocate(totalSize); - uint32 srcStart = (*numEntries + 1) * sizeof(uint16) + 6; + uint32 srcStart = (numEntries + 1) * sizeof(uint16) + 6; AnimationDecoder::decode_data(src, dest, srcStart); - _numFrames = *numEntries; + _numFrames = numEntries; _frameNumber = 0; // Special handling need if (newRecord->animRecordId == SERF_ANIM_ID) { _frameStartsUsed = true; _frames = new Surface(416, 27); - } - else { + } else { _frames = new Surface(_width * _numFrames, _height); _frameStartsUsed = false; } @@ -350,7 +354,7 @@ void Hotspot::copyTo(Surface *dest) { return; // Reduce the source rectangle to only the on-screen portion - r.top += -(yPos + MENUBAR_Y_SIZE); + r.top += -yPos + MENUBAR_Y_SIZE; yPos = MENUBAR_Y_SIZE; } else if (yPos >= FULL_SCREEN_HEIGHT) @@ -414,9 +418,10 @@ bool Hotspot::executeScript() { } void Hotspot::tick() { - debugC(ERROR_BASIC, kLureDebugAnimations, "Hotspot %xh tick begin", _hotspotId); + uint16 id = _hotspotId; + debugC(ERROR_BASIC, kLureDebugAnimations, "Hotspot %xh tick begin", id); _tickHandler(*this); - debugC(ERROR_BASIC, kLureDebugAnimations, "Hotspot %xh tick end", _hotspotId); + debugC(ERROR_BASIC, kLureDebugAnimations, "Hotspot %xh tick end", id); } void Hotspot::setTickProc(uint16 newVal) { @@ -828,7 +833,7 @@ HotspotPrecheckResult Hotspot::actionPrecheck(HotspotData *hotspot) { } else if (hotspot->roomNumber != roomNumber()) { // loc_884 if (actionCtr() == 0) - converse(0, hotspotId()); + converse(NOONE_ID, 0); setActionCtr(0); return PC_NOT_IN_ROOM; } else if (actionCtr() != 0) { @@ -992,7 +997,6 @@ bool Hotspot::characterWalkingCheck(HotspotData *hotspot) { } // Default walking handling - // TODO: ANIM[27h] = 1 if hotspot has walk co-ordinates if ((ABS(x() - xp) >= 8) || (ABS(y() + heightCopy() - yp - 1) >= 19)) { walkTo(xp, yp); @@ -1242,7 +1246,8 @@ void Hotspot::doOpen(HotspotData *hotspot) { joinRec->blocked = 0; if (hotspotId() != PLAYER_ID) { - // TODO: HS[44h]=3, HS[42h]W = 4 + setCharacterMode(CHARMODE_PAUSED); + setDelayCtr(4); } } } @@ -1465,8 +1470,8 @@ void Hotspot::doTell(HotspotData *hotspot) { character->setBlockedFlag(false); for (int index = 1; index < cmdData.numParams(); index += 3) { - character->currentActions().addBack((Action) cmdData.param(index), - character->roomNumber(), cmdData.param(index + 1), cmdData.param(index + 2)); + character->currentActions().addBack((Action) cmdData.param(index), 0, + cmdData.param(index + 1), cmdData.param(index + 2)); } } } @@ -1966,8 +1971,8 @@ void Hotspot::npcJumpAddress(HotspotData *hotspot) { Resources &res = Resources::getReference(); ValueTableData &fields = res.fieldList(); int procIndex = _currentActions.top().supportData().param(0); - HotspotData *player; - CharacterScheduleEntry *newEntry; + Hotspot *player; + CharacterScheduleEntry *entry; endAction(); switch (procIndex) { @@ -1980,9 +1985,14 @@ void Hotspot::npcJumpAddress(HotspotData *hotspot) { break; case 1: - player = res.getHotspot(PLAYER_ID); - newEntry = res.charSchedules().getEntry(JUMP_ADDR_2_SUPPORT_ID, NULL); - _currentActions.top().setSupportData(newEntry); + player = res.getActiveHotspot(PLAYER_ID); + if (player->y() < 52) { + entry = res.charSchedules().getEntry(JUMP_ADDR_2_SUPPORT_ID, NULL); + assert(entry); + + _currentActions.clear(); + _currentActions.addFront(DISPATCH_ACTION, entry, ROOMNUM_CELLAR); + } break; default: @@ -2131,9 +2141,11 @@ HandlerMethodPtr HotspotTickHandlers::getHandler(uint16 procOffset) { case PLAYER_TICK_PROC_ID: return playerAnimHandler; case 0x7C14: + case FOLLOWER_TICK_PROC_2: return followerAnimHandler; - case 0x7EFA: - return skorlAnimHandler; + case JAILOR_TICK_PROC_ID: + case 0x7F02: + return jailorAnimHandler; case STANDARD_ANIM_2_TICK_PROC: return standardAnimHandler2; case STANDARD_ANIM_TICK_PROC: @@ -2163,16 +2175,30 @@ HandlerMethodPtr HotspotTickHandlers::getHandler(uint16 procOffset) { case 0x82A0: return barmanAnimHandler; case 0x85ce: - return skorlGaurdAnimHandler; + return skorlAnimHandler; case 0x862D: return gargoyleAnimHandler; + case GOEWIN_SHOP_TICK_PROC: + return goewinShopAnimHandler; case 0x86FA: case 0x86FF: + case 0x871E: + case 0x873D: + case 0x8742: + case 0x8747: return skullAnimHandler; + case 0x87B3: + return dragonFireAnimHandler; + case 0x87EC: + return castleSkorlAnimHandler; case 0x882A: return rackSerfAnimHandler; case TALK_TICK_PROC_ID: return talkAnimHandler; + case 0x982D: + return fighterAnimHandler; + case PLAYER_FIGHT_TICK_PROC_ID: + return playerFightAnimHandler; default: error("Unknown tick proc %xh for hotspot", procOffset); // return defaultHandler; @@ -2493,25 +2519,25 @@ void HotspotTickHandlers::voiceBubbleAnimHandler(Hotspot &h) { debugC(ERROR_DETAILED, kLureDebugAnimations, "Voice Bubble anim handler: char = %xh, ctr = %d, char speaking ctr = %d", h.hotspotId(), h.voiceCtr(), - res.getActiveHotspot(res.getTalkingCharacter())->resource()->talkCountdown); + res.getHotspot(res.getTalkingCharacter())->talkCountdown); if (h.voiceCtr() != 0) h.setVoiceCtr(h.voiceCtr() - 1); if (h.voiceCtr() != 0) { // Countdown not yet ended - Hotspot *charHotspot = res.getActiveHotspot(res.getTalkingCharacter()); - if (charHotspot->roomNumber() == h.roomNumber()) { + HotspotData *charHotspot = res.getHotspot(res.getTalkingCharacter()); + if (charHotspot->roomNumber == h.roomNumber()) { // Character is still in the same room as when it began speaking - if (charHotspot->resource()->talkCountdown != 0) { + if (charHotspot->talkCountdown != 0) { // Character still talking - if (!res.checkHotspotExtent(charHotspot->resource())) { + if (!res.checkHotspotExtent(charHotspot)) { // Set voice bubble off screen to hide it h.setPosition(h.x(), -100); } else { // Keep voice bubble in track with character - h.setPosition(charHotspot->x() + charHotspot->talkX() + 12, - charHotspot->y() + charHotspot->talkY() - 18); + h.setPosition(charHotspot->startX + charHotspot->talkX + 12, + charHotspot->startY + charHotspot->talkY - 18); } return; } @@ -2796,8 +2822,8 @@ void HotspotTickHandlers::followerAnimHandler(Hotspot &h) { ValueTableData &fields = res.fieldList(); Hotspot *player = res.getActiveHotspot(PLAYER_ID); - if ((fields.getField(37) == 0) && h.currentActions().isEmpty()) { - if (h.roomNumber() != player->roomNumber()) { + if ((h.resource()->tickProcOffset == FOLLOWER_TICK_PROC_2) || (fields.getField(37) == 0)) { + if (h.currentActions().isEmpty() && (h.roomNumber() != player->roomNumber())) { // Character in different room than player if (h.hotspotId() == GOEWIN_ID) h.currentActions().addFront(DISPATCH_ACTION, player->roomNumber()); @@ -2872,18 +2898,17 @@ void HotspotTickHandlers::followerAnimHandler(Hotspot &h) { standardCharacterAnimHandler(h); } -void HotspotTickHandlers::skorlAnimHandler(Hotspot &h) { +void HotspotTickHandlers::jailorAnimHandler(Hotspot &h) { Resources &res = Resources::getReference(); ValueTableData &fields = res.fieldList(); HotspotData *player = res.getHotspot(PLAYER_ID); - if ((fields.getField(11) != 0) && !h.skipFlag() && - (h.roomNumber() == player->roomNumber)) { - // TODO: Need extra check on data_669 - - if (Support::charactersIntersecting(h.resource(), player)) { - // Skorl has caught the player - Game::getReference().setState(GS_RESTORE_RESTART | GS_CAUGHT); + if ((fields.getField(11) != 0) || (h.hotspotId() == CASTLE_SKORL_ID)) { + if (!h.skipFlag() && (h.roomNumber() == player->roomNumber)) { + if (Support::charactersIntersecting(h.resource(), player)) { + // Skorl has caught the player + Game::getReference().setState(GS_RESTORE_RESTART | GS_CAUGHT); + } } } @@ -3290,6 +3315,14 @@ void HotspotTickHandlers::talkAnimHandler(Hotspot &h) { } } +void HotspotTickHandlers::fighterAnimHandler(Hotspot &h) { + Fights.fighterAnimHandler(h); +} + +void HotspotTickHandlers::playerFightAnimHandler(Hotspot &h) { + Fights.playerAnimHandler(h); +} + void HotspotTickHandlers::grubAnimHandler(Hotspot &h) { Resources &res = Resources::getReference(); h.handleTalkDialog(); @@ -3521,10 +3554,8 @@ void HotspotTickHandlers::barmanAnimHandler(Hotspot &h) { h.setFrameNumber(h.actionCtr()); } -void HotspotTickHandlers::skorlGaurdAnimHandler(Hotspot &h) { +void HotspotTickHandlers::skorlAnimHandler(Hotspot &h) { h.handleTalkDialog(); - - // Set the frame number h.setFrameNumber(h.actionCtr()); } @@ -3532,12 +3563,80 @@ void HotspotTickHandlers::gargoyleAnimHandler(Hotspot &h) { h.handleTalkDialog(); } +void HotspotTickHandlers::goewinShopAnimHandler(Hotspot &h) { + Resources &res = Resources::getReference(); + ValueTableData &fields = res.fieldList(); + + h.setDirection(UP); + h.setCharacterMode(CHARMODE_WAIT_FOR_INTERACT); + + h.handleTalkDialog(); + if (h.frameCtr() > 0) { + h.decrFrameCtr(); + return; + } + + h.executeScript(); + + if (h.delayCtr() > 0) { + h.setDelayCtr(h.delayCtr() - 1); + + if (h.delayCtr() == 0) { + Hotspot *playerHotspot = res.getActiveHotspot(PLAYER_ID); + uint16 talkIndex = fields.getField(TALK_INDEX); + + if ((talkIndex == 12) || (talkIndex == 13) || (talkIndex == 14) || + (playerHotspot->roomNumber() == 34)) + h.setDelayCtr(1500); + else + Script::normalGoewin(0, 0, 0); + } + } +} + void HotspotTickHandlers::skullAnimHandler(Hotspot &h) { Resources &res = Resources::getReference(); - RoomExitJoinData *joinRec = res.getExitJoin( - (h.hotspotId() == 0x42f) ? 0x272A : 0x272C); + uint16 doorId = 0x272E; + if ((h.hotspotId() == 0x42E) || (h.hotspotId() == 0x431) || (h.hotspotId() == 0x432)) + doorId = 0x272A; + else if ((h.hotspotId() == 0x42f) || (h.hotspotId() == 0x433)) + doorId = 0x272C; + + RoomExitJoinData *joinRec = res.getExitJoin(doorId); + if ((h.hotspotId() == 0x42E) || (h.hotspotId() == 0x42F)) { + h.setFrameNumber(joinRec->blocked ? 0 : 1); + } else { + h.setFrameNumber(joinRec->blocked ? 1 : 0); + } +} + +void HotspotTickHandlers::dragonFireAnimHandler(Hotspot &h) { + if (h.executeScript()) + // Script is finished - player is dead + Game::getReference().setState(GS_RESTORE_RESTART); +} + +void HotspotTickHandlers::castleSkorlAnimHandler(Hotspot &h) { + Resources &res = Resources::getReference(); + + h.handleTalkDialog(); + if (h.frameCtr() > 0) { + h.decrFrameCtr(); + return; + } - h.setFrameNumber(joinRec->blocked ? 0 : 1); + if (h.executeScript()) { + HotspotData *hotspot = res.getHotspot(h.hotspotId()); + assert(hotspot); + res.deactivateHotspot(hotspot->hotspotId); + hotspot->layer = 255; + hotspot->talkCountdown = 0; + hotspot->flags |= HOTSPOTFLAG_MENU_EXCLUSION; + + hotspot = res.getHotspot(CASTLE_SKORL_ID); + hotspot->roomNumber = 45; + res.activateHotspot(CASTLE_SKORL_ID); + } } void HotspotTickHandlers::rackSerfAnimHandler(Hotspot &h) { diff --git a/engines/lure/hotspots.h b/engines/lure/hotspots.h index 970f05414c..3f8bc544f6 100644 --- a/engines/lure/hotspots.h +++ b/engines/lure/hotspots.h @@ -67,7 +67,7 @@ private: static void roomExitAnimHandler(Hotspot &h); static void playerAnimHandler(Hotspot &h); static void followerAnimHandler(Hotspot &h); - static void skorlAnimHandler(Hotspot &h); + static void jailorAnimHandler(Hotspot &h); static void sonicRatAnimHandler(Hotspot &h); static void droppingTorchAnimHandler(Hotspot &h); static void playerSewerExitAnimHandler(Hotspot &h); @@ -81,11 +81,15 @@ private: static void talkAnimHandler(Hotspot &h); static void grubAnimHandler(Hotspot &h); static void barmanAnimHandler(Hotspot &h); - static void skorlGaurdAnimHandler(Hotspot &h); + static void skorlAnimHandler(Hotspot &h); static void gargoyleAnimHandler(Hotspot &h); + static void goewinShopAnimHandler(Hotspot &h); static void skullAnimHandler(Hotspot &h); + static void dragonFireAnimHandler(Hotspot &h); + static void castleSkorlAnimHandler(Hotspot &h); static void rackSerfAnimHandler(Hotspot &h); - + static void fighterAnimHandler(Hotspot &h); + static void playerFightAnimHandler(Hotspot &h); public: static HandlerMethodPtr getHandler(uint16 procOffset); }; @@ -129,6 +133,10 @@ public: class CurrentActionStack { private: ManagedList<CurrentActionEntry *> _actions; + void validateStack() { + if (_actions.size() > 20) + error("NPC character got an excessive number of pending actions"); + } public: CurrentActionStack() { _actions.clear(); } @@ -143,21 +151,27 @@ public: void addBack(CurrentAction newAction, uint16 roomNum) { _actions.push_back(new CurrentActionEntry(newAction, roomNum)); + validateStack(); } void addBack(CurrentAction newAction, CharacterScheduleEntry *rec, uint16 roomNum) { _actions.push_back(new CurrentActionEntry(newAction, rec, roomNum)); + validateStack(); } void addBack(Action newAction, uint16 roomNum, uint16 param1, uint16 param2) { _actions.push_back(new CurrentActionEntry(newAction, roomNum, param1, param2)); + validateStack(); } void addFront(CurrentAction newAction, uint16 roomNum) { _actions.push_front(new CurrentActionEntry(newAction, roomNum)); + validateStack(); } void addFront(CurrentAction newAction, CharacterScheduleEntry *rec, uint16 roomNum) { _actions.push_front(new CurrentActionEntry(newAction, rec, roomNum)); + validateStack(); } void addFront(Action newAction, uint16 roomNum, uint16 param1, uint16 param2) { _actions.push_front(new CurrentActionEntry(newAction, roomNum, param1, param2)); + validateStack(); } void saveToStream(WriteStream *stream); @@ -373,6 +387,8 @@ public: void setTickProc(uint16 newVal); bool persistant() { return _persistant; } void setPersistant(bool value) { _persistant = value; } + uint8 colourOffset() { return _colourOffset; } + void setColourOffset(uint8 value) { _colourOffset = value; } void setRoomNumber(uint16 roomNum) { _roomNumber = roomNum; if (_data) _data->roomNumber = roomNum; diff --git a/engines/lure/intro.cpp b/engines/lure/intro.cpp index e8107e2f1a..3f939c6389 100644 --- a/engines/lure/intro.cpp +++ b/engines/lure/intro.cpp @@ -47,47 +47,24 @@ static const AnimRecord anim_screens[] = {{0x40, 0, true, true}, {0x42, 1, false // should be aborted bool Introduction::showScreen(uint16 screenId, uint16 paletteId, uint16 delaySize) { + Events &events = Events::getReference(); _screen.screen().loadScreen(screenId); _screen.update(); Palette p(paletteId); _screen.paletteFadeIn(&p); - bool result = delay(delaySize); - if (Events::getReference().quitFlag) return true; + bool result = events.interruptableDelay(delaySize); + if (events.quitFlag) return true; _screen.paletteFadeOut(); return result; } -// delay -// Delays for a given number of milliseconds. If it returns true, it indicates that -// Escape has been pressed, and the introduction should be aborted. - -bool Introduction::delay(uint32 milliseconds) { - Events &events = Events::getReference(); - uint32 delayCtr = _system.getMillis() + milliseconds; - - while (_system.getMillis() < delayCtr) { - if (events.quitFlag) return true; - - if (events.pollEvent()) { - if (events.type() == Common::EVENT_KEYDOWN) - return events.event().kbd.keycode == 27; - else if (events.type() == Common::EVENT_LBUTTONDOWN) - return false; - } - - uint32 delayAmount = delayCtr - _system.getMillis(); - if (delayAmount > 10) delayAmount = 10; - _system.delayMillis(delayAmount); - } - return false; -} - // show // Main method for the introduction sequence bool Introduction::show() { + Events &events = Events::getReference(); _screen.setPaletteEmpty(); // Initial game company and then game screen @@ -109,13 +86,13 @@ bool Introduction::show() { anim = new AnimationSequence(_screen, _system, curr_anim->resourceId, coll.getPalette(curr_anim->paletteIndex), fadeIn); if (curr_anim->initialPause) - if (delay(12000)) return true; + if (events.interruptableDelay(12000)) return true; result = false; switch (anim->show()) { case ABORT_NONE: if (curr_anim->endingPause) { - result = delay(12000); + result = events.interruptableDelay(12000); } break; @@ -136,9 +113,9 @@ bool Introduction::show() { result = false; anim = new AnimationSequence(_screen, _system, 0x48, coll.getPalette(4), false); do { - result = delay(2000); + result = events.interruptableDelay(2000); _screen.paletteFadeOut(); - if (!result) result = delay(500); + if (!result) result = events.interruptableDelay(500); if (result) break; } while (anim->step()); delete anim; diff --git a/engines/lure/intro.h b/engines/lure/intro.h index 769081fdda..14c733e16b 100644 --- a/engines/lure/intro.h +++ b/engines/lure/intro.h @@ -36,7 +36,6 @@ private: OSystem &_system; bool showScreen(uint16 screenId, uint16 paletteId, uint16 delaySize); - bool delay(uint32 milliseconds); public: Introduction(Screen &screen, OSystem &system): _screen(screen), _system(system) {} diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp index 6b28753fd1..f7c4272f0e 100644 --- a/engines/lure/lure.cpp +++ b/engines/lure/lure.cpp @@ -44,6 +44,8 @@ LureEngine::LureEngine(OSystem *system): Engine(system) { Common::addSpecialDebugLevel(kLureDebugScripts, "scripts", "Scripts debugging"); Common::addSpecialDebugLevel(kLureDebugAnimations, "animations", "Animations debugging"); Common::addSpecialDebugLevel(kLureDebugHotspots, "hotspots", "Hotspots debugging"); + Common::addSpecialDebugLevel(kLureDebugFights, "fights", "Fights debugging"); + // Setup mixer /* if (!_mixer->isReady()) { @@ -75,6 +77,7 @@ int LureEngine::init() { _menu = new Menu(); Surface::initialise(); _room = new Room(); + _fights = new FightsManager(); int_engine = this; return 0; } @@ -85,6 +88,7 @@ LureEngine::~LureEngine() { // Delete and deinitialise subsystems Surface::deinitialise(); + delete _fights; delete _room; delete _menu; delete _events; @@ -146,6 +150,7 @@ bool LureEngine::saveGame(uint8 slotNumber, Common::String &caption) { Resources::getReference().saveToStream(f); Room::getReference().saveToStream(f); + Fights.saveToStream(f); delete f; return true; @@ -187,6 +192,7 @@ bool LureEngine::loadGame(uint8 slotNumber) { // Load in the data Resources::getReference().loadFromStream(f); Room::getReference().loadFromStream(f); + Fights.loadFromStream(f); delete f; return true; diff --git a/engines/lure/lure.h b/engines/lure/lure.h index 010361573a..aa7f0ae93a 100644 --- a/engines/lure/lure.h +++ b/engines/lure/lure.h @@ -38,6 +38,7 @@ #include "lure/menu.h" #include "lure/strings.h" #include "lure/room.h" +#include "lure/fights.h" namespace Lure { @@ -54,6 +55,7 @@ private: Menu *_menu; StringData *_strings; Room *_room; + FightsManager *_fights; void detectGame(); const char *generateSaveName(int slotNumber); diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h index 62c5490c8c..a715c4a1e7 100644 --- a/engines/lure/luredefs.h +++ b/engines/lure/luredefs.h @@ -34,7 +34,7 @@ namespace Lure { #define SUPPORT_FILENAME "lure.dat" #define LURE_DAT_MAJOR 1 -#define LURE_DAT_MINOR 19 +#define LURE_DAT_MINOR 20 #define LURE_DEBUG 1 @@ -44,7 +44,8 @@ namespace Lure { enum { kLureDebugScripts = 1 << 0, kLureDebugAnimations = 1 << 1, - kLureDebugHotspots = 1 << 2 + kLureDebugHotspots = 1 << 2, + kLureDebugFights = 1 << 3 }; #define ERROR_BASIC 1 @@ -126,6 +127,9 @@ enum Action { // Palette and animation for hiding in barrel #define BARREL_PALETTE_ID 0xE9F0 #define BARREL_ANIM_ID 0xE9F1 +// Endgame animation constants +#define ENDGAME_PALETTE_ID 0xFF00 +#define ENDGAME_ANIM_ID 0xFF01 // Specifies the maximum buffer sized allocated for decoding animation data #define MAX_ANIM_DECODER_BUFFER_SIZE 300000 @@ -142,14 +146,12 @@ enum Action { #define CURSOR_HEIGHT 16 #define CURSOR_SIZE 256 #define CURSOR_RESOURCE_ID 1 -#define CURSOR_ARROW 0 -#define CURSOR_DISK 1 -#define CURSOR_TIME_START 2 -#define CURSOR_TIME_END 9 -#define CURSOR_CROSS 10 -#define CURSOR_CAMERA 15 -#define CURSOR_TALK 16 -#define CURSOR_MENUBAR 17 + +enum CursorType {CURSOR_ARROW = 0, CURSOR_DISK = 1, CURSOR_TIME_START = 2, + CURSOR_TIME_END = 9, CURSOR_CROSS = 10, CURSOR_UP_ARROW = 11, CURSOR_DOWN_ARROW = 12, + CURSOR_LEFT_ARROW = 13, CURSOR_RIGHT_ARROW = 14, CURSOR_CAMERA = 15, CURSOR_TALK = 16, + CURSOR_MENUBAR = 17, CURSOR_FIGHT_UPPER = 23, CURSOR_FIGHT_MIDDLE = 24, + CURSOR_FIGHT_LOWER = 25}; // Font details #define FONT_RESOURCE_ID 4 @@ -216,7 +218,8 @@ enum Action { #define ROOM_PATHS_RESOURCE_ID 0x3f13 #define EXIT_COORDINATES_RESOURCE_ID 0x3f14 #define EXIT_HOTSPOT_ID_LIST 0x3f15 -#define STRING_LIST_RESOURCE_ID 0x3f16 +#define FIGHT_DATA_RESOURCE_ID 0x3f16 +#define STRING_LIST_RESOURCE_ID 0x3f17 // Script constants #define STARTUP_SCRIPT 0x23FC @@ -230,6 +233,8 @@ enum Action { #define SKORL_ID 0x3EA #define BLACKSMITH_ID 0x3EB #define GOEWIN_ID 0x3EF +#define WAYNE_ID 0x3f1 +#define CASTLE_SKORL_ID 0x3F3 #define FIRST_NONCHARACTER_ID 0x408 #define SACK_ID 0x40D #define PRISONER_ID 0x412 @@ -238,10 +243,12 @@ enum Action { #define TRANSFORM_ID 0x425 #define NELLIE_ID 0x429 #define EWAN_ID 0x436 -#define WAYNE_ID 0x3f1 +#define PIG_ID 0x43F +#define SKORL_FIGHTER_ID 0x444 #define START_EXIT_ID 0x2710 #define BOTTLE_HOTSPOT_ID 0x2710 #define BRICKS_ID 0x2714 +#define BOOK_ID 0x2723 #define START_NONVISUAL_HOTSPOT_ID 0x7530 // Milliseconds delay between game frames @@ -252,9 +259,13 @@ enum Action { #define PLAYER_TICK_PROC_ID 0x5E44 #define VOICE_TICK_PROC_ID 0x625E #define PUZZLED_TICK_PROC_ID 0x6571 +#define FOLLOWER_TICK_PROC_2 0x7C24 +#define JAILOR_TICK_PROC_ID 0x7efa #define STANDARD_ANIM_2_TICK_PROC 0x7F37 #define STANDARD_ANIM_TICK_PROC 0x7f3a +#define GOEWIN_SHOP_TICK_PROC 0x865A #define TALK_TICK_PROC_ID 0x8ABD +#define PLAYER_FIGHT_TICK_PROC_ID 0x98B6 // String constants #define STRANGER_ID 0x17A @@ -263,6 +274,7 @@ enum Action { // Misc constants #define GENERAL_MAGIC_ID 42 +#define PLAYER_FIGHT_ANIM_ID 0x55F6 #define VOICE_ANIM_ID 0x5810 #define PUZZLED_ANIM_ID 0x8001 #define EXCLAMATION_ANIM_ID 0x8002 @@ -279,6 +291,10 @@ enum Action { #define MAX_TELL_COMMANDS 8 #define MAX_SAVEGAME_SLOTS 10 +#define ROOMNUM_CAVE 38 +#define ROOMNUM_CELLAR 42 +#define ROOMNUM_DINING_HALL 45 + // Countdown for # operations in path finder before breaking until next // tick - set it to 0 if you'd like all pathfinding to be done at once //#define PATHFIND_COUNTDOWN 4000 @@ -290,12 +306,15 @@ enum Action { // Hotspot flags #define HOTSPOTFLAG_FOUND 0x80 #define HOTSPOTFLAG_SKIP 0x40 -#define HOTSPOTFLAG_20 0x20 +#define HOTSPOTFLAG_MENU_EXCLUSION 0x20 +#define HOTSPOTFLAG_ROOM_SPECIFIC 0x10 // Constants used to reference entries in the reworked support data entry lists #define RETURN_SUPPORT_ID 0x400 #define EXIT_BLOCKED_SUPPORT_ID 0x800 #define JUMP_ADDR_2_SUPPORT_ID 0x1403 +#define GOEWIN_CAVE_SUPPORT_ID 0x1800 +#define GOEWIN_STANDARD_SUPPORT_ID 0x1C00 // Constants used in animation Serf on the rack #define RACK_SERF_SCRIPT_ID_1 0x35C diff --git a/engines/lure/menu.cpp b/engines/lure/menu.cpp index 9c8a26a3f2..8b3003c808 100644 --- a/engines/lure/menu.cpp +++ b/engines/lure/menu.cpp @@ -257,7 +257,7 @@ uint16 PopupMenu::ShowInventory() { #define MAX_NUM_DISPLAY_ITEMS 20 -uint16 PopupMenu::ShowItems(Action contextAction) { +uint16 PopupMenu::ShowItems(Action contextAction, uint16 roomNumber) { Resources &res = Resources::getReference(); ValueTableData &fields = res.fieldList(); RoomDataList &rooms = res.roomData(); @@ -273,7 +273,6 @@ uint16 PopupMenu::ShowItems(Action contextAction) { char *entryNames[MAX_NUM_DISPLAY_ITEMS]; int numItems = 0; int itemCtr; - Hotspot *player = res.getActiveHotspot(PLAYER_ID); uint32 contextBitflag = 1 << (contextAction - 1); // Loop for rooms @@ -282,7 +281,7 @@ uint16 PopupMenu::ShowItems(Action contextAction) { // Pre-condition checks for whether to skip room if ((roomData->hdrFlags != 15) && ((roomData->hdrFlags & fields.hdrFlagMask()) == 0)) continue; - if (((roomData->flags & HOTSPOTFLAG_20) != 0) || ((roomData->flags & HOTSPOTFLAG_FOUND) == 0)) + if (((roomData->flags & HOTSPOTFLAG_MENU_EXCLUSION) != 0) || ((roomData->flags & HOTSPOTFLAG_FOUND) == 0)) continue; if ((roomData->actions & contextBitflag) == 0) continue; @@ -304,20 +303,21 @@ uint16 PopupMenu::ShowItems(Action contextAction) { ((hotspot->headerFlags & fields.hdrFlagMask()) == 0)) continue; - if (((hotspot->flags & HOTSPOTFLAG_20) != 0) || ((hotspot->flags & HOTSPOTFLAG_FOUND) == 0)) + if (((hotspot->flags & HOTSPOTFLAG_MENU_EXCLUSION) != 0) || ((hotspot->flags & HOTSPOTFLAG_FOUND) == 0)) // Skip the current hotspot continue; - // Following checks are done for room list - still need to include check against [3350h] - if (((hotspot->flags & 0x10) != 0) && (hotspot->roomNumber != player->roomNumber())) + // If the hotspot is room specific, skip if the character will not be in the specified room + if (((hotspot->flags & HOTSPOTFLAG_ROOM_SPECIFIC) != 0) && + (hotspot->roomNumber != roomNumber)) continue; + // If hotspot does not allow action, then skip it if ((hotspot->actions & contextBitflag) == 0) - // If hotspot does not allow action, then skip it continue; + // If a special hotspot Id, then skip displaying if ((hotspot->nameId == 0x17A) || (hotspot->nameId == 0x147)) - // Special hotspot names to skip continue; // Check if the hotspot's name is already used in an already set item diff --git a/engines/lure/menu.h b/engines/lure/menu.h index 6a639f7ec5..587074e8af 100644 --- a/engines/lure/menu.h +++ b/engines/lure/menu.h @@ -83,7 +83,7 @@ public: static Action Show(int numEntries, Action *actions); static uint16 Show(int numEntries, const char *actions[]); static uint16 ShowInventory(); - static uint16 ShowItems(Action contextAction); + static uint16 ShowItems(Action contextAction, uint16 roomNumber); }; } // End of namespace Lure diff --git a/engines/lure/res.cpp b/engines/lure/res.cpp index 3c183ebafc..4da38eddc7 100644 --- a/engines/lure/res.cpp +++ b/engines/lure/res.cpp @@ -268,7 +268,7 @@ void Resources::reloadData() { // Load in the list of room exit coordinates mb = d.getEntry(EXIT_COORDINATES_RESOURCE_ID); RoomExitCoordinateEntryResource *coordRec = (RoomExitCoordinateEntryResource *) mb->data(); - while (*((uint16 *) coordRec) != 0xffff) { + while (READ_LE_UINT16(coordRec) != 0xffff) { RoomExitCoordinates *newEntry = new RoomExitCoordinates(coordRec); _coordinateList.push_back(newEntry); ++coordRec; diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp index 1ca4394ad3..79bf0dfe6e 100644 --- a/engines/lure/res_struct.cpp +++ b/engines/lure/res_struct.cpp @@ -94,6 +94,8 @@ RoomData::RoomData(RoomResource *rec, MemoryBlock *pathData) { clippingXStart = FROM_LE_16(rec->clippingXStart); clippingXEnd = FROM_LE_16(rec->clippingXEnd); + exitTime = FROM_LE_32(rec->exitTime); + areaFlag = rec->areaFlag; walkBounds.left = FROM_LE_16(rec->walkBounds.xs); walkBounds.right = FROM_LE_16(rec->walkBounds.xe); walkBounds.top = FROM_LE_16(rec->walkBounds.ys); @@ -285,6 +287,7 @@ void RoomDataList::saveToStream(WriteStream *stream) { for (i = begin(); i != end(); ++i) { RoomData *rec = *i; + stream->writeByte(rec->flags); const byte *pathData = rec->paths.data(); stream->write(pathData, ROOM_PATHS_HEIGHT * ROOM_PATHS_WIDTH); } @@ -296,6 +299,7 @@ void RoomDataList::loadFromStream(ReadStream *stream) { for (i = begin(); i != end(); ++i) { RoomData *rec = *i; + rec->flags = stream->readByte(); stream->read(data, ROOM_PATHS_HEIGHT * ROOM_PATHS_WIDTH); rec->paths.load(data); } @@ -730,6 +734,7 @@ void SequenceDelayList::add(uint16 delay, uint16 seqOffset, bool canClear) { } void SequenceDelayList::tick() { + Resources &res = Resources::getReference(); uint32 currTime = g_system->getMillis(); SequenceDelayList::iterator i; @@ -738,6 +743,15 @@ void SequenceDelayList::tick() { if (currTime >= entry->timeoutCtr) { // Timeout reached - delete entry from list and execute the sequence uint16 seqOffset = entry->sequenceOffset; + + // FIXME: At current speed the player can enter the cave a bit too quickly ahead of Goewin. + // Use a hard-coded check to make sure Goewin is in the room + if (seqOffset == 0xebd) { + Hotspot *goewinHotspot = res.getActiveHotspot(GOEWIN_ID); + if (goewinHotspot->roomNumber() != 38) + return; + } + erase(i); Script::execute(seqOffset); return; diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h index 55907e4c12..59581b9c7d 100644 --- a/engines/lure/res_struct.h +++ b/engines/lure/res_struct.h @@ -129,6 +129,8 @@ struct RoomResource { uint16 sequenceOffset; int16 clippingXStart; int16 clippingXEnd; + uint32 exitTime; + uint8 areaFlag; RoomRect walkBounds; uint16 numExits; }; @@ -206,8 +208,8 @@ struct RoomExitCoordinateResource { #define ROOM_EXIT_COORDINATES_NUM_ROOMS 52 struct RoomExitCoordinateEntryResource { - RoomExitCoordinateResource entries[ROOM_EXIT_COORDINATES_NUM_ENTRIES]; uint8 roomIndex[ROOM_EXIT_COORDINATES_NUM_ROOMS]; + RoomExitCoordinateResource entries[ROOM_EXIT_COORDINATES_NUM_ENTRIES]; }; #define MAX_SCHEDULE_ENTRY_PARAMS 5 @@ -337,6 +339,8 @@ public: uint16 sequenceOffset; int16 clippingXStart; int16 clippingXEnd; + uint8 areaFlag; + uint32 exitTime; Common::Rect walkBounds; RoomExitHotspotList exitHotspots; RoomExitList exits; diff --git a/engines/lure/room.cpp b/engines/lure/room.cpp index a2abd3565d..016432dfac 100644 --- a/engines/lure/room.cpp +++ b/engines/lure/room.cpp @@ -1,8 +1,5 @@ -/* 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. +/* ScummVM - Scumm Interpreter + * Copyright (C) 2005-2006 The ScummVM project * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -171,7 +168,7 @@ void Room::checkRoomHotspots() { if (!skipFlag) { skipFlag = (((entry->flags & HOTSPOTFLAG_FOUND) == 0) && ((entry->flags & HOTSPOTFLAG_SKIP) != 0)) || - ((entry->flags & HOTSPOTFLAG_20) != 0); + ((entry->flags & HOTSPOTFLAG_MENU_EXCLUSION) != 0); } if ((!skipFlag) && (entry->hotspotId < 0x409)) @@ -225,7 +222,7 @@ void Room::checkRoomHotspots() { } } -uint8 Room::checkRoomExits() { +CursorType Room::checkRoomExits() { Mouse &m = Mouse::getReference(); Resources &res = Resources::getReference(); _destRoomNumber = 0; @@ -249,7 +246,7 @@ uint8 Room::checkRoomExits() { if (!skipFlag && (m.x() >= rec->xs) && (m.x() <= rec->xe) && (m.y() >= rec->ys) && (m.y() <= rec->ye)) { // Cursor is within exit area - uint8 cursorNum = rec->cursorNum; + CursorType cursorNum = (CursorType)rec->cursorNum; _destRoomNumber = rec->destRoomNumber; // If it's a hotspotted exit, change arrow to the + arrow @@ -258,7 +255,7 @@ uint8 Room::checkRoomExits() { _hotspot = res.getHotspot(_hotspotId); _hotspotNameId = _hotspot->nameId; _isExit = true; - cursorNum += 7; + cursorNum = (CursorType)((int)cursorNum + 7); } return cursorNum; @@ -315,6 +312,9 @@ void Room::addLayers(Hotspot &h) { int16 yEnd = (hsY + h.heightCopy() - 1) / RECT_SIZE; int16 numY = yEnd - yStart + 1; + if ((xStart < 0) || (yEnd < 0)) + return; + for (int16 xCtr = 0; xCtr < numX; ++xCtr, ++xStart) { int16 xs = xStart - 4; if (xs < 0) continue; @@ -457,6 +457,11 @@ void Room::update() { Memory::dealloc(statusLineCopy); } + // Debug - if the bottle object is on layer 0FEh, then display it's surface + Hotspot *displayHotspot = res.getActiveHotspot(BOTTLE_HOTSPOT_ID); + if ((displayHotspot != NULL) && (displayHotspot->layer() == 0xfe)) + displayHotspot->frames().copyTo(&s); + // If show information is turned on, show extra debugging information if (_showInfo) { char buffer[64]; @@ -490,6 +495,7 @@ void Room::setRoomNumber(uint16 newRoomNumber, bool showOverlay) { _roomData = r.getRoom(newRoomNumber); if (!_roomData) error("Tried to change to non-existant room: %d", newRoomNumber); + bool leaveFlag = (_layers[0] && (newRoomNumber != _roomNumber)); _roomNumber = _roomData->roomNumber; _descId = _roomData->descId; @@ -497,7 +503,7 @@ void Room::setRoomNumber(uint16 newRoomNumber, bool showOverlay) { _screen.empty(); _screen.resetPalette(); - if (_layers[0]) leaveRoom(); + if (leaveFlag) leaveRoom(); _numLayers = _roomData->numLayers; if (showOverlay) ++_numLayers; @@ -532,15 +538,15 @@ void Room::checkCursor() { Mouse &mouse = Mouse::getReference(); Resources &res = Resources::getReference(); uint16 oldHotspotId = _hotspotId; - uint16 currentCursor = mouse.getCursorNum(); - uint16 newCursor = currentCursor; + CursorType currentCursor = mouse.getCursorNum(); + CursorType newCursor = currentCursor; CurrentAction playerAction = res.getActiveHotspot(PLAYER_ID)->currentActions().action(); uint16 oldRoomNumber = res.fieldList().getField(OLD_ROOM_NUMBER); if ((currentCursor >= CURSOR_TIME_START) && (currentCursor <= CURSOR_TIME_END) && ((playerAction == START_WALKING) || (playerAction == PROCESSING_PATH))) { // Animate the clock when processing the player path - ++newCursor; + newCursor = (CursorType)((int)newCursor + 1); if (newCursor == CURSOR_CROSS) newCursor = CURSOR_TIME_START; } else if (checkInTalkDialog() && (oldRoomNumber == 0)) { newCursor = CURSOR_TALK; @@ -628,8 +634,8 @@ void Room::saveToStream(Common::WriteStream *stream) { } void Room::loadFromStream(Common::ReadStream *stream) { - int roomNum = stream->readUint16LE(); - setRoomNumber(roomNum, false); + _roomNumber = stream->readUint16LE(); + setRoomNumber(_roomNumber, false); _destRoomNumber = stream->readUint16LE(); _showInfo = stream->readByte() != 0; diff --git a/engines/lure/room.h b/engines/lure/room.h index d991f36c92..6c5dfc6747 100644 --- a/engines/lure/room.h +++ b/engines/lure/room.h @@ -78,7 +78,7 @@ private: CursorState _cursorState; void checkRoomHotspots(); - uint8 checkRoomExits(); + CursorType checkRoomExits(); void loadRoomHotspots(); bool sub_112() { return false; } // not yet implemented void flagCoveredCells(Hotspot &h); |