Initial commit
This commit is contained in:
504
engines/mads/conversations.h
Normal file
504
engines/mads/conversations.h
Normal file
@@ -0,0 +1,504 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MADS_CONVERSATIONS_H
|
||||
#define MADS_CONVERSATIONS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/str-array.h"
|
||||
#include "mads/screen.h"
|
||||
#include "mads/dialogs.h"
|
||||
|
||||
namespace MADS {
|
||||
|
||||
#define MAX_CONVERSATIONS 5
|
||||
#define MAX_SPEAKERS 5
|
||||
|
||||
enum ConversationMode {
|
||||
CONVMODE_NONE = -1,
|
||||
CONVMODE_NEXT = 0,
|
||||
CONVMODE_WAIT_AUTO = 1,
|
||||
CONVMODE_WAIT_ENTRY = 2,
|
||||
CONVMODE_EXECUTE = 3,
|
||||
CONVMODE_REPLY = 4,
|
||||
CONVMODE_5 = 5,
|
||||
CONVMODE_6 = 6,
|
||||
CONVMODE_7 = 7,
|
||||
CONVMODE_8 = 8,
|
||||
CONVMODE_9 = 9,
|
||||
CONVMODE_STOP = 10
|
||||
};
|
||||
|
||||
enum DialogCommand {
|
||||
CMD_END = 0,
|
||||
CMD_1 = 1,
|
||||
CMD_HIDE = 2,
|
||||
CMD_UNHIDE = 3,
|
||||
CMD_MESSAGE1 = 4,
|
||||
CMD_MESSAGE2 = 5,
|
||||
CMD_ERROR = 6,
|
||||
CMD_NODE = 7,
|
||||
CMD_GOTO = 8,
|
||||
CMD_ASSIGN = 9,
|
||||
CMD_DIALOG_END = 255
|
||||
};
|
||||
|
||||
enum ConvEntryFlag {
|
||||
ENTRYFLAG_2 = 2,
|
||||
ENTRYFLAG_4000 = 0x4000,
|
||||
ENTRYFLAG_8000 = 0x8000
|
||||
};
|
||||
|
||||
enum ConditionalOperation {
|
||||
CONDOP_NONE = 0xff,
|
||||
CONDOP_VALUE = 0,
|
||||
CONDOP_ADD = 1,
|
||||
CONDOP_SUBTRACT = 2,
|
||||
CONDOP_MULTIPLY = 3,
|
||||
CONDOP_DIVIDE = 4,
|
||||
CONDOP_MODULUS = 5,
|
||||
CONDOP_LTEQ = 6,
|
||||
CONDOP_GTEQ = 7,
|
||||
CONDOP_LT = 8,
|
||||
CONDOP_GT = 9,
|
||||
CONDOP_NEQ = 10,
|
||||
CONDOP_EQ = 11,
|
||||
CONDOP_AND = 12,
|
||||
CONDOP_OR = 13,
|
||||
CONDOP_ABORT = 0xff
|
||||
};
|
||||
|
||||
|
||||
struct ConversationVar {
|
||||
bool _isPtr;
|
||||
int _val;
|
||||
int *_valPtr;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ConversationVar() : _isPtr(false), _val(0), _valPtr(nullptr) {}
|
||||
|
||||
/**
|
||||
* Sets a numeric value
|
||||
*/
|
||||
void setValue(int val);
|
||||
|
||||
/**
|
||||
* Sets a pointer value
|
||||
*/
|
||||
void setValue(int *val);
|
||||
|
||||
/**
|
||||
* Return either the variable's pointer, or a pointer to it's direct value
|
||||
*/
|
||||
int *getValue() { return _isPtr ? _valPtr : &_val; }
|
||||
|
||||
/**
|
||||
* Returns true if variable is a pointer
|
||||
*/
|
||||
bool isPtr() const { return _isPtr; }
|
||||
|
||||
/**
|
||||
* Returns true if variable is numeric
|
||||
*/
|
||||
bool isNumeric() const { return !_isPtr; }
|
||||
};
|
||||
|
||||
struct ScriptEntry {
|
||||
struct Conditional {
|
||||
struct CondtionalParamEntry {
|
||||
bool _isVariable;
|
||||
int _val;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
CondtionalParamEntry() : _isVariable(false), _val(0) {}
|
||||
};
|
||||
|
||||
static Common::Array<ConversationVar> *_vars;
|
||||
ConditionalOperation _operation;
|
||||
CondtionalParamEntry _param1;
|
||||
CondtionalParamEntry _param2;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Conditional() : _operation(CONDOP_NONE) {}
|
||||
|
||||
/**
|
||||
* Loads data from a passed stream into the parameters structure
|
||||
*/
|
||||
void load(Common::SeekableReadStream &s);
|
||||
|
||||
/**
|
||||
* Gets the value
|
||||
*/
|
||||
int get(int paramNum) const;
|
||||
|
||||
/**
|
||||
* Evaluates the conditional
|
||||
*/
|
||||
int evaluate() const;
|
||||
};
|
||||
|
||||
struct MessageEntry {
|
||||
int _size;
|
||||
int _v2;
|
||||
|
||||
MessageEntry() : _size(0), _v2(0) {}
|
||||
};
|
||||
|
||||
DialogCommand _command;
|
||||
Conditional _conditionals[3];
|
||||
|
||||
// Extra parameters for different opcodes
|
||||
int _index;
|
||||
Common::Array<int> _entries;
|
||||
Common::Array<MessageEntry> _entries2;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ScriptEntry() : _command(CMD_END), _index(0) {}
|
||||
|
||||
/**
|
||||
* Loads data from a passed stream into the parameters structure
|
||||
*/
|
||||
void load(Common::SeekableReadStream &s);
|
||||
};
|
||||
|
||||
/**
|
||||
* Representation of scripts associated with a dialog
|
||||
*/
|
||||
class DialogScript : public Common::Array<ScriptEntry> {
|
||||
public:
|
||||
/**
|
||||
* Loads a script from the passed stream
|
||||
*/
|
||||
void load(Common::SeekableReadStream &s, uint startingOffset);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reperesents the data for a dialog to be displayed in a conversation
|
||||
*/
|
||||
struct ConvDialog {
|
||||
struct ScriptEntry {
|
||||
DialogCommand _command;
|
||||
};
|
||||
|
||||
int16 _textLineIndex; // 0-based
|
||||
int16 _speechIndex; // 1-based
|
||||
uint16 _scriptOffset; // offset of script entry
|
||||
uint16 _scriptSize; // size of script entry
|
||||
|
||||
DialogScript _script;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a node within the conversation control logic
|
||||
*/
|
||||
struct ConvNode {
|
||||
uint16 _index;
|
||||
uint16 _dialogCount;
|
||||
int16 _unk1;
|
||||
bool _active;
|
||||
int16 _unk3;
|
||||
|
||||
Common::Array<ConvDialog> _dialogs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a message entry
|
||||
*/
|
||||
struct ConvMessage {
|
||||
uint _stringIndex;
|
||||
uint _count;
|
||||
|
||||
ConvMessage() : _stringIndex(0), _count(0) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the static, non-changing data for a conversation
|
||||
*/
|
||||
struct ConversationData {
|
||||
uint16 _nodeCount; // conversation nodes, each one containing several dialog options and messages
|
||||
uint16 _dialogCount; // messages (non-selectable) + texts (selectable)
|
||||
uint16 _messageCount; // messages (non-selectable)
|
||||
uint16 _textLineCount;
|
||||
uint16 _unk2;
|
||||
uint16 _maxImports;
|
||||
uint16 _speakerCount;
|
||||
int _textSize;
|
||||
int _commandsSize;
|
||||
|
||||
Common::Path _portraits[MAX_SPEAKERS];
|
||||
int _speakerFrame[MAX_SPEAKERS];
|
||||
Common::Path _speechFile;
|
||||
Common::Array<ConvMessage> _messages;
|
||||
Common::StringArray _textLines;
|
||||
Common::Array<ConvNode> _nodes;
|
||||
Common::Array<ConvDialog> _dialogs;
|
||||
|
||||
/**
|
||||
* Load the specified conversation resource file
|
||||
*/
|
||||
void load(const Common::Path &filename);
|
||||
};
|
||||
|
||||
/**
|
||||
* Conditional (i.e. changeable) data for the conversation
|
||||
*/
|
||||
struct ConversationConditionals {
|
||||
Common::Array<uint> _importVariables;
|
||||
Common::Array<uint> _entryFlags;
|
||||
Common::Array<ConversationVar> _vars;
|
||||
int _numImports;
|
||||
|
||||
int _currentNode;
|
||||
Common::Array<int> _playerMessageList;
|
||||
Common::Array<int> _actorMessageList;
|
||||
Common::Array<int> _playerSpeechList;
|
||||
Common::Array<int> _actorSpeechList;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ConversationConditionals();
|
||||
|
||||
/**
|
||||
* Load the specified conversation conditionals resource file
|
||||
*/
|
||||
void load(const Common::Path &filename);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents all the data needed for a particular loaded conversation
|
||||
*/
|
||||
struct ConversationEntry {
|
||||
int _convId;
|
||||
ConversationData _data;
|
||||
ConversationConditionals _cnd;
|
||||
};
|
||||
|
||||
class MADSEngine;
|
||||
|
||||
/**
|
||||
* Manager for loading and running conversations
|
||||
*/
|
||||
class GameConversations {
|
||||
private:
|
||||
MADSEngine *_vm;
|
||||
ConversationEntry _conversations[MAX_CONVERSATIONS];
|
||||
bool _speakerActive[MAX_SPEAKERS];
|
||||
int _speakerSeries[MAX_SPEAKERS];
|
||||
int _speakerFrame[MAX_SPEAKERS];
|
||||
int _popupX[MAX_SPEAKERS];
|
||||
int _popupY[MAX_SPEAKERS];
|
||||
int _popupMaxLen[MAX_SPEAKERS];
|
||||
InputMode _inputMode;
|
||||
bool _popupVisible;
|
||||
ConversationMode _currentMode;
|
||||
ConversationMode _priorMode;
|
||||
int _verbId;
|
||||
int _speakerVal;
|
||||
int _heroTrigger;
|
||||
TriggerMode _heroTriggerMode;
|
||||
int _interlocutorTrigger;
|
||||
TriggerMode _interlocutorTriggerMode;
|
||||
ConversationEntry *_runningConv;
|
||||
int _restoreRunning;
|
||||
bool _playerEnabled;
|
||||
uint32 _startFrameNumber;
|
||||
ConversationVar *_vars;
|
||||
ConversationVar *_nextStartNode;
|
||||
int _currentNode;
|
||||
int _dialogNodeOffset, _dialogNodeSize;
|
||||
int _personSpeaking;
|
||||
TextDialog *_dialog;
|
||||
bool _dialogAltFlag;
|
||||
|
||||
/**
|
||||
* Returns the record for the specified conversation, if it's loaded
|
||||
*/
|
||||
ConversationEntry *getConv(int convId);
|
||||
|
||||
/**
|
||||
* Start a specified conversation slot
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Remove any currently active dialog window
|
||||
*/
|
||||
void removeActiveWindow();
|
||||
|
||||
/**
|
||||
* Flags a conversation option/entry
|
||||
*/
|
||||
void flagEntry(DialogCommand mode, int entryIndex);
|
||||
|
||||
/**
|
||||
* Generate a menu
|
||||
*/
|
||||
ConversationMode generateMenu();
|
||||
|
||||
/**
|
||||
* Generate text
|
||||
*/
|
||||
void generateText(int textLineIndex, Common::Array<int> &messages);
|
||||
|
||||
/**
|
||||
* Generate message
|
||||
*/
|
||||
void generateMessage(Common::Array<int> &messageList, Common::Array<int> &voiecList);
|
||||
|
||||
/**
|
||||
* Gets the next node
|
||||
*/
|
||||
bool nextNode();
|
||||
|
||||
/**
|
||||
* Executes a conversation entry
|
||||
*/
|
||||
int executeEntry(int index);
|
||||
|
||||
/**
|
||||
* Handle messages
|
||||
*/
|
||||
void scriptMessage(ScriptEntry &scrEntry);
|
||||
|
||||
/**
|
||||
* Handle node changes
|
||||
*/
|
||||
bool scriptNode(ScriptEntry &scrEntry);
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
GameConversations(MADSEngine *vm);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~GameConversations();
|
||||
|
||||
/**
|
||||
* Gets the specified conversation and loads into into a free slot
|
||||
* in the conversation list
|
||||
*/
|
||||
void load(int id);
|
||||
|
||||
/**
|
||||
* Run a specified conversation number. The conversation must have
|
||||
* previously been loaded by calling the load method
|
||||
*/
|
||||
void run(int id);
|
||||
|
||||
/**
|
||||
* Sets a variable to a numeric value
|
||||
*/
|
||||
void setVariable(uint idx, int val);
|
||||
|
||||
/**
|
||||
* Sets a variable to a pointer value
|
||||
*/
|
||||
void setVariable(uint idx, int *val);
|
||||
|
||||
/**
|
||||
* Sets the starting node index
|
||||
*/
|
||||
void setStartNode(uint nodeIndex);
|
||||
|
||||
/**
|
||||
* Set the hero trigger
|
||||
*/
|
||||
void setHeroTrigger(int val);
|
||||
|
||||
/**
|
||||
* Set the interlocutor trigger
|
||||
*/
|
||||
void setInterlocutorTrigger(int val);
|
||||
|
||||
/**
|
||||
* Returns either the pointer value of a variable, or if the variable
|
||||
* contains a numeric value directly, returns a pointer to it
|
||||
*/
|
||||
int *getVariable(int idx);
|
||||
|
||||
/**
|
||||
* Hold the current mode value
|
||||
*/
|
||||
void hold();
|
||||
|
||||
/**
|
||||
* Release the prevoiusly held mode value
|
||||
*/
|
||||
void release();
|
||||
|
||||
/**
|
||||
* Stop any currently running conversation
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Adds the passed pointer into the list of import variables for the given conversation
|
||||
*/
|
||||
void exportPointer(int *ptr);
|
||||
|
||||
/**
|
||||
* Adds the passed value into the list of import variables for the given conversation
|
||||
*/
|
||||
void exportValue(int val);
|
||||
|
||||
void reset(int id);
|
||||
|
||||
/**
|
||||
* Handles updating the conversation display
|
||||
*/
|
||||
void update(bool flag);
|
||||
|
||||
/**
|
||||
* Returns true if any conversation is currently atcive
|
||||
*/
|
||||
bool active() const { return _runningConv != nullptr; }
|
||||
|
||||
/**
|
||||
* Returns the currently active conversation Id
|
||||
*/
|
||||
int activeConvId() const { return !active() ? -1 : _runningConv->_convId; }
|
||||
|
||||
/**
|
||||
* Returns _restoreRunning value
|
||||
*/
|
||||
int restoreRunning() const { return _restoreRunning; }
|
||||
|
||||
/**
|
||||
* Returns the current conversation mode
|
||||
*/
|
||||
ConversationMode currentMode() const { return _currentMode; }
|
||||
};
|
||||
|
||||
} // End of namespace MADS
|
||||
|
||||
#endif /* MADS_CONVERSATIONS_H */
|
||||
Reference in New Issue
Block a user