aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/lure/res_struct.cpp181
-rw-r--r--engines/lure/res_struct.h81
2 files changed, 252 insertions, 10 deletions
diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp
index 91c0c0e982..807aeebb24 100644
--- a/engines/lure/res_struct.cpp
+++ b/engines/lure/res_struct.cpp
@@ -33,6 +33,10 @@ const char *actionList[] = {NULL, "Get", NULL, "Push", "Pull", "Operate", "Open"
"Look", "Look at", "Look through", "Ask", NULL, "Drink", "Status",
"Go to", "Return", "Bribe", "Examine"};
+int actionNumParams[NPC_JUMP_ADDRESS+1] = {0,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 1,
+ 0, 1, 1, 1, 1, 0, 0, 2, 0, 1, 0, 0, 1, 1, 2, 2, 5, 2, 2, 1};
+
// Room data holding class
RoomData::RoomData(RoomResource *rec, MemoryBlock *pathData) {
@@ -48,6 +52,10 @@ RoomData::RoomData(RoomResource *rec, MemoryBlock *pathData) {
clippingXStart = READ_LE_UINT16(&rec->clippingXStart);
clippingXEnd = READ_LE_UINT16(&rec->clippingXEnd);
+ walkBounds.left = READ_LE_INT16(&rec->walkBounds.xs);
+ walkBounds.right = READ_LE_INT16(&rec->walkBounds.xe);
+ walkBounds.top = READ_LE_INT16(&rec->walkBounds.ys);
+ walkBounds.bottom = READ_LE_INT16(&rec->walkBounds.ye);
}
// Room exit hotspot area holding class
@@ -282,6 +290,7 @@ HotspotData::HotspotData(HotspotResource *rec) {
tickProcOffset = READ_LE_UINT16(&rec->tickProcOffset);
tickTimeout = READ_LE_UINT16(&rec->tickTimeout);
tickSequenceOffset = READ_LE_UINT16(&rec->tickSequenceOffset);
+ npcSchedule = READ_LE_UINT16(&rec->npcSchedule);
}
// Hotspot override data
@@ -430,12 +439,13 @@ TalkEntryData *TalkData::getResponse(int index) {
RoomExitCoordinates::RoomExitCoordinates(RoomExitCoordinateEntryResource *rec) {
int ctr;
+
for (ctr = 0; ctr < ROOM_EXIT_COORDINATES_NUM_ENTRIES; ++ctr) {
+ uint16 tempY = FROM_LE_16(rec->entries[ctr].y);
_entries[ctr].x = FROM_LE_16(rec->entries[ctr].x);
- _entries[ctr].y = FROM_LE_16(rec->entries[ctr].y);
- uint16 v = FROM_LE_16(rec->entries[ctr].roomNumber);
- _entries[ctr].roomNumber = v & 0xfff;
- _entries[ctr].unknown = v >> 12;
+ _entries[ctr].y = tempY & 0xfff;
+ _entries[ctr].roomNumber = FROM_LE_16(rec->entries[ctr].roomNumber);
+ _entries[ctr].hotspotIndexId = (tempY >> 12) << 4;
}
for (ctr = 0; ctr < ROOM_EXIT_COORDINATES_NUM_ROOMS; ++ctr)
@@ -482,6 +492,161 @@ void SequenceDelayList::tick() {
}
}
+// The following classes hold the NPC schedule classes
+
+CharacterScheduleEntry::CharacterScheduleEntry(Action theAction, ...) {
+ _parent = NULL;
+ _action = theAction;
+
+ va_list u_Arg;
+ va_start(u_Arg, theAction);
+
+ for (int paramCtr = 0; paramCtr < actionNumParams[_action]; ++paramCtr)
+ _params[paramCtr] = (uint16) va_arg(u_Arg, int);
+
+ va_end(u_Arg);
+}
+
+CharacterScheduleEntry::CharacterScheduleEntry(CharacterScheduleSet *parentSet,
+ CharacterScheduleResource *&rec) {
+ _parent = parentSet;
+
+ if ((rec->action == 0) || (rec->action > NPC_JUMP_ADDRESS))
+ error("Invalid action encountered reading NPC schedule");
+
+ _action = (Action) rec->action;
+ for (int index = 0; index < actionNumParams[_action]; ++index)
+ _params[index] = FROM_LE_16(rec->params[index]);
+
+ rec = (CharacterScheduleResource *) ((byte *) rec +
+ (actionNumParams[_action] + 1) * sizeof(uint16));
+}
+
+int CharacterScheduleEntry::numParams() {
+ return actionNumParams[_action];
+}
+
+uint16 CharacterScheduleEntry::param(int index) {
+ if ((index < 0) || (index >= numParams()))
+ error("Invalid parameter index %d on handling action %d", index, _action);
+ return _params[index];
+}
+
+void CharacterScheduleEntry::setDetails(Action theAction, ...) {
+ _action = theAction;
+
+ va_list list;
+ va_start(list, theAction);
+
+ for (int paramCtr = 0; paramCtr < actionNumParams[_action]; ++paramCtr)
+ _params[paramCtr] = (uint16) va_arg(list, int);
+
+ va_end(list);
+}
+
+CharacterScheduleEntry *CharacterScheduleEntry::next() {
+ if (_parent) {
+ CharacterScheduleSet::iterator i;
+ for (i = _parent->begin(); i != _parent->end(); ++i) {
+ if (*i == this) {
+ ++i;
+ CharacterScheduleEntry *result = (i == _parent->end()) ? NULL : *i;
+ return result;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+uint16 CharacterScheduleEntry::id() {
+ return parent()->getId(this);
+}
+
+CharacterScheduleSet::CharacterScheduleSet(CharacterScheduleResource *rec, uint16 setId) {
+ // Load up all the entries in the schedule
+
+ while (rec->action != 0) {
+ CharacterScheduleEntry *r = new CharacterScheduleEntry(this, rec);
+ push_back(r);
+ }
+
+ _id = setId;
+}
+
+// Given a support data entry identifier, locates that entry in the list of data sets
+
+CharacterScheduleEntry *CharacterScheduleList::getEntry(uint16 id, CharacterScheduleSet *currentSet) {
+ // Respond to the special no entry with no record
+ if (id == 0xffff) return NULL;
+
+ // Handle jumps within a current set versus external jumps
+ if ((id >> 10) == 0) {
+ // Jump within current set
+ if (currentSet == NULL)
+ error("Local support data jump encountered outside of a support data sequence");
+ } else {
+ // Inter-set jump - locate the appropriate set
+ int index = (id >> 10) - 1;
+
+ iterator i = begin();
+ while ((i != end()) && (index > 0)) {
+ ++i;
+ --index;
+ }
+
+ if (i == end())
+ error("Invalid index %d specified for support data set", id >> 8);
+ currentSet = *i;
+ }
+
+ // Get the indexed instruction in the specified set
+ int instructionIndex = id & 0x3ff;
+ CharacterScheduleSet::iterator i = currentSet->begin();
+ while ((i != currentSet->end()) && (instructionIndex > 0)) {
+ ++i;
+ --instructionIndex;
+ }
+ if (i == currentSet->end())
+ error("Invalid index %d specified within support data set", id & 0x3ff);
+
+ return *i;
+}
+
+uint16 CharacterScheduleSet::getId(CharacterScheduleEntry *rec) {
+ // Return an Id for the entry based on the id of the set combined with the
+ // index of the specific entry
+ uint16 result = _id << 10;
+
+ iterator i;
+ for (i = begin(); i != end(); ++i, ++result)
+ if (*i == rec) break;
+ if (i == end())
+ error("Parent child relationship missing in character schedule set");
+ return result;
+}
+
+// This class handles an indexed hotspot entry - which is used by the NPC code to
+// determine whether exiting a room to another given room has an exit hotspot or not
+
+RoomExitIndexedHotspotData::RoomExitIndexedHotspotData(RoomExitIndexedHotspotResource *rec) {
+ roomNumber = rec->roomNumber;
+ hotspotIndex = rec->hotspotIndex;
+ hotspotId = FROM_LE_16(rec->hotspotId);
+}
+
+uint16 RoomExitIndexedHotspotList::getHotspot(uint16 roomNumber, uint8 hotspotIndexId) {
+ iterator i;
+ for (i = begin(); i != end(); ++i) {
+ RoomExitIndexedHotspotData *entry = *i;
+ if ((entry->roomNumber == roomNumber) && (entry->hotspotIndex == hotspotIndexId))
+ return entry->hotspotId;
+ }
+
+ // No hotspot
+ return 0xffff;
+}
+
// Field list and miscellaneous variables
ValueTableData::ValueTableData() {
@@ -501,8 +666,8 @@ bool ValueTableData::isKnownField(uint16 fieldIndex) {
uint16 ValueTableData::getField(uint16 fieldIndex) {
if (fieldIndex > NUM_VALUE_FIELDS)
error("Invalid field index specified %d", fieldIndex);
- if (!isKnownField(fieldIndex))
- warning("Unknown field index %d in GET_FIELD opcode", fieldIndex);
+// if (!isKnownField(fieldIndex))
+// warning("Unknown field index %d in GET_FIELD opcode", fieldIndex);
return _fieldList[fieldIndex];
}
@@ -514,8 +679,8 @@ void ValueTableData::setField(uint16 fieldIndex, uint16 value) {
if (fieldIndex > NUM_VALUE_FIELDS)
error("Invalid field index specified %d", fieldIndex);
_fieldList[fieldIndex] = value;
- if (!isKnownField(fieldIndex))
- warning("Unknown field index %d in SET_FIELD opcode", fieldIndex);
+// if (!isKnownField(fieldIndex))
+// warning("Unknown field index %d in SET_FIELD opcode", fieldIndex);
}
void ValueTableData::setField(FieldName fieldName, uint16 value) {
diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h
index 72eaa03629..0d02ef3f18 100644
--- a/engines/lure/res_struct.h
+++ b/engines/lure/res_struct.h
@@ -83,6 +83,7 @@ struct HotspotResource {
uint16 tickProcOffset;
uint16 tickTimeout;
uint16 tickSequenceOffset;
+ uint16 npcSchedule;
} GCC_PACK;
struct HotspotAnimResource {
@@ -105,6 +106,10 @@ struct MovementResource {
int16 yChange;
} GCC_PACK;
+struct RoomRect {
+ int16 xs, xe;
+ int16 ys, ye;
+};
struct RoomResource {
uint16 roomNumber;
@@ -114,6 +119,7 @@ struct RoomResource {
uint16 sequenceOffset;
int16 clippingXStart;
int16 clippingXEnd;
+ RoomRect walkBounds;
uint16 numExits;
} GCC_PACK;
@@ -194,6 +200,19 @@ struct RoomExitCoordinateEntryResource {
uint8 roomIndex[ROOM_EXIT_COORDINATES_NUM_ROOMS];
} GCC_PACK;
+#define MAX_SCHEDULE_ENTRY_PARAMS 5
+
+struct CharacterScheduleResource {
+ uint16 action;
+ uint16 params[MAX_SCHEDULE_ENTRY_PARAMS];
+};
+
+struct RoomExitIndexedHotspotResource {
+ uint8 roomNumber;
+ uint8 hotspotIndex;
+ uint16 hotspotId;
+};
+
#if !defined(__GNUC__)
#pragma END_PACK_STRUCTS
#endif
@@ -305,6 +324,7 @@ public:
uint16 sequenceOffset;
int16 clippingXStart;
int16 clippingXEnd;
+ Common::Rect walkBounds;
RoomExitHotspotList exitHotspots;
RoomExitList exits;
RoomPathsData paths;
@@ -385,7 +405,8 @@ public:
uint16 tickProcOffset;
uint16 tickTimeout;
uint16 tickSequenceOffset;
-
+ uint16 npcSchedule;
+
void enable() { flags |= 0x80; }
void disable() { flags &= 0x7F; }
Direction nonVisualDirection() { return (Direction) scriptLoadFlag; }
@@ -481,7 +502,7 @@ struct RoomExitCoordinateData {
int16 x;
int16 y;
uint16 roomNumber;
- byte unknown;
+ byte hotspotIndexId;
};
class RoomExitCoordinates {
@@ -498,6 +519,20 @@ public:
RoomExitCoordinates &getEntry(uint16 roomNumber);
};
+class RoomExitIndexedHotspotData {
+public:
+ RoomExitIndexedHotspotData(RoomExitIndexedHotspotResource *rec);
+
+ uint16 roomNumber;
+ uint8 hotspotIndex;
+ uint16 hotspotId;
+};
+
+class RoomExitIndexedHotspotList: public ManagedList<RoomExitIndexedHotspotData *> {
+public:
+ uint16 getHotspot(uint16 roomNumber, uint8 hotspotIndexId);
+};
+
// The following classes hold any sequence offsets that are being delayed
class SequenceDelayData {
@@ -515,6 +550,48 @@ public:
void tick();
};
+// The following classes holds the data for NPC schedules
+
+extern int actionNumParams[NPC_JUMP_ADDRESS+1];
+
+class CharacterScheduleSet;
+
+class CharacterScheduleEntry {
+private:
+ CharacterScheduleSet *_parent;
+ Action _action;
+ uint16 _params[MAX_SCHEDULE_ENTRY_PARAMS];
+public:
+ CharacterScheduleEntry() { _action = NONE; _parent = NULL; }
+ CharacterScheduleEntry(Action theAction, ...);
+ CharacterScheduleEntry(CharacterScheduleSet *parentSet,
+ CharacterScheduleResource *&rec);
+
+ Action action() { return _action; }
+ int numParams();
+ uint16 param(int index);
+ void setDetails(Action theAction, ...);
+ CharacterScheduleEntry *next();
+ CharacterScheduleSet *parent() { return _parent; }
+ uint16 id();
+};
+
+class CharacterScheduleSet: public ManagedList<CharacterScheduleEntry *> {
+private:
+ uint16 _id;
+public:
+ CharacterScheduleSet(CharacterScheduleResource *rec, uint16 setId);
+ uint16 getId(CharacterScheduleEntry *rec);
+ uint16 id() { return _id; }
+};
+
+class CharacterScheduleList: public ManagedList<CharacterScheduleSet *> {
+public:
+ CharacterScheduleEntry *getEntry(uint16 id, CharacterScheduleSet *currentSet = NULL);
+};
+
+typedef List<uint16> CharacterScheduleOffsets;
+
// The following class holds the field list used by the script engine as
// well as miscellaneous fields used by the game.