From 02ff4ce4950e09afb634feae4a7a854644418019 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 7 Jun 2015 11:37:15 -0400 Subject: SHERLOCK: Implemented talk/listen sequence methods --- engines/sherlock/people.h | 10 +- engines/sherlock/scalpel/scalpel_people.cpp | 30 +++++ engines/sherlock/scalpel/scalpel_people.h | 5 + engines/sherlock/scalpel/scalpel_talk.cpp | 34 +----- engines/sherlock/scalpel/scalpel_talk.h | 5 - engines/sherlock/talk.cpp | 4 +- engines/sherlock/talk.h | 8 +- engines/sherlock/tattoo/tattoo_people.cpp | 171 +++++++++++++++++++++++++++- engines/sherlock/tattoo/tattoo_people.h | 8 +- engines/sherlock/tattoo/tattoo_talk.cpp | 100 +++------------- engines/sherlock/tattoo/tattoo_talk.h | 7 +- 11 files changed, 237 insertions(+), 145 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index f991cc1b4b..4b19d44c7c 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -94,12 +94,11 @@ public: class SherlockEngine; class People { -private: +protected: + SherlockEngine *_vm; Person _data[MAX_CHARACTERS]; int _oldWalkSequence; int _srcZone, _destZone; -protected: - SherlockEngine *_vm; People(SherlockEngine *vm); public: @@ -191,6 +190,11 @@ public: * Synchronize the data for a savegame */ void synchronize(Common::Serializer &s); + + /** + * Change the sequence of the scene background object associated with the current speaker. + */ + virtual void setTalkSequence(int speaker, int sequenceNum = 1) = 0; }; } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel_people.cpp b/engines/sherlock/scalpel/scalpel_people.cpp index 5e661fe16a..08100fef11 100644 --- a/engines/sherlock/scalpel/scalpel_people.cpp +++ b/engines/sherlock/scalpel/scalpel_people.cpp @@ -86,6 +86,36 @@ void ScalpelPeople::setTalking(int speaker) { } } +void ScalpelPeople::setTalkSequence(int speaker, int sequenceNum) { + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + + // If no speaker is specified, then nothing needs to be done + if (speaker == -1) + return; + + if (speaker) { + int objNum = people.findSpeaker(speaker); + if (objNum != -1) { + Object &obj = scene._bgShapes[objNum]; + + if (obj._seqSize < MAX_TALK_SEQUENCES) { + warning("Tried to copy too many talk frames"); + } + else { + for (int idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) { + obj._sequences[idx] = people._characters[speaker]._talkSequences[idx]; + if (idx > 0 && !obj._sequences[idx] && !obj._sequences[idx - 1]) + return; + + obj._frameNumber = 0; + obj._sequenceNumber = 0; + } + } + } + } +} + } // End of namespace Scalpel } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel_people.h b/engines/sherlock/scalpel/scalpel_people.h index 0e9eec10fe..b2267790e0 100644 --- a/engines/sherlock/scalpel/scalpel_people.h +++ b/engines/sherlock/scalpel/scalpel_people.h @@ -50,6 +50,11 @@ public: * Setup the data for an animating speaker portrait at the top of the screen */ void setTalking(int speaker); + + /** + * Change the sequence of the scene background object associated with the specified speaker. + */ + virtual void setTalkSequence(int speaker, int sequenceNum = 1); }; } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel_talk.cpp b/engines/sherlock/scalpel/scalpel_talk.cpp index 2923359415..89efc70803 100644 --- a/engines/sherlock/scalpel/scalpel_talk.cpp +++ b/engines/sherlock/scalpel/scalpel_talk.cpp @@ -97,7 +97,8 @@ const byte SCALPEL_OPCODES[] = { 0, // OP_NPC_VERB_SCRIPT 0, // OP_RESTORE_PEOPLE_SEQUENCE 0, // OP_NPC_VERB_TARGET - 0 // OP_TURN_SOUNDS_OFF + 0, // OP_TURN_SOUNDS_OFF + 0 // OP_NULL }; /*----------------------------------------------------------------*/ @@ -281,7 +282,7 @@ OpcodeReturn ScalpelTalk::cmdSwitchSpeaker(const byte *&str) { people.setTalking(_speaker); pullSequence(); pushSequence(_speaker); - setSequence(_speaker); + people.setTalkSequence(_speaker); return RET_SUCCESS; } @@ -457,35 +458,6 @@ OpcodeReturn ScalpelTalk::cmdCarriageReturn(const byte *&str) { return RET_SUCCESS; } -void ScalpelTalk::setSequence(int speaker, int sequenceNum) { - People &people = *_vm->_people; - Scene &scene = *_vm->_scene; - - // If no speaker is specified, then nothing needs to be done - if (speaker == -1) - return; - - if (speaker) { - int objNum = people.findSpeaker(speaker); - if (objNum != -1) { - Object &obj = scene._bgShapes[objNum]; - - if (obj._seqSize < MAX_TALK_SEQUENCES) { - warning("Tried to copy too many talk frames"); - } else { - for (int idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) { - obj._sequences[idx] = people._characters[speaker]._talkSequences[idx]; - if (idx > 0 && !obj._sequences[idx] && !obj._sequences[idx - 1]) - return; - - obj._frameNumber = 0; - obj._sequenceNumber = 0; - } - } - } - } -} - } // 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 6dc104de08..eb97b5760d 100644 --- a/engines/sherlock/scalpel/scalpel_talk.h +++ b/engines/sherlock/scalpel/scalpel_talk.h @@ -51,11 +51,6 @@ private: OpcodeReturn cmdSummonWindow(const byte *&str); OpcodeReturn cmdCarriageReturn(const byte *&str); protected: - /** - * Change the sequence of the scene background object associated with the current speaker. - */ - virtual void setSequence(int speaker, int sequenceNum = 1); - /** * Display the talk interface window */ diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 959a769520..fe1ff705fd 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -993,9 +993,9 @@ void Talk::doScript(const Common::String &script) { pullSequence(); pushSequence(_speaker); - setSequence(_speaker); + people.setTalkSequence(_speaker); } else { - setSequence(_speaker); + people.setTalkSequence(_speaker); } if (IS_SERRATED_SCALPEL) { diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 54f6b695cc..ec8f52699e 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -104,7 +104,8 @@ enum { OP_NPC_VERB_SCRIPT = 61, OP_RESTORE_PEOPLE_SEQUENCE = 62, OP_NPC_VERB_TARGET = 63, - OP_TURN_SOUNDS_OFF = 64 + OP_TURN_SOUNDS_OFF = 64, + OP_NULL = 65 }; enum OpcodeReturn { RET_EXIT = -1, RET_SUCCESS = 0, RET_CONTINUE = 1 }; @@ -252,11 +253,6 @@ protected: OpcodeReturn cmdWalkToCAnimation(const byte *&str); OpcodeReturn cmdWalkToCoords(const byte *&str); protected: - /** - * Change the sequence of the scene background object associated with the current speaker. - */ - virtual void setSequence(int speaker, int sequenceNum = 1) = 0; - /** * Display the talk interface window */ diff --git a/engines/sherlock/tattoo/tattoo_people.cpp b/engines/sherlock/tattoo/tattoo_people.cpp index e0f4102abb..b253afd1da 100644 --- a/engines/sherlock/tattoo/tattoo_people.cpp +++ b/engines/sherlock/tattoo/tattoo_people.cpp @@ -21,17 +21,184 @@ */ #include "sherlock/tattoo/tattoo_people.h" +#include "sherlock/tattoo/tattoo_talk.h" +#include "sherlock/sherlock.h" namespace Sherlock { namespace Tattoo { void TattooPeople::setListenSequence(int speaker, int sequenceNum) { - // TODO + Scene &scene = *_vm->_scene; + + // If no speaker is specified, then nothing needs to be done + if (speaker == -1) + return; + + int objNum = findSpeaker(speaker); + if (objNum < 256 && objNum != -1) { + // See if the Object has to wait for an Abort Talk Code + Object &obj = scene._bgShapes[objNum]; + if (obj.hasAborts()) + obj._gotoSeq = sequenceNum; + else + obj.setObjTalkSequence(sequenceNum); + } else if (objNum != -1) { + objNum -= 256; + Person &person = _data[objNum]; + + int newDir = person._sequenceNumber; + switch (person._sequenceNumber) { + case WALK_UP: + case STOP_UP: + case WALK_UPRIGHT: + case STOP_UPRIGHT: + case TALK_UPRIGHT: + case LISTEN_UPRIGHT: + newDir = LISTEN_UPRIGHT; + break; + case WALK_RIGHT: + case STOP_RIGHT: + case TALK_RIGHT: + case LISTEN_RIGHT: + newDir = LISTEN_RIGHT; + break; + case WALK_DOWNRIGHT: + case STOP_DOWNRIGHT: + case TALK_DOWNRIGHT: + case LISTEN_DOWNRIGHT: + newDir = LISTEN_DOWNRIGHT; + break; + case WALK_DOWN: + case STOP_DOWN: + case WALK_DOWNLEFT: + case STOP_DOWNLEFT: + case TALK_DOWNLEFT: + case LISTEN_DOWNLEFT: + newDir = LISTEN_DOWNLEFT; + break; + case WALK_LEFT: + case STOP_LEFT: + case TALK_LEFT: + case LISTEN_LEFT: + newDir = LISTEN_LEFT; + break; + case WALK_UPLEFT: + case STOP_UPLEFT: + case TALK_UPLEFT: + case LISTEN_UPLEFT: + newDir = LISTEN_UPLEFT; + break; + + default: + break; + } + + // See if the NPC's Seq has to wait for an Abort Talk Code + if (person.hasAborts()) { + person._gotoSeq = newDir; + } else { + if (person._seqTo) { + // Reset to previous value + person._walkSequences[person._sequenceNumber]._sequences[person._frameNumber] = person._seqTo; + person._seqTo = 0; + } + + person._sequenceNumber = newDir; + person._frameNumber = 0; + person.checkWalkGraphics(); + } + } } void TattooPeople::setTalkSequence(int speaker, int sequenceNum) { - // TODO + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + TattooTalk &talk = *(TattooTalk *)_vm->_talk; + + // If no speaker is specified, then nothing needs to be done + if (speaker == -1) + return; + + int objNum = people.findSpeaker(speaker); + if (objNum != -1 && objNum < 256) { + Object &obj = scene._bgShapes[objNum]; + + // See if the Object has to wait for an Abort Talk Code + if (obj.hasAborts()) { + talk.pushTalkSequence(&obj); + obj._gotoSeq = sequenceNum; + } + else { + obj.setObjTalkSequence(sequenceNum); + } + } + else if (objNum != -1) { + objNum -= 256; + Person &person = people[objNum]; + int newDir = person._sequenceNumber; + + switch (newDir) { + case WALK_UP: + case STOP_UP: + case WALK_UPRIGHT: + case STOP_UPRIGHT: + case TALK_UPRIGHT: + case LISTEN_UPRIGHT: + newDir = TALK_UPRIGHT; + break; + case WALK_RIGHT: + case STOP_RIGHT: + case TALK_RIGHT: + case LISTEN_RIGHT: + newDir = TALK_RIGHT; + break; + case WALK_DOWNRIGHT: + case STOP_DOWNRIGHT: + case TALK_DOWNRIGHT: + case LISTEN_DOWNRIGHT: + newDir = TALK_DOWNRIGHT; + break; + case WALK_DOWN: + case STOP_DOWN: + case WALK_DOWNLEFT: + case STOP_DOWNLEFT: + case TALK_DOWNLEFT: + case LISTEN_DOWNLEFT: + newDir = TALK_DOWNLEFT; + break; + case WALK_LEFT: + case STOP_LEFT: + case TALK_LEFT: + case LISTEN_LEFT: + newDir = TALK_LEFT; + break; + case WALK_UPLEFT: + case STOP_UPLEFT: + case TALK_UPLEFT: + case LISTEN_UPLEFT: + newDir = TALK_UPLEFT; + break; + default: + break; + } + + // See if the NPC's sequence has to wait for an Abort Talk Code + if (person.hasAborts()) { + person._gotoSeq = newDir; + } + else { + if (person._seqTo) { + // Reset to previous value + person._walkSequences[person._sequenceNumber]._sequences[person._frameNumber] = person._seqTo; + person._seqTo = 0; + } + + person._sequenceNumber = newDir; + person._frameNumber = 0; + person.checkWalkGraphics(); + } + } } } // End of namespace Tattoo diff --git a/engines/sherlock/tattoo/tattoo_people.h b/engines/sherlock/tattoo/tattoo_people.h index 085e078411..481ce7804a 100644 --- a/engines/sherlock/tattoo/tattoo_people.h +++ b/engines/sherlock/tattoo/tattoo_people.h @@ -87,13 +87,11 @@ public: */ void setListenSequence(int speaker, int sequenceNum); + /** - * If the specified speaker is a background object, this will set it so that it uses - * the Talk Sequence specified. If the current sequence has an Allow Talk Code in it, - * _gotoSeq will be set so that the object begins talking as soon as it hits the - * Allow Talk Code. If there is no Abort Code, the Talk Sequence will begin immediately. + * Change the sequence of the scene background object associated with the specified speaker. */ - void setTalkSequence(int speaker, int sequenceNum); + virtual void setTalkSequence(int speaker, int sequenceNum = 1); }; } // End of namespace Scalpel diff --git a/engines/sherlock/tattoo/tattoo_talk.cpp b/engines/sherlock/tattoo/tattoo_talk.cpp index 99a6d267c3..9e20ad4237 100644 --- a/engines/sherlock/tattoo/tattoo_talk.cpp +++ b/engines/sherlock/tattoo/tattoo_talk.cpp @@ -101,7 +101,8 @@ const byte TATTOO_OPCODES[] = { 222, // OP_NPC_VERB_SCRIPT 224, // OP_RESTORE_PEOPLE_SEQUENCE 226, // OP_NPC_VERB_TARGET - 227 // OP_TURN_SOUNDS_OFF + 227, // OP_TURN_SOUNDS_OFF + 225 // OP_NULL }; /*----------------------------------------------------------------*/ @@ -175,101 +176,28 @@ TattooTalk::TattooTalk(SherlockEngine *vm) : Talk(vm) { nullptr, (OpcodeMethod)&TattooTalk::cmdRestorePeopleSequence, (OpcodeMethod)&TattooTalk::cmdSetNPCVerbTarget, - (OpcodeMethod)&TattooTalk::cmdTurnSoundsOff + (OpcodeMethod)&TattooTalk::cmdTurnSoundsOff, + nullptr }; _opcodes = TATTOO_OPCODES; _opcodeTable = OPCODE_METHODS; } -void TattooTalk::setSequence(int speaker, int sequenceNum) { - People &people = *_vm->_people; - Scene &scene = *_vm->_scene; - - // If no speaker is specified, then nothing needs to be done - if (speaker == -1) - return; - - int objNum = people.findSpeaker(speaker); - if (objNum != -1 && objNum < 256) { - Object &obj = scene._bgShapes[objNum]; - - // See if the Object has to wait for an Abort Talk Code - if (obj.hasAborts()) { - pushTalkSequence(&obj); - obj._gotoSeq = sequenceNum; - } else { - obj.setObjTalkSequence(sequenceNum); - } - } else if (objNum != -1) { - objNum -= 256; - Person &person = people[objNum]; - int newDir = person._sequenceNumber; - - switch (newDir) { - case WALK_UP: - case STOP_UP: - case WALK_UPRIGHT: - case STOP_UPRIGHT: - case TALK_UPRIGHT: - case LISTEN_UPRIGHT: - newDir = TALK_UPRIGHT; - break; - case WALK_RIGHT: - case STOP_RIGHT: - case TALK_RIGHT: - case LISTEN_RIGHT: - newDir = TALK_RIGHT; - break; - case WALK_DOWNRIGHT: - case STOP_DOWNRIGHT: - case TALK_DOWNRIGHT: - case LISTEN_DOWNRIGHT: - newDir = TALK_DOWNRIGHT; - break; - case WALK_DOWN: - case STOP_DOWN: - case WALK_DOWNLEFT: - case STOP_DOWNLEFT: - case TALK_DOWNLEFT: - case LISTEN_DOWNLEFT: - newDir = TALK_DOWNLEFT; - break; - case WALK_LEFT: - case STOP_LEFT: - case TALK_LEFT: - case LISTEN_LEFT: - newDir = TALK_LEFT; - break; - case WALK_UPLEFT: - case STOP_UPLEFT: - case TALK_UPLEFT: - case LISTEN_UPLEFT: - newDir = TALK_UPLEFT; - break; - default: - break; - } - - // See if the NPC's sequence has to wait for an Abort Talk Code - if (person.hasAborts()) { - person._gotoSeq = newDir; - } else { - if (person._seqTo) { - // Reset to previous value - person._walkSequences[person._sequenceNumber]._sequences[person._frameNumber] = person._seqTo; - person._seqTo = 0; - } +void TattooTalk::talkInterface(const byte *&str) { + drawTalk(str); - person._sequenceNumber = newDir; - person._frameNumber = 0; - person.checkWalkGraphics(); - } + _charCount = 0; + while ((*str < TATTOO_OPCODES[0] || *str == TATTOO_OPCODES[OP_NULL]) && *str) { + ++_charCount; + ++str; } + + _wait = true; } -void TattooTalk::talkInterface(const byte *&str) { - warning("TODO: TattooTalk::talkInterface"); +void TattooTalk::drawTalk(const byte *str) { + // TODO } OpcodeReturn TattooTalk::cmdSwitchSpeaker(const byte *&str) { diff --git a/engines/sherlock/tattoo/tattoo_talk.h b/engines/sherlock/tattoo/tattoo_talk.h index ee99fceeec..0b5e7e4ae7 100644 --- a/engines/sherlock/tattoo/tattoo_talk.h +++ b/engines/sherlock/tattoo/tattoo_talk.h @@ -71,12 +71,9 @@ private: OpcodeReturn cmdWalkNPCToCAnimation(const byte *&str); OpcodeReturn cmdWalkNPCToCoords(const byte *&str); OpcodeReturn cmdWalkHomesAndNPCToCoords(const byte *&str); +private: + void drawTalk(const byte *str); protected: - /** - * Change the sequence of the scene background object associated with the current speaker. - */ - virtual void setSequence(int speaker, int sequenceNum = 1); - /** * Display the talk interface window */ -- cgit v1.2.3