aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/lure/events.cpp37
-rw-r--r--engines/lure/events.h14
-rw-r--r--engines/lure/game.cpp73
-rw-r--r--engines/lure/game.h3
-rw-r--r--engines/lure/hotspots.cpp193
-rw-r--r--engines/lure/hotspots.h22
-rw-r--r--engines/lure/intro.cpp39
-rw-r--r--engines/lure/intro.h1
-rw-r--r--engines/lure/lure.cpp6
-rw-r--r--engines/lure/lure.h2
-rw-r--r--engines/lure/luredefs.h45
-rw-r--r--engines/lure/menu.cpp16
-rw-r--r--engines/lure/menu.h2
-rw-r--r--engines/lure/res.cpp2
-rw-r--r--engines/lure/res_struct.cpp14
-rw-r--r--engines/lure/res_struct.h6
-rw-r--r--engines/lure/room.cpp36
-rw-r--r--engines/lure/room.h2
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);