From f6b2cf2c6dcc37c54913ad2209545002727ee6fd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 11 Apr 2006 10:43:53 +0000 Subject: Updated resource structures to add support for hotspot y corrections, proximity data, room walkable areas, and the room exit coordinate list svn-id: r21779 --- engines/lure/res_struct.cpp | 178 ++++++++++++++++++++++++++++++++++++++++++-- engines/lure/res_struct.h | 114 ++++++++++++++++++++++++++-- 2 files changed, 277 insertions(+), 15 deletions(-) (limited to 'engines/lure') diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp index 587e25919f..75cb27f9c5 100644 --- a/engines/lure/res_struct.cpp +++ b/engines/lure/res_struct.cpp @@ -35,12 +35,14 @@ const char *actionList[] = {NULL, "Get", NULL, "Push", "Pull", "Operate", "Open" // Room data holding class -RoomData::RoomData(RoomResource *rec) { +RoomData::RoomData(RoomResource *rec, MemoryBlock *pathData) { roomNumber = READ_LE_UINT16(&rec->roomNumber); descId = READ_LE_UINT16(&rec->descId); sequenceOffset = READ_LE_UINT16(&rec->sequenceOffset); numLayers = READ_LE_UINT16(&rec->numLayers); + paths.load(pathData->data() + (roomNumber - 1) * ROOM_PATHS_SIZE); + for (int ctr = 0; ctr < 4; ++ctr) layers[ctr] = READ_LE_UINT16(&rec->layers[ctr]); @@ -92,31 +94,143 @@ RoomExitData::RoomExitData(RoomExitResource *rec) { } bool RoomExitData::insideRect(int16 xp, int16 yp) { - return ((xp >= xs) && (xp <= xe) && (yp >= ys) && (yp <= ye)); + return ((xp >= xs) && (xp < xe) && (yp >= ys) && (yp < ye)); } RoomExitData *RoomExitList::checkExits(int16 xp, int16 yp) { iterator i; for (i = begin(); i != end(); i++) { RoomExitData *rec = *i; - if (rec->insideRect(xp, yp)) return rec; + if (rec->insideRect(xp, yp)) { + return rec; + } } return NULL; } +// Room paths + +bool RoomPathsData::isOccupied(int x, int y) { + if ((x < 0) || (y < 0) || (x >= ROOM_PATHS_WIDTH) || (y >= ROOM_PATHS_HEIGHT)) + // Off screen, so flag as not occupied + return false; + return (_data[y * 5 + (x >> 3)] & (0x80 >> (x % 8))) != 0; +} + +void RoomPathsData::setOccupied(int x, int y, int width) { + if ((x < 0) || (y < 0) || (x >= ROOM_PATHS_WIDTH) || (x >= ROOM_PATHS_HEIGHT)) + return; + + byte *p = &_data[y * 5 + (x % 8)]; + byte bitMask = 0x80 >> (x % 8); + + for (int bitCtr = 0; bitCtr < width; ++bitCtr) { + *p |= bitMask; + bitMask >>= 1; + if (bitMask == 0) { + ++p; + bitMask = 0x80; + } + } +} + +void RoomPathsData::clearOccupied(int x, int y, int width) { + if ((x < 0) || (y < 0) || (x >= ROOM_PATHS_WIDTH) || (x >= ROOM_PATHS_HEIGHT)) + return; + + byte *p = &_data[y * 5 + (x % 8)]; + byte bitMask = 0x80 >> (x % 8); + + for (int bitCtr = 0; bitCtr < width; ++bitCtr) { + *p &= !bitMask; + bitMask >>= 1; + if (bitMask == 0) { + ++p; + bitMask = 0x80; + } + } +} + +// decompresses the bit-packed data for which parts of a room are occupied +// into a byte array. It also adds a column and row of padding around the +// edges of the screen, and extends occupied areas to adjust for the width +// of the chracter + +void RoomPathsData::decompress(RoomPathsDecompressedData &dataOut, int characterWidth) { + byte *pIn = &_data[ROOM_PATHS_SIZE - 1]; + uint16 *pOut = &dataOut[DECODED_PATHS_WIDTH * DECODED_PATHS_HEIGHT - 1]; + byte v; + int paddingCtr; + int charWidth = (characterWidth - 1) >> 3; + int charCtr = 0; + bool charState = false; + + // Handle padding for last row, including left/right edge padding, as + // well as the right column of the second row + for (paddingCtr = 0; paddingCtr < (DECODED_PATHS_WIDTH + 1); ++paddingCtr) + *pOut-- = 0; + + for (int y = 0; y < ROOM_PATHS_HEIGHT; ++y) { + for (int x = 0; x < (ROOM_PATHS_WIDTH / 8); ++x) { + // Get next byte, which containing bits for 8 blocks + v = *pIn--; + + for (int bitCtr = 0; bitCtr < 8; ++bitCtr) { + bool isSet = (v & 1) != 0; + v >>= 1; + + if (charState) { + // Handling occupied characters adjusted for character width + if (isSet) + // Reset character counter + charCtr = charWidth; + + *pOut-- = 0xffff; + charState = (--charCtr != 0); + + } else { + // Normal decompression + if (!isSet) { + // Flag block is available for walking on + *pOut-- = 0; + } else { + // Flag block is occupied + *pOut-- = 0xffff; + + // Handling for adjusting for character widths + charCtr = charWidth - 1; + charState = charCtr >= 0; + } + } + } + } + + // Store 2 words to allow off-screen row-start/prior row end + *pOut-- = 0; + *pOut-- = 0; + charState = false; + } + + // Handle padding for final top row - no need for end column, as end of prior + // row provided padding for it + for (paddingCtr = 0; paddingCtr < (ROOM_PATHS_WIDTH + 1); ++paddingCtr) + *pOut-- = 0; +} + // Room exit joins class RoomExitJoinData::RoomExitJoinData(RoomExitJoinResource *rec) { hotspot1Id = READ_LE_UINT16(&rec->hotspot1Id); h1CurrentFrame = rec->h1CurrentFrame; h1DestFrame = rec->h1DestFrame; - h1Unknown = READ_LE_UINT16(&rec->h1Unknown); + h1OpenSound = rec->h1OpenSound; + h1CloseSound = rec->h1CloseSound; hotspot2Id = READ_LE_UINT16(&rec->hotspot2Id); h2CurrentFrame = rec->h2CurrentFrame; h2DestFrame = rec->h2DestFrame; - h2Unknown = READ_LE_UINT16(&rec->h2Unknown); + h2OpenSound = rec->h2OpenSound; + h2CloseSound = rec->h2CloseSound; blocked = rec->blocked; - unknown = rec->unknown; } // Hotspot action record @@ -159,6 +273,7 @@ HotspotData::HotspotData(HotspotResource *rec) { height = READ_LE_UINT16(&rec->height); widthCopy = READ_LE_UINT16(&rec->widthCopy); heightCopy = READ_LE_UINT16(&rec->heightCopy); + yCorrection = READ_LE_UINT16(&rec->yCorrection); talkX = rec->talkX; talkY = rec->talkY; colourOffset = READ_LE_UINT16(&rec->colourOffset); @@ -309,6 +424,34 @@ TalkEntryData *TalkData::getResponse(int index) { return *i; } +// The following class handles a set of coordinates a character should walk to +// if they're to exit a room to a designated secondary room + +RoomExitCoordinates::RoomExitCoordinates(RoomExitCoordinateEntryResource *rec) { + int ctr; + for (ctr = 0; ctr < ROOM_EXIT_COORDINATES_NUM_ENTRIES; ++ctr) { + _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; + } + + for (ctr = 0; ctr < ROOM_EXIT_COORDINATES_NUM_ROOMS; ++ctr) + _roomIndex[ctr] = rec->roomIndex[ctr]; +} + +RoomExitCoordinates &RoomExitCoordinatesList::getEntry(uint16 roomNumber) { + RoomExitCoordinatesList::iterator i = begin(); + while (--roomNumber > 0) + ++i; + return **i; +} + +RoomExitCoordinateData &RoomExitCoordinates::getData(uint16 destRoomNumber) { + return _entries[_roomIndex[destRoomNumber - 1]]; +} + // The following classes hold any sequence offsets that are being delayed SequenceDelayData::SequenceDelayData(uint16 delay, uint16 seqOffset) { @@ -338,11 +481,32 @@ void SequenceDelayList::tick() { } } +// The following class holds the proximity data for hotspots that is used +// to determine whether a character needs to walk to a hotspot or not + +HotspotProximityData::HotspotProximityData(HotspotProximityResource *rec) { + hotspotId = FROM_LE_16(rec->hotspotId); + x = FROM_LE_16(rec->x); + y = FROM_LE_16(rec->y); +} + +HotspotProximityData *HotspotProximityList::getHotspot(uint16 hotspotId) { + iterator i; + for (i = begin(); i != end(); ++i) { + HotspotProximityData *rec = *i; + if (rec->hotspotId == hotspotId) return rec; + } + + return NULL; +} + // Field list and miscellaneous variables ValueTableData::ValueTableData() { _numGroats = 0; - + _playerNewPos.roomNumber = 0; + _playerNewPos.position.x = 0; + _playerNewPos.position.y = 0; 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 86f2a0b779..d8334c8c1f 100644 --- a/engines/lure/res_struct.h +++ b/engines/lure/res_struct.h @@ -28,6 +28,8 @@ namespace Lure { +using namespace Common; + extern const char *actionList[]; /*-------------------------------------------------------------------------*/ @@ -70,6 +72,7 @@ struct HotspotResource { uint16 height; uint16 widthCopy; uint16 heightCopy; + uint16 yCorrection; int8 talkX; int8 talkY; uint16 colourOffset; @@ -136,13 +139,14 @@ struct RoomExitJoinResource { uint16 hotspot1Id; byte h1CurrentFrame; byte h1DestFrame; - uint16 h1Unknown; + uint8 h1OpenSound; + uint8 h1CloseSound; uint16 hotspot2Id; byte h2CurrentFrame; byte h2DestFrame; - uint16 h2Unknown; + uint8 h2OpenSound; + uint8 h2CloseSound; byte blocked; - uint32 unknown; } GCC_PACK; struct HotspotActionResource { @@ -173,6 +177,26 @@ struct TalkResponseResource { uint16 sequenceId3; } GCC_PACK; +struct HotspotProximityResource { + uint16 hotspotId; + uint16 x; + uint16 y; +} GCC_PACK; + +struct RoomExitCoordinateResource { + int16 x; + int16 y; + uint16 roomNumber; +} GCC_PACK; + +#define ROOM_EXIT_COORDINATES_NUM_ENTRIES 6 +#define ROOM_EXIT_COORDINATES_NUM_ROOMS 52 + +struct RoomExitCoordinateEntryResource { + RoomExitCoordinateResource entries[ROOM_EXIT_COORDINATES_NUM_ENTRIES]; + uint8 roomIndex[ROOM_EXIT_COORDINATES_NUM_ROOMS]; +} GCC_PACK; + #if !defined(__GNUC__) #pragma END_PACK_STRUCTS #endif @@ -247,11 +271,35 @@ public: RoomExitData *checkExits(int16 xp, int16 yp); }; +#define ROOM_PATHS_WIDTH 40 +#define ROOM_PATHS_HEIGHT 24 +#define ROOM_PATHS_SIZE (ROOM_PATHS_WIDTH / 8 * ROOM_PATHS_HEIGHT) +#define DECODED_PATHS_WIDTH 42 +#define DECODED_PATHS_HEIGHT 26 + +typedef uint16 RoomPathsDecompressedData[DECODED_PATHS_WIDTH * DECODED_PATHS_HEIGHT]; + +class RoomPathsData { +private: + byte _data[ROOM_PATHS_HEIGHT * ROOM_PATHS_WIDTH]; +public: + RoomPathsData() {}; + RoomPathsData(byte *srcData) { load(srcData); } + + void load(byte *srcData) { + memcpy(_data, srcData, ROOM_PATHS_SIZE); + } + bool isOccupied(int x, int y); + void setOccupied(int x, int y, int width); + void clearOccupied(int x, int y, int width); + void decompress(RoomPathsDecompressedData &dataOut, int characterWidth); +}; + #define MAX_NUM_LAYERS 4 class RoomData { public: - RoomData(RoomResource *rec); + RoomData(RoomResource *rec, MemoryBlock *pathData); uint16 roomNumber; uint16 descId; @@ -262,6 +310,7 @@ public: int16 clippingXEnd; RoomExitHotspotList exitHotspots; RoomExitList exits; + RoomPathsData paths; }; typedef ManagedList RoomDataList; @@ -273,11 +322,13 @@ public: uint16 hotspot1Id; byte h1CurrentFrame; byte h1DestFrame; - uint16 h1Unknown; + uint8 h1OpenSound; + uint8 h1CloseSound; uint16 hotspot2Id; byte h2CurrentFrame; byte h2DestFrame; - uint16 h2Unknown; + uint8 h2OpenSound; + uint8 h2CloseSound; byte blocked; uint32 unknown; }; @@ -326,6 +377,7 @@ public: uint16 height; uint16 widthCopy; uint16 heightCopy; + uint16 yCorrection; int8 talkX; int8 talkY; uint16 colourOffset; @@ -333,6 +385,9 @@ public: uint16 sequenceOffset; uint16 tickProcOffset; uint16 tickTimeout; + + void enable() { flags |= 0x80; } + void disable() { flags &= 0x7F; } }; typedef ManagedList HotspotDataList; @@ -407,7 +462,7 @@ public: typedef ManagedList TalkEntryList; -struct TalkData { +class TalkData { public: TalkData(uint16 id); ~TalkData(); @@ -421,6 +476,27 @@ public: typedef ManagedList TalkDataList; +struct RoomExitCoordinateData { + int16 x; + int16 y; + uint16 roomNumber; + byte unknown; +}; + +class RoomExitCoordinates { +private: + RoomExitCoordinateData _entries[ROOM_EXIT_COORDINATES_NUM_ENTRIES]; + uint8 _roomIndex[ROOM_EXIT_COORDINATES_NUM_ROOMS]; +public: + RoomExitCoordinates(RoomExitCoordinateEntryResource *rec); + RoomExitCoordinateData &getData(uint16 destRoomNumber); +}; + +class RoomExitCoordinatesList: public ManagedList { +public: + RoomExitCoordinates &getEntry(uint16 roomNumber); +}; + // The following classes hold any sequence offsets that are being delayed class SequenceDelayData { @@ -438,10 +514,29 @@ public: void tick(); }; +class HotspotProximityData { +public: + HotspotProximityData(HotspotProximityResource *rec); + + uint16 hotspotId; + uint16 x; + uint16 y; +}; + +class HotspotProximityList: public ManagedList { +public: + HotspotProximityData *getHotspot(uint16 hotspotId); +}; + +struct PlayerNewPosition { + Point position; + uint16 roomNumber; +}; + // The following class holds the field list used by the script engine as // well as miscellaneous fields used by the game. -#define NUM_VALUE_FIELDS 85 +#define NUM_VALUE_FIELDS 90 enum FieldName { ROOM_NUMBER = 0, @@ -463,6 +558,8 @@ enum FieldName { class ValueTableData { private: uint16 _numGroats; + PlayerNewPosition _playerNewPos; + uint16 _fieldList[NUM_VALUE_FIELDS]; bool isKnownField(uint16 fieldIndex); public: @@ -473,6 +570,7 @@ public: void setField(uint16 fieldIndex, uint16 value); void setField(FieldName fieldName, uint16 value); uint16 &numGroats() { return _numGroats; } + PlayerNewPosition &playerNewPos() { return _playerNewPos; } }; } // End of namespace Lure -- cgit v1.2.3