diff options
Diffstat (limited to 'engines/sherlock/talk.h')
-rw-r--r-- | engines/sherlock/talk.h | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h new file mode 100644 index 0000000000..f354c28c1b --- /dev/null +++ b/engines/sherlock/talk.h @@ -0,0 +1,369 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_TALK_H +#define SHERLOCK_TALK_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "common/stream.h" +#include "common/stack.h" +#include "sherlock/objects.h" +#include "sherlock/saveload.h" + +namespace Sherlock { + +#define SPEAKER_REMOVE 0x80 +#define MAX_TALK_SEQUENCES 11 + +enum { + OP_SWITCH_SPEAKER = 0, + OP_RUN_CANIMATION = 1, + OP_ASSIGN_PORTRAIT_LOCATION = 2, + OP_PAUSE = 3, + OP_REMOVE_PORTRAIT = 4, + OP_CLEAR_WINDOW = 5, + OP_ADJUST_OBJ_SEQUENCE = 6, + OP_WALK_TO_COORDS = 7, + OP_PAUSE_WITHOUT_CONTROL = 8, + OP_BANISH_WINDOW = 9, + OP_SUMMON_WINDOW = 10, + OP_SET_FLAG = 11, + OP_SFX_COMMAND = 12, + OP_TOGGLE_OBJECT = 13, + OP_STEALTH_MODE_ACTIVE = 14, + OP_IF_STATEMENT = 15, + OP_ELSE_STATEMENT = 16, + OP_END_IF_STATEMENT = 17, + OP_STEALTH_MODE_DEACTIVATE = 18, + OP_TURN_HOLMES_OFF = 19, + OP_TURN_HOLMES_ON = 20, + OP_GOTO_SCENE = 21, + OP_PLAY_PROLOGUE = 22, + OP_ADD_ITEM_TO_INVENTORY = 23, + OP_SET_OBJECT = 24, + OP_CALL_TALK_FILE = 25, + OP_MOVE_MOUSE = 26, + OP_DISPLAY_INFO_LINE = 27, + OP_CLEAR_INFO_LINE = 28, + OP_WALK_TO_CANIMATION = 29, + OP_REMOVE_ITEM_FROM_INVENTORY = 30, + OP_ENABLE_END_KEY = 31, + OP_DISABLE_END_KEY = 32, + OP_END_TEXT_WINDOW = 33, + + OP_MOUSE_OFF_ON = 34, + OP_SET_WALK_CONTROL = 35, + OP_SET_TALK_SEQUENCE = 36, + OP_PLAY_SONG = 37, + OP_WALK_HOLMES_AND_NPC_TO_CANIM = 38, + OP_SET_NPC_PATH_DEST = 39, + OP_NEXT_SONG = 40, + OP_SET_NPC_PATH_PAUSE = 41, + OP_NEED_PASSWORD = 42, + OP_SET_SCENE_ENTRY_FLAG = 43, + OP_WALK_NPC_TO_CANIM = 44, + OP_WALK_NPC_TO_COORDS = 45, + OP_WALK_HOLMES_AND_NPC_TO_COORDS = 46, + OP_SET_NPC_TALK_FILE = 47, + OP_TURN_NPC_OFF = 48, + OP_TURN_NPC_ON = 49, + OP_NPC_DESC_ON_OFF = 50, + OP_NPC_PATH_PAUSE_TAKING_NOTES = 51, + OP_NPC_PATH_PAUSE_LOOKING_HOLMES = 52, + OP_ENABLE_TALK_INTERRUPTS = 53, + OP_DISABLE_TALK_INTERRUPTS = 54, + OP_SET_NPC_INFO_LINE = 55, + OP_SET_NPC_POSITION = 56, + OP_NPC_PATH_LABEL = 57, + OP_PATH_GOTO_LABEL = 58, + OP_PATH_IF_FLAG_GOTO_LABEL = 59, + OP_NPC_WALK_GRAPHICS = 60, + OP_NPC_VERB = 61, + OP_NPC_VERB_CANIM = 62, + OP_NPC_VERB_SCRIPT = 63, + OP_RESTORE_PEOPLE_SEQUENCE = 64, + OP_NPC_VERB_TARGET = 65, + OP_TURN_SOUNDS_OFF = 66, + OP_NULL = 67 +}; + +enum OpcodeReturn { RET_EXIT = -1, RET_SUCCESS = 0, RET_CONTINUE = 1 }; + +class SherlockEngine; +class Talk; +namespace Scalpel { class ScalpelUserInterface; } + +typedef OpcodeReturn(Talk::*OpcodeMethod)(const byte *&str); + +struct SequenceEntry { + int _objNum; + Common::Array<byte> _sequences; + 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(); +}; + +struct ScriptStackEntry { + Common::String _name; + int _currentIndex; + int _select; +}; + +struct Statement { + Common::String _statement; + Common::String _reply; + Common::String _linkFile; + Common::String _voiceFile; + Common::Array<int> _required; + Common::Array<int> _modified; + int _portraitSide; + int _quotient; + int _talkMap; + Common::Rect _talkPos; + int _journal; + + /** + * Load the data for a single statement within a talk file + */ + void load(Common::SeekableReadStream &s, bool isRoseTattoo); +}; + +struct TalkHistoryEntry { + bool _data[16]; + + TalkHistoryEntry(); + bool &operator[](int index) { return _data[index]; } +}; + +class Talk { + friend class Scalpel::ScalpelUserInterface; +private: + /** + * Remove any voice commands from a loaded statement list + */ + void stripVoiceCommands(); +protected: + SherlockEngine *_vm; + OpcodeMethod *_opcodeTable; + Common::Stack<SequenceEntry> _savedSequences; + Common::Stack<ScriptStackEntry> _scriptStack; + Common::Array<TalkHistoryEntry> _talkHistory; + int _talkIndex; + int _scriptSelect; + int _talkStealth; + int _talkToFlag; + int _scriptSaveIndex; + int _3doSpeechIndex; + + // These fields are used solely by doScript, but are fields because all the script opcodes are + // separate methods now, and need access to these fields + int _yp; + int _charCount; + int _line; + int _wait; + bool _pauseFlag; + bool _endStr, _noTextYet; + int _seqCount; + const byte *_scriptStart, *_scriptEnd; +protected: + Talk(SherlockEngine *vm); + + OpcodeReturn cmdAddItemToInventory(const byte *&str); + OpcodeReturn cmdAdjustObjectSequence(const byte *&str); + OpcodeReturn cmdBanishWindow(const byte *&str); + OpcodeReturn cmdDisableEndKey(const byte *&str); + OpcodeReturn cmdEnableEndKey(const byte *&str); + OpcodeReturn cmdEndTextWindow(const byte *&str); + OpcodeReturn cmdHolmesOff(const byte *&str); + OpcodeReturn cmdHolmesOn(const byte *&str); + OpcodeReturn cmdPause(const byte *&str); + OpcodeReturn cmdPauseWithoutControl(const byte *&str); + OpcodeReturn cmdRemoveItemFromInventory(const byte *&str); + OpcodeReturn cmdRunCAnimation(const byte *&str); + OpcodeReturn cmdSetFlag(const byte *&str); + OpcodeReturn cmdSetObject(const byte *&str); + OpcodeReturn cmdStealthModeActivate(const byte *&str); + OpcodeReturn cmdStealthModeDeactivate(const byte *&str); + OpcodeReturn cmdToggleObject(const byte *&str); + OpcodeReturn cmdWalkToCAnimation(const byte *&str); +protected: + /** + * Checks, if a character is an opcode + */ + bool isOpcode(byte checkCharacter); + + /** + * Form a table of the display indexes for statements + */ + void setTalkMap(); + + /** + * When the talk window has been displayed, waits a period of time proportional to + * the amount of text that's been displayed + */ + virtual int waitForMore(int delay); + + /** + * Display the talk interface window + */ + virtual void talkInterface(const byte *&str) = 0; + + /** + * Pause when displaying a talk dialog on-screen + */ + virtual void talkWait(const byte *&str); + + /** + * Show the talk display + */ + virtual void showTalk() = 0; + + /** + * Called when a character being spoken to has no talk options to display + */ + virtual void nothingToSay() = 0; + + /** + * Called when the active speaker is switched + */ + virtual void switchSpeaker() {} +public: + Common::Array<Statement> _statements; + bool _talkToAbort; + int _talkCounter; + int _talkTo; + int _scriptMoreFlag; + bool _openTalkWindow; + Common::String _scriptName; + bool _moreTalkUp, _moreTalkDown; + int _converseNum; + const byte *_opcodes; + int _speaker; +public: + static Talk *init(SherlockEngine *vm); + virtual ~Talk() {} + + /** + * Return a given talk statement + */ + Statement &operator[](int idx) { return _statements[idx]; } + + /** + * Called whenever a conversation or item script needs to be run. For standard conversations, + * it opens up a description window similar to how 'talk' does, but shows a 'reply' directly + * instead of waiting for a statement option. + * @remarks It seems that at some point, all item scripts were set up to use this as well. + * In their case, the conversation display is simply suppressed, and control is passed on to + * doScript to implement whatever action is required. + */ + virtual void talkTo(const Common::String filename); + + /** + * Parses a reply for control codes and display text. The found text is printed within + * the text window, handles delays, animations, and animating portraits. + */ + void doScript(const Common::String &script); + + /** + * Main method for handling conversations when a character to talk to has been + * selected. It will make Holmes walk to the person to talk to, draws the + * interface window for the conversation and passes on control to give the + * player a list of options to make a selection from + */ + void initTalk(int objNum); + + /** + * Clear loaded talk data + */ + void freeTalkVars(); + + /** + * Opens the talk file 'talk.tlk' and searches the index for the specified + * conversation. If found, the data for that conversation is loaded + */ + virtual void loadTalkFile(const Common::String &filename); + + /** + * Push the sequence of a background object that's an NPC that needs to be + * saved onto the sequence stack. + */ + void pushSequence(int speaker); + + /** + * 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 + */ + virtual void clearSequences() = 0; + + /** + * Pops an entry off of the script stack + */ + void popStack(); + + /** + * Synchronize the data for a savegame + */ + void synchronize(Serializer &s); + + /** + * Draws the interface for conversation display + */ + virtual void drawInterface() {} + + /** + * Display a list of statements in a window at the bottom of the screen that the + * player can select from. + */ + virtual bool displayTalk(bool slamIt) { return false; } + + /** + * Prints a single conversation option in the interface window + */ + virtual int talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt) { return 0; } + + /** + * Pulls a background object sequence from the sequence stack and restore's the + * object's sequence + */ + virtual void pullSequence(int slot = -1) = 0; + + /** + * Returns true if the script stack is empty + */ + virtual bool isSequencesEmpty() const = 0; +}; + +} // End of namespace Sherlock + +#endif |