From d4e5e447925d251afca20afec0e090b210740c82 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 18 Aug 2015 20:53:31 -0400 Subject: SHERLOCK: Standardize sequence stack code for both games --- engines/sherlock/objects.cpp | 14 +----- engines/sherlock/scalpel/scalpel_talk.cpp | 25 +++++++++- engines/sherlock/scalpel/scalpel_talk.h | 14 +++++- engines/sherlock/scene.h | 2 +- engines/sherlock/talk.cpp | 83 +++++++------------------------ engines/sherlock/talk.h | 41 ++++++--------- engines/sherlock/tattoo/tattoo_people.cpp | 2 +- engines/sherlock/tattoo/tattoo_talk.cpp | 58 +++++++++++++++------ engines/sherlock/tattoo/tattoo_talk.h | 10 +++- 9 files changed, 124 insertions(+), 125 deletions(-) (limited to 'engines/sherlock') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index b412724002..533d2bcc67 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -1228,26 +1228,16 @@ void Object::setObjTalkSequence(int seq) { // See if we're supposed to restore the object's sequence from the talk sequence stack if (seq == -1) { - TalkSequence &ts = talk._talkSequenceStack[_restoreSlot]; if (_seqTo != 0) _sequences[_frameNumber] = _seqTo; - _frameNumber = ts._frameNumber; - _sequenceNumber = ts._sequenceNumber; - _seqStack = ts._seqStack; - _seqTo = ts._seqTo; - _seqCounter = ts._seqCounter; - _seqCounter2 = ts._seqCounter2; - _talkSeq = 0; - - // Flag this slot as free again - ts._obj = nullptr; + talk.pullSequence(_restoreSlot); return; } assert(_type != CHARACTER); - talk.pushTalkSequence(this); + talk.pushSequenceEntry(this); int talkSeqNum = seq; // Find where the talk sequence data begins in the object diff --git a/engines/sherlock/scalpel/scalpel_talk.cpp b/engines/sherlock/scalpel/scalpel_talk.cpp index 61e736483c..4debe7fc26 100644 --- a/engines/sherlock/scalpel/scalpel_talk.cpp +++ b/engines/sherlock/scalpel/scalpel_talk.cpp @@ -879,7 +879,26 @@ OpcodeReturn ScalpelTalk::cmdCallTalkFile(const byte *&str) { return RET_SUCCESS; } -void ScalpelTalk::pullSequence() { +void ScalpelTalk::pushSequenceEntry(Object *obj) { + Scene &scene = *_vm->_scene; + SequenceEntry seqEntry; + seqEntry._objNum = scene._bgShapes.indexOf(*obj); + + if (seqEntry._objNum != -1) { + Object &obj = scene._bgShapes[seqEntry._objNum]; + for (uint idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) + seqEntry._sequences.push_back(obj._sequences[idx]); + + seqEntry._frameNumber = obj._frameNumber; + seqEntry._seqTo = obj._seqTo; + } + + _sequenceStack.push(seqEntry); + if (_scriptStack.size() >= 5) + error("script stack overflow"); +} + +void ScalpelTalk::pullSequence(int slot) { Scene &scene = *_vm->_scene; if (_sequenceStack.empty()) @@ -901,6 +920,10 @@ void ScalpelTalk::pullSequence() { } } +void ScalpelTalk::clearSequences() { + _sequenceStack.clear(); +} + } // End of namespace Scalpel } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel_talk.h b/engines/sherlock/scalpel/scalpel_talk.h index 1d70db14b9..9e07b26dc8 100644 --- a/engines/sherlock/scalpel/scalpel_talk.h +++ b/engines/sherlock/scalpel/scalpel_talk.h @@ -37,6 +37,8 @@ namespace Scalpel { class ScalpelTalk : public Talk { private: + Common::Stack _sequenceStack; + OpcodeReturn cmdSwitchSpeaker(const byte *&str); OpcodeReturn cmdAssignPortraitLocation(const byte *&str); OpcodeReturn cmdGotoScene(const byte *&str); @@ -102,16 +104,26 @@ public: */ void talk3DOMovieTrigger(int subIndex); + /** + * Push the details of a passed object onto the saved sequences stack + */ + virtual void pushSequenceEntry(Object *obj); + /** * Pulls a background object sequence from the sequence stack and restore's the * object's sequence */ - virtual void pullSequence(); + virtual void pullSequence(int slot = -1); /** * Returns true if the script stack is empty */ virtual bool isSequencesEmpty() const { return _scriptStack.empty(); } + + /** + * Clears the stack of pending object sequences associated with speakers in the scene + */ + virtual void clearSequences(); }; } // End of namespace Scalpel diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 42bee4f127..f75dfb40cd 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -220,7 +220,7 @@ public: Common::String _comments; Common::Array _descText; Common::Array _zones; - Common::Array _bgShapes; + ObjectArray _bgShapes; Common::Array _cAnim; Common::Array _sequenceBuffer; Common::Array _images; diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index efe0eccf60..a81041a189 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -36,8 +36,11 @@ namespace Sherlock { SequenceEntry::SequenceEntry() { _objNum = 0; - _frameNumber = 0; + _obj = nullptr; + _seqStack = 0; _seqTo = 0; + _sequenceNumber = _frameNumber = 0; + _seqCounter = _seqCounter2 = 0; } /*----------------------------------------------------------------*/ @@ -87,17 +90,6 @@ TalkHistoryEntry::TalkHistoryEntry() { /*----------------------------------------------------------------*/ -TalkSequence::TalkSequence() { - _obj = nullptr; - _frameNumber = 0; - _sequenceNumber = 0; - _seqStack = 0; - _seqTo = 0; - _seqCounter = _seqCounter2 = 0; -} - -/*----------------------------------------------------------------*/ - Talk *Talk::init(SherlockEngine *vm) { if (vm->getGameID() == GType_SerratedScalpel) return new Scalpel::ScalpelTalk(vm); @@ -203,7 +195,7 @@ void Talk::talkTo(const Common::String &filename) { } } - while (!_sequenceStack.empty()) + while (!isSequencesEmpty()) pullSequence(); if (IS_SERRATED_SCALPEL) { @@ -636,62 +628,16 @@ void Talk::setTalkMap() { } } -void Talk::clearSequences() { - _sequenceStack.clear(); -} - void Talk::pushSequence(int speaker) { People &people = *_vm->_people; Scene &scene = *_vm->_scene; // Only proceed if a speaker is specified - if (speaker == -1 || IS_ROSE_TATTOO) - return; - - SequenceEntry seqEntry; - if (!speaker) { - seqEntry._objNum = -1; - } else { - seqEntry._objNum = people.findSpeaker(speaker); - - if (seqEntry._objNum != -1) { - Object &obj = scene._bgShapes[seqEntry._objNum]; - for (uint idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) - seqEntry._sequences.push_back(obj._sequences[idx]); - - seqEntry._frameNumber = obj._frameNumber; - seqEntry._seqTo = obj._seqTo; - } - } - - _sequenceStack.push(seqEntry); - if (_scriptStack.size() >= 5) - error("script stack overflow"); -} - -void Talk::pushTalkSequence(Object *obj) { - // Check if the shape is already on the stack - for (uint idx = 0; idx < TALK_SEQUENCE_STACK_SIZE; ++idx) { - if (_talkSequenceStack[idx]._obj == obj) - return; - } - - // Find a free slot and save the details in it - for (uint idx = 0; idx < TALK_SEQUENCE_STACK_SIZE; ++idx) { - TalkSequence &ts = _talkSequenceStack[idx]; - if (ts._obj == nullptr) { - ts._obj = obj; - ts._frameNumber = obj->_frameNumber; - ts._sequenceNumber = obj->_sequenceNumber; - ts._seqStack = obj->_seqStack; - ts._seqTo = obj->_seqTo; - ts._seqCounter = obj->_seqCounter; - ts._seqCounter2 = obj->_seqCounter2; - return; - } + if (speaker != -1) { + int objNum = people.findSpeaker(speaker); + if (objNum != -1) + pushSequenceEntry(&scene._bgShapes[objNum]); } - - error("Ran out of talk sequence stack space"); } void Talk::doScript(const Common::String &script) { @@ -744,10 +690,15 @@ void Talk::doScript(const Common::String &script) { // Need to switch speakers? if (str[0] == _opcodes[OP_SWITCH_SPEAKER]) { _speaker = str[1] - 1; - str += IS_SERRATED_SCALPEL ? 2 : 3; - pullSequence(); - pushSequence(_speaker); + if (IS_SERRATED_SCALPEL) { + str += 2; + pullSequence(); + pushSequence(_speaker); + } else { + str += 3; + } + people.setTalkSequence(_speaker); } else { people.setTalkSequence(_speaker); diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 7d40c2235b..d0c26b529f 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -35,7 +35,6 @@ namespace Sherlock { #define SPEAKER_REMOVE 0x80 #define MAX_TALK_SEQUENCES 11 -#define TALK_SEQUENCE_STACK_SIZE 20 enum { OP_SWITCH_SPEAKER = 0, @@ -120,8 +119,13 @@ typedef OpcodeReturn(Talk::*OpcodeMethod)(const byte *&str); struct SequenceEntry { int _objNum; Common::Array _sequences; - int _frameNumber; - int _seqTo; + Object *_obj; // Pointer to the bgshape that these values go to + short _frameNumber; // Frame number in frame sequence to draw + short _sequenceNumber; // Start frame of sequences that are repeated + int _seqStack; // Allows gosubs to return to calling frame + int _seqTo; // Allows 1-5, 8-3 type sequences encoded + int _seqCounter; // How many times this sequence has been executed + int _seqCounter2; SequenceEntry(); }; @@ -158,19 +162,6 @@ struct TalkHistoryEntry { bool &operator[](int index) { return _data[index]; } }; -struct TalkSequence { - Object *_obj; // Pointer to the bgshape that these values go to - short _frameNumber; // Frame number in frame sequence to draw - short _sequenceNumber; // Start frame of sequences that are repeated - int _seqStack; // Allows gosubs to return to calling frame - int _seqTo; // Allows 1-5, 8-3 type sequences encoded - int _seqCounter; // How many times this sequence has been executed - int _seqCounter2; - - TalkSequence(); -}; - - class Talk { friend class Scalpel::ScalpelUserInterface; private: @@ -182,7 +173,6 @@ protected: SherlockEngine *_vm; OpcodeMethod *_opcodeTable; Common::Stack _savedSequences; - Common::Stack _sequenceStack; Common::Stack _scriptStack; Common::Array _talkHistory; int _talkIndex; @@ -264,7 +254,6 @@ protected: */ virtual void switchSpeaker(int subIndex) {} public: - TalkSequence _talkSequenceStack[TALK_SEQUENCE_STACK_SIZE]; Common::Array _statements; bool _talkToAbort; int _talkCounter; @@ -320,11 +309,6 @@ public: */ void loadTalkFile(const Common::String &filename); - /** - * Clears the stack of pending object sequences associated with speakers in the scene - */ - void clearSequences(); - /** * Push the sequence of a background object that's an NPC that needs to be * saved onto the sequence stack. @@ -332,9 +316,14 @@ public: void pushSequence(int speaker); /** - * Push a given shape's sequence data onto the Rose Tattoo talk sequence stack + * Push the details of a passed object onto the saved sequences stack + */ + virtual void pushSequenceEntry(Object *obj) = 0; + + /** + * Clears the stack of pending object sequences associated with speakers in the scene */ - void pushTalkSequence(Object *obj); + virtual void clearSequences() {} /** * Pops an entry off of the script stack @@ -366,7 +355,7 @@ public: * Pulls a background object sequence from the sequence stack and restore's the * object's sequence */ - virtual void pullSequence() = 0; + virtual void pullSequence(int slot = -1) = 0; /** * Returns true if the script stack is empty diff --git a/engines/sherlock/tattoo/tattoo_people.cpp b/engines/sherlock/tattoo/tattoo_people.cpp index 4974b3df40..a208949ae1 100644 --- a/engines/sherlock/tattoo/tattoo_people.cpp +++ b/engines/sherlock/tattoo/tattoo_people.cpp @@ -1271,7 +1271,7 @@ void TattooPeople::setTalkSequence(int speaker, int sequenceNum) { // See if the Object has to wait for an Abort Talk Code if (obj.hasAborts()) { - talk.pushTalkSequence(&obj); + talk.pushSequenceEntry(&obj); obj._gotoSeq = sequenceNum; } else { diff --git a/engines/sherlock/tattoo/tattoo_talk.cpp b/engines/sherlock/tattoo/tattoo_talk.cpp index 49becbe3b4..455d41bd48 100644 --- a/engines/sherlock/tattoo/tattoo_talk.cpp +++ b/engines/sherlock/tattoo/tattoo_talk.cpp @@ -216,7 +216,6 @@ void TattooTalk::showTalk() { TattooPeople &people = *(TattooPeople *)_vm->_people; TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; - _sequenceStack.clear(); people.setListenSequence(_talkTo, 129); _talkWidget.load(); @@ -897,33 +896,60 @@ OpcodeReturn TattooTalk::cmdCallTalkFile(const byte *&str) { return RET_SUCCESS; } -void TattooTalk::pullSequence() { +void TattooTalk::pushSequenceEntry(Object *obj) { + // Check if the shape is already on the stack + for (uint idx = 0; idx < TALK_SEQUENCE_STACK_SIZE; ++idx) { + if (_sequenceStack[idx]._obj == obj) + return; + } + + // Find a free slot and save the details in it + for (uint idx = 0; idx < TALK_SEQUENCE_STACK_SIZE; ++idx) { + SequenceEntry &seq = _sequenceStack[idx]; + if (seq._obj == nullptr) { + seq._obj = obj; + seq._frameNumber = obj->_frameNumber; + seq._sequenceNumber = obj->_sequenceNumber; + seq._seqStack = obj->_seqStack; + seq._seqTo = obj->_seqTo; + seq._seqCounter = obj->_seqCounter; + seq._seqCounter2 = obj->_seqCounter2; + return; + } + } + + error("Ran out of talk sequence stack space"); +} + +void TattooTalk::pullSequence(int slot) { People &people = *_vm->_people; for (int idx = 0; idx < TALK_SEQUENCE_STACK_SIZE; ++idx) { - TalkSequence &ts = _talkSequenceStack[idx]; + SequenceEntry &seq = _sequenceStack[idx]; + if (slot != -1 && idx != slot) + continue; // Check for an entry in this slot - if (ts._obj) { - Object &o = *ts._obj; + if (seq._obj) { + Object &o = *seq._obj; // See if we're not supposed to restore it until an Allow Talk Interrupt - if (ts._obj->hasAborts()) { - ts._obj->_gotoSeq = -1; - ts._obj->_restoreSlot = idx; + if (seq._obj->hasAborts()) { + seq._obj->_gotoSeq = -1; + seq._obj->_restoreSlot = idx; } else { // Restore the object's sequence information immediately - o._frameNumber = ts._frameNumber; - o._sequenceNumber = ts._sequenceNumber; - o._seqStack = ts._seqStack; - o._seqTo = ts._seqTo; - o._seqCounter = ts._seqCounter; - o._seqCounter2 = ts._seqCounter2; + o._frameNumber = seq._frameNumber; + o._sequenceNumber = seq._sequenceNumber; + o._seqStack = seq._seqStack; + o._seqTo = seq._seqTo; + o._seqCounter = seq._seqCounter; + o._seqCounter2 = seq._seqCounter2; o._gotoSeq = 0; o._talkSeq = 0; // Flag the slot as free again - ts._obj = nullptr; + seq._obj = nullptr; } } } @@ -950,7 +976,7 @@ void TattooTalk::pullSequence() { bool TattooTalk::isSequencesEmpty() const { for (int idx = 0; idx < TALK_SEQUENCE_STACK_SIZE; ++idx) { - if (_talkSequenceStack[idx]._obj) + if (_sequenceStack[idx]._obj) return false; } diff --git a/engines/sherlock/tattoo/tattoo_talk.h b/engines/sherlock/tattoo/tattoo_talk.h index 68db063751..3976f15e32 100644 --- a/engines/sherlock/tattoo/tattoo_talk.h +++ b/engines/sherlock/tattoo/tattoo_talk.h @@ -37,6 +37,8 @@ namespace Sherlock { namespace Tattoo { +#define TALK_SEQUENCE_STACK_SIZE 20 + class WidgetTalk; class TattooTalk : public Talk { @@ -44,6 +46,7 @@ class TattooTalk : public Talk { private: WidgetTalk _talkWidget; WidgetPassword _passwordWidget; + SequenceEntry _sequenceStack[TALK_SEQUENCE_STACK_SIZE]; OpcodeReturn cmdCallTalkFile(const byte *&str); OpcodeReturn cmdSwitchSpeaker(const byte *&str); @@ -101,11 +104,16 @@ public: TattooTalk(SherlockEngine *vm); virtual ~TattooTalk() {} + /** + * Push the details of a passed object onto the saved sequences stack + */ + virtual void pushSequenceEntry(Object *obj); + /** * Pulls a background object sequence from the sequence stack and restore's the * object's sequence */ - virtual void pullSequence(); + virtual void pullSequence(int slot = -1); /** * Returns true if the script stack is empty -- cgit v1.2.3