aboutsummaryrefslogtreecommitdiff
path: root/engines/lure/hotspots.cpp
diff options
context:
space:
mode:
authorPaul Gilbert2007-06-22 12:36:04 +0000
committerPaul Gilbert2007-06-22 12:36:04 +0000
commit8b3821e9ff5b60ee75d180514ca8b067bd5a0105 (patch)
tree2e07798aec37da5ec665ac09e08ee6eca231e8f7 /engines/lure/hotspots.cpp
parent707e62e669b227e0baf7a8c976283b32cef20b9d (diff)
downloadscummvm-rg350-8b3821e9ff5b60ee75d180514ca8b067bd5a0105.tar.gz
scummvm-rg350-8b3821e9ff5b60ee75d180514ca8b067bd5a0105.tar.bz2
scummvm-rg350-8b3821e9ff5b60ee75d180514ca8b067bd5a0105.zip
Lots of bugfixes - game is now completable
svn-id: r27606
Diffstat (limited to 'engines/lure/hotspots.cpp')
-rw-r--r--engines/lure/hotspots.cpp193
1 files changed, 146 insertions, 47 deletions
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) {