aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2006-07-08 08:36:32 +0000
committerPaul Gilbert2006-07-08 08:36:32 +0000
commitc6b6a2e12587b15a95d371acf9f18586ff392736 (patch)
treefa981c613059bc61dcfdc9a8e4c79d59990e4981
parentacb3a5a9ac6700341af2100a1eb5885a18d73c74 (diff)
downloadscummvm-rg350-c6b6a2e12587b15a95d371acf9f18586ff392736.tar.gz
scummvm-rg350-c6b6a2e12587b15a95d371acf9f18586ff392736.tar.bz2
scummvm-rg350-c6b6a2e12587b15a95d371acf9f18586ff392736.zip
Added new hotspot runtime fields, a list for handling the details of paused characters (who have bumped into each other), and loading of newly added default character states from lure.dat
svn-id: r23410
-rw-r--r--engines/lure/res_struct.cpp168
-rw-r--r--engines/lure/res_struct.h79
2 files changed, 226 insertions, 21 deletions
diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp
index 7ecee018c1..dfa478ffce 100644
--- a/engines/lure/res_struct.cpp
+++ b/engines/lure/res_struct.cpp
@@ -128,6 +128,7 @@ bool RoomPathsData::isOccupied(int x, int y) {
void RoomPathsData::setOccupied(int x, int y, int width) {
if ((x < 0) || (y < 0) || (x >= ROOM_PATHS_WIDTH) || (y >= ROOM_PATHS_HEIGHT))
return;
+
byte *p = &_data[y * 5 + (x / 8)];
byte bitMask = 0x80 >> (x % 8);
@@ -144,6 +145,7 @@ void RoomPathsData::setOccupied(int x, int y, int width) {
void RoomPathsData::clearOccupied(int x, int y, int width) {
if ((x < 0) || (y < 0) || (x >= ROOM_PATHS_WIDTH) || (y >= ROOM_PATHS_HEIGHT))
return;
+
byte *p = &_data[y * 5 + (x / 8)];
byte bitMask = 0x80 >> (x % 8);
@@ -291,11 +293,20 @@ HotspotData::HotspotData(HotspotResource *rec) {
tickTimeout = READ_LE_UINT16(&rec->tickTimeout);
tickSequenceOffset = READ_LE_UINT16(&rec->tickSequenceOffset);
npcSchedule = READ_LE_UINT16(&rec->npcSchedule);
+ characterMode = (CharacterMode) READ_LE_UINT16(&rec->characterMode);
+ delayCtr = READ_LE_UINT16(&rec->delayCtr);
- // Initialise dynamic fields
- delayCtr = 0;
- characterMode = CHARMODE_NONE;
+ // Initialise runtime fields
+ actionCtr = 0;
+ blockedState = BS_NONE;
coveredFlag = false;
+ talkMessageId = 0;
+ talkDestHotspot = 0;
+ talkCountdown = 0;
+ pauseCtr = 0;
+ useHotspotId = 0;
+ v2b = 0;
+ v50 = 0;
}
// Hotspot override data
@@ -470,16 +481,18 @@ RoomExitCoordinateData &RoomExitCoordinates::getData(uint16 destRoomNumber) {
// The following classes hold any sequence offsets that are being delayed
-SequenceDelayData::SequenceDelayData(uint16 delay, uint16 seqOffset) {
+SequenceDelayData::SequenceDelayData(uint16 delay, uint16 seqOffset, bool canClearFlag) {
OSystem &system = System::getReference();
- _timeoutCtr = system.getMillis() + delay;
- _sequenceOffset = seqOffset;
+ // The delay is in number of ticks (1/18th of a second) - convert to milliseconds
+ timeoutCtr = system.getMillis() + (delay * 1000 / 18);
+ sequenceOffset = seqOffset;
+ canClear = canClearFlag;
}
-void SequenceDelayList::addSequence(uint16 delay, uint16 seqOffset) {
- SequenceDelayData *entry = new SequenceDelayData(delay, seqOffset);
- push_back(entry);
+void SequenceDelayList::add(uint16 delay, uint16 seqOffset, bool canClear) {
+ SequenceDelayData *entry = new SequenceDelayData(delay, seqOffset, canClear);
+ push_front(entry);
}
void SequenceDelayList::tick() {
@@ -488,8 +501,9 @@ void SequenceDelayList::tick() {
for (i = begin(); i != end(); i++) {
SequenceDelayData *entry = *i;
- if (entry->_timeoutCtr >= currTime) {
- uint16 seqOffset = entry->_sequenceOffset;
+ if (currTime >= entry->timeoutCtr) {
+ // Timeout reached - delete entry from list and execute the sequence
+ uint16 seqOffset = entry->sequenceOffset;
erase(i);
Script::execute(seqOffset);
return;
@@ -497,6 +511,18 @@ void SequenceDelayList::tick() {
}
}
+void SequenceDelayList::clear() {
+ SequenceDelayList::iterator i = begin();
+
+ while (i != end()) {
+ SequenceDelayData *entry = *i;
+ if (entry->canClear)
+ i = erase(i);
+ else
+ ++i;
+ }
+}
+
// The following classes hold the NPC schedule classes
CharacterScheduleEntry::CharacterScheduleEntry(Action theAction, ...) {
@@ -652,6 +678,121 @@ uint16 RoomExitIndexedHotspotList::getHotspot(uint16 roomNumber, uint8 hotspotIn
return 0xffff;
}
+// Paused character list methods
+
+PausedCharacter::PausedCharacter(uint16 SrcCharId, uint16 DestCharId) {
+ srcCharId = SrcCharId;
+ destCharId = DestCharId;
+ counter = IDLE_COUNTDOWN_SIZE;
+ charHotspot = Resources::getReference().getHotspot(SrcCharId);
+ assert(charHotspot);
+}
+
+void PausedCharacterList::reset(uint16 hotspotId) {
+ iterator i;
+ for (i = begin(); i != end(); ++i) {
+ PausedCharacter *rec = *i;
+
+ if (rec->srcCharId == hotspotId) {
+ rec->counter = 1;
+ if (rec->destCharId < START_EXIT_ID)
+ rec->charHotspot->pauseCtr = 1;
+ }
+ }
+}
+
+void PausedCharacterList::countdown() {
+ iterator i = begin();
+
+ while (i != end()) {
+ PausedCharacter *rec = *i;
+ --rec->counter;
+
+ // Handle reflecting counter to hotspot
+ if (rec->destCharId < START_EXIT_ID)
+ rec->charHotspot->pauseCtr = rec->counter + 1;
+
+ // If counter has reached zero, remove entry from list
+ if (rec->counter == 0)
+ i = erase(i);
+ else
+ ++i;
+ }
+}
+
+void PausedCharacterList::scan(Hotspot &h) {
+ iterator i;
+
+ if (h.blockedState() != BS_NONE) {
+
+ for (i = begin(); i != end(); ++i) {
+ PausedCharacter *rec = *i;
+
+ if (rec->srcCharId == h.hotspotId()) {
+ rec->counter = IDLE_COUNTDOWN_SIZE;
+
+ if (rec->destCharId < START_EXIT_ID)
+ rec->charHotspot->pauseCtr = IDLE_COUNTDOWN_SIZE;
+ }
+ }
+ }
+}
+
+int PausedCharacterList::check(uint16 charId, int numImpinging, uint16 *impingingList) {
+ Resources &res = Resources::getReference();
+ PausedCharacterList::iterator i;
+ int result = 0;
+ Hotspot *charHotspot = res.getActiveHotspot(charId);
+ assert(charHotspot);
+
+ for (int index = 0; index < numImpinging; ++index) {
+ Hotspot *hotspot = res.getActiveHotspot(impingingList[index]);
+ if ((!hotspot) || (!hotspot->currentActions().isEmpty() &&
+ (hotspot->currentActions().top().action() == EXEC_HOTSPOT_SCRIPT)))
+ // Entry is skipped if hotspot not present or is executing hotspot script
+ continue;
+
+ // Scan through the pause list to see if there's a record for the
+ // calling character and the impinging list entry
+ for (i = res.pausedList().begin(); i != res.pausedList().end(); ++i) {
+ PausedCharacter *rec = *i;
+ if ((rec->srcCharId == charId) &&
+ (rec->destCharId == hotspot->hotspotId()))
+ break;
+ }
+
+ if (i != res.pausedList().end())
+ // There was, so move to next impinging character entry
+ continue;
+
+ if ((hotspot->hotspotId() == PLAYER_ID) && !hotspot->coveredFlag())
+ return 1;
+
+ // Add a new paused character entry
+ PausedCharacter *entry = new PausedCharacter(charId, hotspot->hotspotId());
+ res.pausedList().push_back(entry);
+ charHotspot->setBlockedState(BS_INITIAL);
+
+ if (hotspot->hotspotId() < START_EXIT_ID) {
+ if ((charHotspot->characterMode() == CHARMODE_PAUSED) ||
+ ((charHotspot->pauseCtr() == 0) &&
+ (charHotspot->characterMode() == CHARMODE_NONE))) {
+ hotspot->resource()->use2HotspotId = charId;
+ } else {
+ hotspot->setPauseCtr(IDLE_COUNTDOWN_SIZE);
+ }
+ }
+
+ result = 2;
+ if (charHotspot->currentActions().isEmpty())
+ charHotspot->currentActions().addFront(START_WALKING, charHotspot->roomNumber());
+ else
+ charHotspot->currentActions().top().setAction(START_WALKING);
+ }
+
+ return result;
+}
+
// Field list and miscellaneous variables
ValueTableData::ValueTableData() {
@@ -659,6 +800,11 @@ ValueTableData::ValueTableData() {
_playerNewPos.roomNumber = 0;
_playerNewPos.position.x = 0;
_playerNewPos.position.y = 0;
+ _playerPendingPos.pos.x = 0;
+ _playerPendingPos.pos.y = 0;
+ _playerPendingPos.isSet = false;
+ _flags = GAMEFLAG_4 | GAMEFLAG_1;
+
for (uint16 index = 0; index < NUM_VALUE_FIELDS; ++index)
_fieldList[index] = 0;
}
diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h
index 177b83f986..ded24f61f9 100644
--- a/engines/lure/res_struct.h
+++ b/engines/lure/res_struct.h
@@ -84,6 +84,8 @@ struct HotspotResource {
uint16 tickTimeout;
uint16 tickSequenceOffset;
uint16 npcSchedule;
+ uint16 characterMode;
+ uint16 delayCtr;
} GCC_PACK;
struct HotspotAnimResource {
@@ -373,8 +375,10 @@ public:
HotspotActionList *getActions(uint16 recordId);
};
-enum CharacterMode {CHARMODE_NONE, CHARMODE_1, CHARMODE_IDLE, CHARMODE_PAUSED,
- CHARMODE_4, CHARMODE_5, CHARMODE_6, CHARMODE_7};
+enum CharacterMode {CHARMODE_NONE, CHARMODE_HESITATE, CHARMODE_IDLE, CHARMODE_PAUSED,
+ CHARMODE_4, CHARMODE_CONVERSING, CHARMODE_6, CHARMODE_7, CHARMODE_8};
+
+enum BlockedState {BS_NONE, BS_INITIAL, BS_FINAL};
class HotspotData {
public:
@@ -409,10 +413,21 @@ public:
uint16 tickTimeout;
uint16 tickSequenceOffset;
uint16 npcSchedule;
-
- uint16 delayCtr;
CharacterMode characterMode;
+ uint16 delayCtr;
+
+ // Runtime fields
+ uint16 actionCtr;
+ BlockedState blockedState;
bool coveredFlag;
+ uint16 talkMessageId;
+ uint16 talkDestHotspot;
+ uint16 talkCountdown;
+ uint16 pauseCtr;
+ uint16 useHotspotId;
+ uint16 use2HotspotId;
+ uint16 v2b;
+ uint16 v50;
void enable() { flags |= 0x80; }
void disable() { flags &= 0x7F; }
@@ -543,18 +558,19 @@ public:
// The following classes hold any sequence offsets that are being delayed
class SequenceDelayData {
- friend class SequenceDelayList;
-private:
- uint32 _timeoutCtr;
- uint16 _sequenceOffset;
public:
- SequenceDelayData(uint16 delay, uint16 seqOffset);
+ SequenceDelayData(uint16 delay, uint16 seqOffset, bool canClearFlag);
+
+ uint32 timeoutCtr;
+ uint16 sequenceOffset;
+ bool canClear;
};
class SequenceDelayList: public ManagedList<SequenceDelayData *> {
public:
- void addSequence(uint16 delay, uint16 seqOffset);
+ void add(uint16 delay, uint16 seqOffset, bool canClear);
void tick();
+ void clear();
};
// The following classes holds the data for NPC schedules
@@ -599,6 +615,26 @@ public:
typedef List<uint16> CharacterScheduleOffsets;
+class PausedCharacter {
+public:
+ PausedCharacter(uint16 SrcCharId, uint16 DestCharId);
+
+ uint16 srcCharId;
+ uint16 destCharId;
+ uint16 counter;
+ HotspotData *charHotspot;
+};
+
+class Hotspot;
+
+class PausedCharacterList: public ManagedList<PausedCharacter *> {
+public:
+ void reset(uint16 hotspotId);
+ void countdown();
+ void scan(Hotspot &h);
+ int check(uint16 charId, int numImpinging, uint16 *impingingList);
+};
+
// The following class holds the field list used by the script engine as
// well as miscellaneous fields used by the game.
@@ -611,6 +647,7 @@ enum FieldName {
ACTIVE_HOTSPOT_ID = 3,
SEQUENCE_RESULT = 4,
GENERAL = 5,
+ GIVE_TALK_INDEX = 6,
NEW_ROOM_NUMBER = 7,
OLD_ROOM_NUMBER = 8,
CELL_DOOR_STATE = 9,
@@ -621,15 +658,33 @@ enum FieldName {
SACK_CUT = 20
};
+enum GameFlags {
+ GAMEFLAG_1 = 1,
+ GAMEFLAG_2 = 2,
+ GAMEFLAG_4 = 4,
+ GAMEFLAG_8 = 8,
+ GAMEFLAG_10 = 0x10,
+ GAMEFLAG_20 = 0x20,
+ GAMEFLAG_40 = 0x40,
+ GAMEFLAG_FAST_TEXTSPEED = 0x80
+};
+
struct PlayerNewPosition {
Point position;
uint16 roomNumber;
};
+struct PlayerPendingPosition {
+ Point pos;
+ bool isSet;
+};
+
class ValueTableData {
private:
uint16 _numGroats;
PlayerNewPosition _playerNewPos;
+ PlayerPendingPosition _playerPendingPos;
+ uint8 _flags;
uint16 _fieldList[NUM_VALUE_FIELDS];
bool isKnownField(uint16 fieldIndex);
@@ -640,8 +695,12 @@ public:
void setField(uint16 fieldIndex, uint16 value);
void setField(FieldName fieldName, uint16 value);
+ int size() { return NUM_VALUE_FIELDS; }
+
uint16 &numGroats() { return _numGroats; }
+ uint8 &flags() { return _flags; }
PlayerNewPosition &playerNewPos() { return _playerNewPos; }
+ PlayerPendingPosition &playerPendingPos() { return _playerPendingPos; }
};
} // End of namespace Lure