aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2015-06-03 21:03:44 -0400
committerPaul Gilbert2015-06-03 21:03:44 -0400
commit60378fe22883387c9d116764dc631c5cd5a6d3f8 (patch)
treea1503969168bb2775a29b82fdd57a722a12c5421
parentbc7127c52222fc98c36f6b33b534acdcb10027c8 (diff)
downloadscummvm-rg350-60378fe22883387c9d116764dc631c5cd5a6d3f8.tar.gz
scummvm-rg350-60378fe22883387c9d116764dc631c5cd5a6d3f8.tar.bz2
scummvm-rg350-60378fe22883387c9d116764dc631c5cd5a6d3f8.zip
SHERLOCK: Implemented setObjTalkSequence methods
-rw-r--r--engines/sherlock/objects.cpp101
-rw-r--r--engines/sherlock/objects.h15
-rw-r--r--engines/sherlock/talk.cpp38
-rw-r--r--engines/sherlock/talk.h25
4 files changed, 164 insertions, 15 deletions
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 124e7c5c1c..9e4a20f565 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -368,6 +368,24 @@ const Common::Rect Sprite::getOldBounds() const {
return Common::Rect(_oldPosition.x, _oldPosition.y, _oldPosition.x + _oldSize.x, _oldPosition.y + _oldSize.y);
}
+void Sprite::setObjTalkSequence(int seq) {
+ assert(seq != -1 && _type == CHARACTER);
+
+ if (_seqTo) {
+ // reset to previous value
+ _walkSequences[_sequenceNumber]._sequences[_frameNumber] = _seqTo;
+ _seqTo = 0;
+ }
+
+ _sequenceNumber = _gotoSeq;
+ _frameNumber = 0;
+ checkWalkGraphics();
+}
+
+void Sprite::checkWalkGraphics() {
+ error("TODO: checkWalkGraphics");
+}
+
/*----------------------------------------------------------------*/
void WalkSequence::load(Common::SeekableReadStream &s) {
@@ -493,7 +511,7 @@ Object::Object() {
_requiredFlag1 = 0;
_gotoSeq = 0;
_talkSeq = 0;
- _restoreSlot = 0;
+ _restoreSlot = -1;
}
void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
@@ -888,7 +906,86 @@ void Object::setObjSequence(int seq, bool wait) {
}
void Object::setObjTalkSequence(int seq) {
- error("TODO: setObjTalkSequence");
+ Talk &talk = *_vm->_talk;
+
+ // 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;
+
+ return;
+ }
+
+ assert(_type != CHARACTER);
+
+ // If the object passed in is an NPC, set it's sequence through the sequence number rather
+ // than adjusting the frame number to a specific sub-sequence
+ /*
+ s = (SpriteType *)bg;
+ if (s->seqto)
+ {
+ // reset to previous value
+ s->WalkSeqs[s->fs]->Seq[s->fn] = s->seqto;
+ s->seqto = 0;
+ }
+ s->fs = s->GotoSeq;
+ s->fn = 0;
+ CheckWalkGraphics(s);
+ */
+
+ talk.pushTalkSequence(this);
+ int talkSeqNum = seq;
+
+ // Find where the talk sequence data begins in the object
+ int idx = 0;
+ for (;;) {
+ // Get the Frame value
+ byte f = _sequences[idx++];
+
+ // See if we've found the beginning of a Talk Sequence
+ if ((f == TALK_SEQ_CODE && seq < 128) || (f == TALK_LISTEN_CODE && seq > 128)) {
+ --seq;
+
+ // See if we're at the correct Talk Sequence Number
+ if (!(seq & 127))
+ {
+ // Correct Sequence, Start Talking Here
+ if (_seqTo != 0)
+ _sequences[_frameNumber] = _seqTo;
+ _frameNumber = idx;
+ _seqTo = 0;
+ _seqStack = 0;
+ _seqCounter = 0;
+ _seqCounter2 = 0;
+ _talkSeq = talkSeqNum;
+ break;
+ }
+ } else {
+ // Move ahead any extra because of special control codes
+ switch (f) {
+ case 0: idx++; break;
+ case MOVE_CODE:
+ case TELEPORT_CODE: idx += 4; break;
+ case CALL_TALK_CODE: idx += 8; break;
+ case HIDE_CODE: idx += 2; break;
+ }
+ }
+
+ // See if we're out of sequence data
+ if (idx >= (int)_seqSize)
+ break;
+ }
}
int Object::checkNameForCodes(const Common::String &name, const char *const messages[]) {
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index 936adc57d0..bd32948763 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -165,6 +165,12 @@ struct UseType {
class Sprite {
private:
static SherlockEngine *_vm;
+
+ /**
+ * Checks a sprite associated with an NPC to see if the frame sequence specified
+ * in the sequence number uses alternate graphics, and if so if they need to be loaded
+ */
+ void checkWalkGraphics();
public:
Common::String _name;
Common::String _description;
@@ -243,6 +249,15 @@ public:
void checkSprite();
/**
+ * Adjusts the frame and sequence variables of a sprite that corresponds to the current speaker
+ * so that it points to the beginning of the sequence number's talk sequence in the object's
+ * sequence buffer
+ * @param seq Which sequence to use (if there's more than 1)
+ * @remarks 1: First talk seq, 2: second talk seq, etc.
+ */
+ void setObjTalkSequence(int seq);
+
+ /**
* Return frame width
*/
int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; }
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 319cb10850..bb5c11c81f 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -222,12 +222,13 @@ TalkHistoryEntry::TalkHistoryEntry() {
/*----------------------------------------------------------------*/
-TalkSequences::TalkSequences(const byte *data) {
- Common::copy(data, data + MAX_TALK_SEQUENCES, _data);
-}
-
-void TalkSequences::clear() {
- Common::fill(&_data[0], &_data[MAX_TALK_SEQUENCES], 0);
+TalkSequence::TalkSequence() {
+ _obj = nullptr;
+ _frameNumber = 0;
+ _sequenceNumber = 0;
+ _seqStack = 0;
+ _seqTo = 0;
+ _seqCounter = _seqCounter2 = 0;
}
/*----------------------------------------------------------------*/
@@ -1022,6 +1023,31 @@ void Talk::pushSequence(int speaker) {
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;
+ }
+ }
+
+ error("Ran out of talk sequence stack space");
+}
+
void Talk::setSequence(int speaker) {
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index ebfe8f1732..79616b246b 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -29,11 +29,13 @@
#include "common/serializer.h"
#include "common/stream.h"
#include "common/stack.h"
+#include "sherlock/objects.h"
namespace Sherlock {
#define MAX_TALK_SEQUENCES 11
#define MAX_TALK_FILES 500
+#define TALK_SEQUENCE_STACK_SIZE 20
enum {
OP_SWITCH_SPEAKER = 0,
@@ -153,16 +155,19 @@ struct TalkHistoryEntry {
bool &operator[](int index) { return _data[index]; }
};
-struct TalkSequences {
- byte _data[MAX_TALK_SEQUENCES];
+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;
- TalkSequences() { clear(); }
- TalkSequences(const byte *data);
-
- byte &operator[](int idx) { return _data[idx]; }
- void clear();
+ TalkSequence();
};
+
class Talk {
friend class Scalpel::ScalpelUserInterface;
private:
@@ -248,6 +253,7 @@ protected:
OpcodeReturn cmdWalkToCAnimation(const byte *&str);
OpcodeReturn cmdWalkToCoords(const byte *&str);
public:
+ TalkSequence _talkSequenceStack[TALK_SEQUENCE_STACK_SIZE];
bool _talkToAbort;
int _talkCounter;
int _talkTo;
@@ -324,6 +330,11 @@ public:
void pushSequence(int speaker);
/**
+ * Push a given shape's sequence data onto the Rose Tattoo talk sequence stack
+ */
+ void pushTalkSequence(Object *obj);
+
+ /**
* Change the sequence of the scene background object associated with the current speaker.
*/
void setSequence(int speaker);