aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2006-05-29 08:12:07 +0000
committerPaul Gilbert2006-05-29 08:12:07 +0000
commit5fa3985bcbd96558d8adb0e306f1cfd0b10b2e03 (patch)
treef430e8398c3adef77ba6b09540839e9ba3ffef7d /engines
parent5d562eb3c588345b93f8c21a3f076a02bbe5a454 (diff)
downloadscummvm-rg350-5fa3985bcbd96558d8adb0e306f1cfd0b10b2e03.tar.gz
scummvm-rg350-5fa3985bcbd96558d8adb0e306f1cfd0b10b2e03.tar.bz2
scummvm-rg350-5fa3985bcbd96558d8adb0e306f1cfd0b10b2e03.zip
Player now moves out of the way if he's blocking an entrance when an NPC enters. Also changed errors in unimplemented NPC actions to warnings
svn-id: r22731
Diffstat (limited to 'engines')
-rw-r--r--engines/lure/game.cpp2
-rw-r--r--engines/lure/hotspots.cpp193
-rw-r--r--engines/lure/hotspots.h35
-rw-r--r--engines/lure/res_struct.cpp5
-rw-r--r--engines/lure/res_struct.h9
-rw-r--r--engines/lure/room.cpp4
-rw-r--r--engines/lure/room.h2
7 files changed, 201 insertions, 49 deletions
diff --git a/engines/lure/game.cpp b/engines/lure/game.cpp
index 8f5eaeb449..5c3fb365b1 100644
--- a/engines/lure/game.cpp
+++ b/engines/lure/game.cpp
@@ -310,7 +310,7 @@ void Game::handleClick() {
if (response != MENUITEM_NONE)
handleMenuResponse(response);
} else if ((room.cursorState() == CS_SEQUENCE) ||
- (room.cursorState() == CS_UNKNOWN)) {
+ (room.cursorState() == CS_BUMPED)) {
// No action necessary
} else {
if (mouse.lButton())
diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp
index 83ae3995cf..52ec0eb4f1 100644
--- a/engines/lure/hotspots.cpp
+++ b/engines/lure/hotspots.cpp
@@ -75,6 +75,8 @@ Hotspot::Hotspot(HotspotData *res): _pathFinder(this) {
_actionCtr = 0;
_blockedOffset = 0;
_exitCtr = 0;
+ _blockedState = BS_NONE;
+ _unknownFlag = false;
if (_data->npcSchedule != 0) {
CharacterScheduleEntry *entry = resources.charSchedules().getEntry(_data->npcSchedule);
@@ -96,6 +98,8 @@ Hotspot::Hotspot(Hotspot *character, uint16 objType): _pathFinder(this) {
_destHotspotId = character->hotspotId();
_blockedOffset = 0;
_exitCtr = 0;
+ _blockedState = BS_NONE;
+ _unknownFlag = false;
switch (objType) {
case VOICE_ANIM_ID:
@@ -389,6 +393,31 @@ void Hotspot::faceHotspot(HotspotData *hotspot) {
}
}
+// Sets a character walking to a random destination position
+
+void Hotspot::setRandomDest() {
+ Resources &res = Resources::getReference();
+ RoomData *roomData = res.getRoom(roomNumber());
+ Common::Rect &rect = roomData->walkBounds;
+ Common::RandomSource _rnd;
+ int tryCtr = 0;
+ int16 xp, yp;
+
+ if (_currentActions.isEmpty())
+ _currentActions.addFront(START_WALKING, roomNumber());
+ else
+ _currentActions.top().setAction(START_WALKING);
+
+ while (tryCtr ++ <= 20) {
+ xp = rect.left + _rnd.getRandomNumber(rect.right - rect.left);
+ yp = rect.left + _rnd.getRandomNumber(rect.right - rect.left);
+ setDestPosition(xp, yp);
+
+ if (!roomData->paths.isOccupied(xp, yp) && !roomData->paths.isOccupied(xp, yp))
+ break;
+ }
+}
+
// Sets or clears the hotspot as occupying an area in its room's pathfinding data
void Hotspot::setOccupied(bool occupiedFlag) {
@@ -464,6 +493,30 @@ bool Hotspot::walkingStep() {
return false;
}
+void Hotspot::updateMovement() {
+ assert(_data != NULL);
+ if (_currentActions.action() == EXEC_HOTSPOT_SCRIPT) {
+ if (_data->coveredFlag) {
+ // Reset position and direction
+ resetPosition();
+ } else {
+ // Make sure the cell occupied by character is covered
+ _data->coveredFlag = true;
+ setOccupied(true);
+ }
+ }
+}
+
+void Hotspot::updateMovement2(CharacterMode value) {
+ setCharacterMode(value);
+ updateMovement();
+}
+
+void Hotspot::resetPosition() {
+ setPosition(x() & 0xf8 | 5, y());
+ setDirection(direction());
+}
+
/*-------------------------------------------------------------------------*/
/* Hotspot action handling */
/* */
@@ -1302,7 +1355,7 @@ void Hotspot::npcUnknown2(HotspotData *hotspot) {
void Hotspot::npcSetRandomDest(HotspotData *hotspot) {
endAction();
- Support::setRandomDest(*this);
+ setRandomDest();
}
void Hotspot::npcWalkingCheck(HotspotData *hotspot) {
@@ -1373,19 +1426,23 @@ void Hotspot::npcDispatchAction(HotspotData *hotspot) {
}
void Hotspot::npcUnknown3(HotspotData *hotspot) {
- error("npcUnknown3: Not yet implemented");
+ warning("npcUnknown3: Not yet implemented");
+ endAction();
}
void Hotspot::npcUnknown4(HotspotData *hotspot) {
- error("npcUnknown4: Not yet implemented");
+ warning("npcUnknown4: Not yet implemented");
+ endAction();
}
void Hotspot::npcStartTalking(HotspotData *hotspot) {
- error("npcStartTalking: Not yet implemented");
+ warning("npcStartTalking: Not yet implemented");
+ endAction();
}
void Hotspot::npcJumpAddress(HotspotData *hotspot) {
- error("npcJumpAddress: Not yet implemented");
+ warning("npcJumpAddress: Not yet implemented");
+ endAction();
}
/*------------------------------------------------------------------------*/
@@ -1460,7 +1517,7 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
CurrentActionStack &actions = h.currentActions();
uint16 impingingList[MAX_NUM_IMPINGING];
int numImpinging;
- int index;
+ bool bumpedPlayer;
// TODO: handle talk dialogs countdown if necessary
@@ -1471,26 +1528,74 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
}
numImpinging = Support::findIntersectingCharacters(h, impingingList);
+ bumpedPlayer = (numImpinging == 0) ? false :
+ Support::isCharacterInList(impingingList, numImpinging, PLAYER_ID);
+
+ // Check for character having just changed room
if (h.skipFlag()) {
if (numImpinging > 0) {
- index = 0;
- while ((index < numImpinging) && (impingingList[index] != PLAYER_ID))
- ++index;
-
- if (index != numImpinging) {
- // Character has bumped into player
- // TODO: Figure out handling code
- error("Unimplemented - character bumping into player");
+ // Scan to check if the character has bumped into player
+ Hotspot *player = res.getActiveHotspot(PLAYER_ID);
+
+ if (bumpedPlayer && (player->characterMode() == CHARMODE_IDLE)) {
+ // Signal the player to move out of the way automatically
+ player->setBlockedState(BS_INITIAL);
+ player->setDestHotspot(0);
+
+ Room::getReference().setCursorState(CS_BUMPED);
+ player->setRandomDest();
+ } else {
+ // Signal the character to pause briefly to allow bumped
+ // character time to start moving out of the way
+ h.setDelayCtr(10);
+ h.setCharacterMode(CHARMODE_PAUSED);
}
return;
}
-
+
h.setSkipFlag(false);
}
// TODO: Handling of any set Tick Script Offset, as well as certain other
// as of yet unknown hotspot flags
+ if (h.characterMode() != CHARMODE_NONE) {
+ if (h.characterMode() == CHARMODE_6) {
+ // TODO: Figure out what mode 6 is
+ h.updateMovement();
+ if (bumpedPlayer) return;
+
+ } else {
+ // All other character modes
+ if (h.delayCtr() > 0) {
+ // There is some countdown left to do
+ bool decrementFlag = true; //TODO: = HS[50h] == 0
+
+ if (!decrementFlag) {
+ HotspotData *hotspot = res.getHotspot(0); // TODO: HS[50h]
+ decrementFlag = (hotspot->roomNumber != h.roomNumber()) ? false :
+ Support::charactersIntersecting(hotspot, h.resource());
+ }
+
+ if (decrementFlag) {
+ h.setDelayCtr(h.delayCtr() - 1);
+ return;
+ }
+ }
+ }
+
+ // TODO: HS[50h]=0
+ CharacterMode currentMode = h.characterMode();
+ h.setCharacterMode(CHARMODE_NONE);
+ h.pathFinder().clear();
+
+ if ((currentMode == CHARMODE_4) || (currentMode == CHARMODE_7)) {
+ // TODO: HS[33h]=0
+ Dialog::showMessage(1, h.hotspotId());
+ }
+ return;
+ }
+
CurrentAction action = actions.action();
switch (action) {
@@ -1639,6 +1744,7 @@ void HotspotTickHandlers::playerAnimHandler(Hotspot &h) {
case NO_ACTION:
// Make sure there is no longer any destination
h.setDestHotspot(0);
+ h.updateMovement2(CHARMODE_IDLE);
break;
case DISPATCH_ACTION:
@@ -1678,9 +1784,17 @@ void HotspotTickHandlers::playerAnimHandler(Hotspot &h) {
// Deliberate fall through to processing walking path
case PROCESSING_PATH:
+ h.setCharacterMode(CHARMODE_NONE);
if (!pathFinder.process()) break;
// Pathfinding is now complete
+/*
+ if ((pathFinder.result() != PF_OK) && (h.unknownFlag() ||
+ (pathFinder.result() != PF_DEST_OCCUPIED))) {
+ // TODO: occupiedFlag
+
+ }
+*/
actions.pop();
if (pathFinder.isEmpty()) {
@@ -1709,6 +1823,9 @@ void HotspotTickHandlers::playerAnimHandler(Hotspot &h) {
if (h.walkingStep()) {
// Walking done
+ Room &room = Room::getReference();
+ if (room.cursorState() == CS_BUMPED)
+ room.setCursorState(CS_NONE);
h.currentActions().pop();
}
@@ -2003,7 +2120,7 @@ void HotspotTickHandlers::npcRoomChange(Hotspot &h) {
}
if (numCharacters >= 4) {
-error("npcChangeRoom - too many characters - yet to be tested");
+warning("XYZZY npcChangeRoom - too many characters - yet to be tested");
uint16 dataId = res.getCharOffset(0);
CharacterScheduleEntry *entry = res.charSchedules().getEntry(dataId);
h.currentActions().addFront(DISPATCH_ACTION, entry, h.roomNumber());
@@ -2062,14 +2179,18 @@ PathFinder::PathFinder(Hotspot *h) {
_stepCtr = 0;
}
-void PathFinder::reset(RoomPathsData &src) {
+void PathFinder::clear() {
_stepCtr = 0;
_list.clear();
- src.decompress(_layer, _hotspot->widthCopy());
_inProgress = false;
_countdownCtr = PATHFIND_COUNTDOWN;
}
+void PathFinder::reset(RoomPathsData &src) {
+ clear();
+ src.decompress(_layer, _hotspot->widthCopy());
+}
+
// Does the next stage of processing to figure out a path to take to a given
// destination. Returns true if the path finding has been completed
@@ -2439,6 +2560,7 @@ int Support::findIntersectingCharacters(Hotspot &h, uint16 *charList) {
int numImpinging = 0;
Resources &res = Resources::getReference();
Rect r;
+ uint16 hotspotY;
r.left = h.x();
r.right = h.x() + h.widthCopy();
@@ -2456,12 +2578,13 @@ int Support::findIntersectingCharacters(Hotspot &h, uint16 *charList) {
hotspot.skipFlag()) continue;
// TODO: See why si+ANIM_HOTSPOT_OFFSET compared aganst di+ANIM_VOICE_CTR
+ hotspotY = hotspot.y() + hotspot.heightCopy();
+
if ((hotspot.x() > r.right) || (hotspot.x() + hotspot.widthCopy() <= r.left) ||
- (hotspot.y() + hotspot.heightCopy() + hotspot.charRectY() > r.bottom) ||
- (hotspot.y() + hotspot.heightCopy() - hotspot.charRectY()
- - hotspot.yCorrection() <= r.top))
+ (hotspotY + hotspot.charRectY() < r.top) ||
+ (hotspotY - hotspot.charRectY() - hotspot.yCorrection() >= r.bottom))
continue;
-
+
// Add hotspot Id to list
if (numImpinging == MAX_NUM_IMPINGING)
error("Exceeded maximum allowable number of impinging characters");
@@ -2534,26 +2657,6 @@ void Support::characterChangeRoom(Hotspot &h, uint16 roomNumber,
}
}
-void Support::setRandomDest(Hotspot &h) {
- Resources &res = Resources::getReference();
- RoomData *roomData = res.getRoom(h.roomNumber());
- Common::Rect &rect = roomData->walkBounds;
- Common::RandomSource _rnd;
- int tryCtr = 0;
- int16 xp, yp;
-
- h.currentActions().top().setAction(DISPATCH_ACTION);
-
- while (tryCtr ++ <= 20) {
- xp = rect.left + _rnd.getRandomNumber(rect.right - rect.left);
- yp = rect.left + _rnd.getRandomNumber(rect.right - rect.left);
- h.setDestPosition(xp, yp);
-
- if (!roomData->paths.isOccupied(xp, yp) && !roomData->paths.isOccupied(xp, yp))
- break;
- }
-}
-
bool Support::charactersIntersecting(HotspotData *hotspot1, HotspotData *hotspot2) {
return !((hotspot1->startX + hotspot1->widthCopy + 4 < hotspot2->startX) ||
(hotspot2->startX + hotspot2->widthCopy + 4 < hotspot1->startX) ||
@@ -2563,4 +2666,10 @@ bool Support::charactersIntersecting(HotspotData *hotspot1, HotspotData *hotspot
hotspot1->startY + hotspot1->heightCopy - hotspot1->yCorrection - 2));
}
+bool Support::isCharacterInList(uint16 *lst, int numEntries, uint16 charId) {
+ while (numEntries-- > 0)
+ if (*lst++ == charId) return true;
+ return false;
+}
+
} // end of namespace Lure
diff --git a/engines/lure/hotspots.h b/engines/lure/hotspots.h
index 4f5649b3c8..8e18827092 100644
--- a/engines/lure/hotspots.h
+++ b/engines/lure/hotspots.h
@@ -41,8 +41,8 @@ public:
static void checkRoomChange(Hotspot &h);
static void characterChangeRoom(Hotspot &h, uint16 roomNumber,
int16 newX, int16 newY, Direction dir);
- static void setRandomDest(Hotspot &h);
static bool charactersIntersecting(HotspotData *hotspot1, HotspotData *hotspot2);
+ static bool isCharacterInList(uint16 *lst, int numEntries, uint16 charId);
};
typedef void(*HandlerMethodPtr)(Hotspot &h);
@@ -172,9 +172,9 @@ private:
void addBack(Direction dir, int steps) {
_list.push_back(new WalkingActionEntry(dir, steps));
}
- void clear() { _list.clear(); }
public:
PathFinder(Hotspot *h);
+ void clear();
void reset(RoomPathsData &src);
bool process();
void list();
@@ -183,10 +183,13 @@ public:
WalkingActionEntry &top() { return **_list.begin(); }
bool isEmpty() { return _list.empty(); }
int &stepCtr() { return _stepCtr; }
+ PathFinderResult result() { return _result; }
};
enum HotspotPrecheckResult {PC_EXECUTE, PC_NOT_IN_ROOM, PC_UNKNOWN, PC_INITIAL, PC_EXCESS};
+enum BlockedState {BS_NONE, BS_INITIAL, BS_UNKNOWN};
+
class Hotspot {
private:
HotspotData *_data;
@@ -224,6 +227,8 @@ private:
uint16 _destHotspotId;
uint16 _blockedOffset;
uint8 _exitCtr;
+ BlockedState _blockedState;
+ bool _unknownFlag;
// Support methods
void startTalk(HotspotData *charHotspot);
@@ -234,6 +239,7 @@ private:
void actionPrecheck3(HotspotData *hotspot);
bool characterWalkingCheck(HotspotData *hotspot);
bool doorCloseCheck(uint16 doorId);
+ void resetDirection();
// Action set
void doNothing(HotspotData *hotspot);
@@ -295,6 +301,8 @@ public:
uint16 destHotspotId() { return _destHotspotId; }
uint16 blockedOffset() { return _blockedOffset; }
uint8 exitCtr() { return _exitCtr; }
+ BlockedState blockedState() { return _blockedState; }
+ bool unknownFlag() { return _unknownFlag; }
uint16 width() { return _width; }
uint16 height() { return _height; }
uint16 widthCopy() { return _widthCopy; }
@@ -320,14 +328,33 @@ public:
void setDestPosition(int16 newX, int16 newY) { _destX = newX; _destY = newY; }
void setDestHotspot(uint16 id) { _destHotspotId = id; }
void setExitCtr(uint8 value) { _exitCtr = value; }
+ void setBlockedState(BlockedState newState) { _blockedState = newState; }
+ void setUnknownFlag(bool value) { _unknownFlag = value; }
void setSize(uint16 newWidth, uint16 newHeight);
void setScript(uint16 offset) {
+ assert(_data != NULL);
_sequenceOffset = offset;
_data->sequenceOffset = offset;
}
void setActions(uint32 newActions) { _actions = newActions; }
void setCharRectY(uint16 value) { _charRectY = value; }
void setSkipFlag(bool value) { _skipFlag = value; }
+ CharacterMode characterMode() {
+ assert(_data != NULL);
+ return _data->characterMode;
+ }
+ void setCharacterMode(CharacterMode value) {
+ assert(_data != NULL);
+ _data->characterMode = value;
+ }
+ uint16 delayCtr() {
+ assert(_data != NULL);
+ return _data->delayCtr;
+ }
+ void setDelayCtr(uint16 value) {
+ assert(_data != NULL);
+ _data->delayCtr = value;
+ }
void copyTo(Surface *dest);
bool executeScript();
@@ -340,8 +367,12 @@ public:
void endAction();
void setDirection(Direction dir);
void faceHotspot(HotspotData *hotspot);
+ void setRandomDest();
void setOccupied(bool occupiedFlag);
bool walkingStep();
+ void updateMovement();
+ void updateMovement2(CharacterMode value);
+ void resetPosition();
// Actions
void doAction();
diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp
index 807aeebb24..7ecee018c1 100644
--- a/engines/lure/res_struct.cpp
+++ b/engines/lure/res_struct.cpp
@@ -291,6 +291,11 @@ HotspotData::HotspotData(HotspotResource *rec) {
tickTimeout = READ_LE_UINT16(&rec->tickTimeout);
tickSequenceOffset = READ_LE_UINT16(&rec->tickSequenceOffset);
npcSchedule = READ_LE_UINT16(&rec->npcSchedule);
+
+ // Initialise dynamic fields
+ delayCtr = 0;
+ characterMode = CHARMODE_NONE;
+ coveredFlag = false;
}
// Hotspot override data
diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h
index 0d02ef3f18..177b83f986 100644
--- a/engines/lure/res_struct.h
+++ b/engines/lure/res_struct.h
@@ -373,6 +373,9 @@ public:
HotspotActionList *getActions(uint16 recordId);
};
+enum CharacterMode {CHARMODE_NONE, CHARMODE_1, CHARMODE_IDLE, CHARMODE_PAUSED,
+ CHARMODE_4, CHARMODE_5, CHARMODE_6, CHARMODE_7};
+
class HotspotData {
public:
HotspotData(HotspotResource *rec);
@@ -405,7 +408,11 @@ public:
uint16 tickProcOffset;
uint16 tickTimeout;
uint16 tickSequenceOffset;
- uint16 npcSchedule;
+ uint16 npcSchedule;
+
+ uint16 delayCtr;
+ CharacterMode characterMode;
+ bool coveredFlag;
void enable() { flags |= 0x80; }
void disable() { flags &= 0x7F; }
diff --git a/engines/lure/room.cpp b/engines/lure/room.cpp
index a543db4207..7d7d569a0c 100644
--- a/engines/lure/room.cpp
+++ b/engines/lure/room.cpp
@@ -535,7 +535,7 @@ void Room::checkCursor() {
newCursor = CURSOR_TALK;
} else if (res.getTalkData()) {
newCursor = CURSOR_ARROW;
- } else if (_cursorState == CS_UNKNOWN) {
+ } else if (_cursorState == CS_BUMPED) {
newCursor = CURSOR_CAMERA;
} else if (_cursorState == CS_TALKING) {
newCursor = CURSOR_ARROW;
@@ -547,7 +547,7 @@ void Room::checkCursor() {
newCursor = CURSOR_MENUBAR;
} else if (_cursorState != CS_NONE) {
// Currently in a special mode
-// checkRoomHotspots();
+ checkRoomHotspots();
newCursor = CURSOR_CAMERA;
} else {
// Check for a highlighted hotspot
diff --git a/engines/lure/room.h b/engines/lure/room.h
index d8011d0300..3eb90a714a 100644
--- a/engines/lure/room.h
+++ b/engines/lure/room.h
@@ -51,7 +51,7 @@ public:
}
};
-enum CursorState {CS_NONE, CS_ACTION, CS_SEQUENCE, CS_TALKING, CS_UNKNOWN};
+enum CursorState {CS_NONE, CS_ACTION, CS_SEQUENCE, CS_TALKING, CS_BUMPED};
class Room {
private: