SHERLOCK: Implemented setObjTalkSequence methods

This commit is contained in:
Paul Gilbert 2015-06-03 21:03:44 -04:00
parent bc7127c522
commit 60378fe228
4 changed files with 164 additions and 15 deletions

View File

@ -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[]) {

View File

@ -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;
@ -242,6 +248,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
*/

View File

@ -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;

View File

@ -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;
@ -323,6 +329,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.
*/