From d804bad5512577b2a268f8985422038eb5d3927d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 10 Jan 2008 13:37:34 +0000 Subject: Replaced the Blacksmith hack with an NPC Schedules list that stores the active schedule of an NPC when it's deactivated in case it's later reactivated again. svn-id: r30378 --- engines/lure/hotspots.cpp | 111 ++++++++++++++++++++++++++++++++++++++++---- engines/lure/hotspots.h | 20 ++++++++ engines/lure/luredefs.h | 2 +- engines/lure/res.cpp | 9 ++++ engines/lure/res.h | 2 + engines/lure/res_struct.cpp | 22 +++++---- engines/lure/res_struct.h | 1 + 7 files changed, 149 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp index 534fe41acf..b585f2a968 100644 --- a/engines/lure/hotspots.cpp +++ b/engines/lure/hotspots.cpp @@ -43,6 +43,7 @@ namespace Lure { Hotspot::Hotspot(HotspotData *res): _pathFinder(this) { Resources &resources = Resources::getReference(); + HotspotSchedules &schedules = resources.hotspotSchedules(); bool isEGA = LureEngine::getReference().isEGA(); _data = res; @@ -88,7 +89,14 @@ Hotspot::Hotspot(HotspotData *res): _pathFinder(this) { _startRoomNumber = 0; _supportValue = 0; - if (_data->npcSchedule != 0) { + HotspotScheduleRecord *rec = schedules.check(_hotspotId); + if (rec != NULL) { + // Hotspot was previously active, so restore prior schedule + _currentActions.copyFrom(*rec); + schedules.remove(_hotspotId); + + } else if (_data->npcSchedule != 0) { + // Set up default schedule based on given Schedule Id CharacterScheduleEntry *entry = resources.charSchedules().getEntry(_data->npcSchedule); _currentActions.addFront(DISPATCH_ACTION, entry, _roomNumber); } @@ -204,13 +212,9 @@ Hotspot::Hotspot(): _pathFinder(NULL) { } Hotspot::~Hotspot() { - // WORKAROUND: If Blacksmith is being deactivated, make sure his animation is - // reset back to his standard movement set - if (_hotspotId == BLACKSMITH_ID) { - Resources &res = Resources::getReference(); - HotspotAnimData *tempAnim = res.animRecords()[BLACKSMITH_DEFAULT_ANIM_INDEX]; - assert(tempAnim); - _data->animRecordId = tempAnim->animRecordId; + if ((_data != NULL) && (_data->npcSchedule != 0)) { + // When deactivating an NPC schedule, store in case the NPC is later reactivated + Resources::getReference().hotspotSchedules().add(_hotspotId, _currentActions); } if (_frames) delete _frames; @@ -4464,6 +4468,19 @@ CurrentActionEntry::CurrentActionEntry(Action newAction, uint16 roomNum, uint16 _roomNumber = roomNum; } +CurrentActionEntry::CurrentActionEntry(CurrentActionEntry *src) { + _action = src->_action; + _dynamicSupportData = src->_dynamicSupportData; + _roomNumber = src->_roomNumber; + if (!_dynamicSupportData) + _supportData = src->_supportData; + else if (src->_supportData == NULL) + _supportData = NULL; + else { + _supportData = new CharacterScheduleEntry(src->_supportData); + } +} + void CurrentActionEntry::setSupportData(uint16 entryId) { CharacterScheduleEntry &entry = supportData(); @@ -4624,6 +4641,15 @@ void CurrentActionStack::loadFromStream(ReadStream *stream) { _actions.push_back(rec); } +void CurrentActionStack::copyFrom(CurrentActionStack &stack) { + ManagedList::iterator i; + + for (i = stack._actions.begin(); i != stack._actions.end(); ++i) { + CurrentActionEntry *rec = *i; + _actions.push_back(new CurrentActionEntry(rec)); + } +} + /*-------------------------------------------------------------------------*/ /* Support methods */ /* */ @@ -4813,4 +4839,73 @@ void HotspotList::loadFromStream(ReadStream *stream) { } } +HotspotScheduleRecord::HotspotScheduleRecord(uint16 hotspotId, CurrentActionStack &stack) { + this->hotspotId = hotspotId; + copyFrom(stack); +} + +HotspotScheduleRecord::HotspotScheduleRecord(uint16 hotspotId) { + this->hotspotId = hotspotId; +} + +void HotspotSchedules::saveToStream(WriteStream *stream) { + iterator i; + + debugC(ERROR_DETAILED, kLureDebugAnimations, "Saving hotspot schedules stack"); + + for (i = begin(); i != end(); ++i) { + HotspotScheduleRecord *rec = *i; + stream->writeUint16LE(rec->hotspotId); + rec->saveToStream(stream); + } + stream->writeUint16LE(0xffff); // End of list marker + debugC(ERROR_DETAILED, kLureDebugAnimations, "Finished saving hotspot schedules stack"); +} + +void HotspotSchedules::loadFromStream(ReadStream *stream) { + iterator i; + uint16 hId; + + debugC(ERROR_DETAILED, kLureDebugAnimations, "Loading hotspot schedules stack"); + + clear(); + while ((hId = stream->readUint16LE()) != 0xffff) { + HotspotScheduleRecord *rec = new HotspotScheduleRecord(hId); + rec->loadFromStream(stream); + } + + debugC(ERROR_DETAILED, kLureDebugAnimations, "Loading saving hotspot schedules stack"); +} + +void HotspotSchedules::add(uint16 hotspotId, CurrentActionStack &actions) { + HotspotScheduleRecord *rec = new HotspotScheduleRecord(hotspotId, actions); + push_back(rec); +} + +void HotspotSchedules::remove(uint16 hotspotId) { + iterator i; + + for (i = begin(); i != end(); ++i) { + HotspotScheduleRecord *rec = *i; + + if (rec->hotspotId == hotspotId) { + erase(i); + return; + } + } +} + +HotspotScheduleRecord *HotspotSchedules::check(uint16 hotspotId) { + iterator i; + + for (i = begin(); i != end(); ++i) { + HotspotScheduleRecord *rec = *i; + + if (rec->hotspotId == hotspotId) + return rec; + } + + return NULL; +} + } // end of namespace Lure diff --git a/engines/lure/hotspots.h b/engines/lure/hotspots.h index 75953b9259..789776167e 100644 --- a/engines/lure/hotspots.h +++ b/engines/lure/hotspots.h @@ -108,6 +108,7 @@ public: CurrentActionEntry(CurrentAction newAction, uint16 roomNum); CurrentActionEntry(CurrentAction newAction, CharacterScheduleEntry *data, uint16 roomNum); CurrentActionEntry(Action newAction, uint16 roomNum, uint16 param1, uint16 param2); + CurrentActionEntry(CurrentActionEntry *src); virtual ~CurrentActionEntry() { if (_dynamicSupportData) delete _supportData; } @@ -177,6 +178,7 @@ public: void saveToStream(WriteStream *stream); void loadFromStream(ReadStream *stream); + void copyFrom(CurrentActionStack &stack); }; class WalkingActionEntry { @@ -249,6 +251,24 @@ struct DestStructure { Point position; }; +class HotspotScheduleRecord: public CurrentActionStack { +public: + uint16 hotspotId; + + HotspotScheduleRecord(uint16 hotspotId, CurrentActionStack &stack); + HotspotScheduleRecord(uint16 hotspotId); +}; + +class HotspotSchedules: public ManagedList { +public: + void add(uint16 hotspotId, CurrentActionStack &actions); + void remove(uint16 hotspotId); + HotspotScheduleRecord *check(uint16 hotspotId); + void saveToStream(Common::WriteStream *stream); + void loadFromStream(Common::ReadStream *stream); +}; + + #define MAX_NUM_FRAMES 16 class Hotspot { diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h index 4cdee1343f..ea05a51b41 100644 --- a/engines/lure/luredefs.h +++ b/engines/lure/luredefs.h @@ -36,7 +36,7 @@ namespace Lure { #define LURE_DAT_MAJOR 1 #define LURE_DAT_MINOR 28 #define LURE_MIN_SAVEGAME_MINOR 25 -#define LURE_SAVEGAME_MINOR 30 +#define LURE_SAVEGAME_MINOR 31 #define LURE_DEBUG 1 diff --git a/engines/lure/res.cpp b/engines/lure/res.cpp index fd6fe357aa..a3eb33660d 100644 --- a/engines/lure/res.cpp +++ b/engines/lure/res.cpp @@ -98,6 +98,7 @@ void Resources::reset() { _fieldList.reset(); _barmanLists.reset(); + _hotspotSchedules.clear(); _talkState = TALK_NONE; _activeTalkData = NULL; @@ -732,6 +733,7 @@ void Resources::saveToStream(Common::WriteStream *stream) { // Save sublist data _hotspotData.saveToStream(stream); _activeHotspots.saveToStream(stream); + _hotspotSchedules.saveToStream(stream); _fieldList.saveToStream(stream); _randomActions.saveToStream(stream); _barmanLists.saveToStream(stream); @@ -757,6 +759,13 @@ void Resources::loadFromStream(Common::ReadStream *stream) { _hotspotData.loadFromStream(stream); debugC(ERROR_DETAILED, kLureDebugScripts, "Loading active hotspots"); _activeHotspots.loadFromStream(stream); + + _hotspotSchedules.clear(); + if (saveVersion >= 31) { + _hotspotSchedules.loadFromStream(stream); + debugC(ERROR_DETAILED, kLureDebugScripts, "Loading hotspot schedules"); + } + debugC(ERROR_DETAILED, kLureDebugScripts, "Loading fields"); _fieldList.loadFromStream(stream); debugC(ERROR_DETAILED, kLureDebugScripts, "Loading random actions"); diff --git a/engines/lure/res.h b/engines/lure/res.h index ac0430e32d..aaf50754f9 100644 --- a/engines/lure/res.h +++ b/engines/lure/res.h @@ -79,6 +79,7 @@ private: PausedCharacterList _pausedList; BarmanLists _barmanLists; StringList _stringList; + HotspotSchedules _hotspotSchedules; int numCharOffsets; uint16 *_charOffsets; @@ -134,6 +135,7 @@ public: RoomExitIndexedHotspotList &exitHotspots() { return _indexedRoomExitHospots; } PausedCharacterList &pausedList() { return _pausedList; } BarmanLists &barmanLists() { return _barmanLists; } + HotspotSchedules &hotspotSchedules() { return _hotspotSchedules; } StringList &stringList() { return _stringList; } uint16 getCharOffset(int index) { if (index >= numCharOffsets) diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp index 991eca7b7f..2d4e3a9d8c 100644 --- a/engines/lure/res_struct.cpp +++ b/engines/lure/res_struct.cpp @@ -741,6 +741,8 @@ SequenceDelayData *SequenceDelayData::load(uint32 delay, uint16 seqOffset, bool } void SequenceDelayList::add(uint16 delay, uint16 seqOffset, bool canClear) { + debugC(ERROR_DETAILED, kLureDebugScripts, "Delay List add sequence=%xh delay=%d canClear=%d", + seqOffset, delay, (int)canClear); SequenceDelayData *entry = new SequenceDelayData(delay, seqOffset, canClear); push_front(entry); } @@ -750,20 +752,15 @@ void SequenceDelayList::tick() { uint32 currTime = g_system->getMillis(); SequenceDelayList::iterator i; + debugC(ERROR_DETAILED, kLureDebugScripts, "Delay List check start at time %d", currTime); + for (i = begin(); i != end(); i++) { SequenceDelayData *entry = *i; + debugC(ERROR_DETAILED, kLureDebugScripts, "Delay List check %xh at time %d", entry->sequenceOffset, entry->timeoutCtr); + if (currTime >= entry->timeoutCtr) { // Timeout reached - delete entry from list and execute the sequence uint16 seqOffset = entry->sequenceOffset; - - // FIXME: At current speed the player can enter the cave a bit too quickly ahead of Goewin. - // Use a hard-coded check to make sure Goewin is in the room - if (seqOffset == 0xebd) { - Hotspot *goewinHotspot = res.getActiveHotspot(GOEWIN_ID); - if (goewinHotspot->roomNumber() != 38) - return; - } - erase(i); Script::execute(seqOffset); return; @@ -842,6 +839,13 @@ CharacterScheduleEntry::CharacterScheduleEntry(CharacterScheduleSet *parentSet, (_numParams + 1) * sizeof(uint16)); } +CharacterScheduleEntry::CharacterScheduleEntry(CharacterScheduleEntry *src) { + _parent = src->_parent; + _action = src->_action; + _numParams = src->_numParams; + Common::copy(src->_params, src->_params + MAX_TELL_COMMANDS * 3 * sizeof(uint16), _params); +} + uint16 CharacterScheduleEntry::param(int index) { if ((index < 0) || (index >= numParams())) error("Invalid parameter index %d on handling action %d", index, _action); diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h index ea2836080e..9469fa939e 100644 --- a/engines/lure/res_struct.h +++ b/engines/lure/res_struct.h @@ -667,6 +667,7 @@ public: CharacterScheduleEntry(Action theAction, ...); CharacterScheduleEntry(CharacterScheduleSet *parentSet, CharacterScheduleResource *&rec); + CharacterScheduleEntry(CharacterScheduleEntry *src); Action action() { return _action; } int numParams() { return _numParams; } -- cgit v1.2.3