aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/mads/conversations.cpp192
-rw-r--r--engines/mads/conversations.h57
-rw-r--r--engines/mads/events.cpp5
-rw-r--r--engines/mads/events.h8
4 files changed, 239 insertions, 23 deletions
diff --git a/engines/mads/conversations.cpp b/engines/mads/conversations.cpp
index 95c088a98f..61391c1b12 100644
--- a/engines/mads/conversations.cpp
+++ b/engines/mads/conversations.cpp
@@ -37,12 +37,14 @@ GameConversations::GameConversations(MADSEngine *vm) : _vm(vm) {
_speakerVal = 0;
_currentMode = CONVMODE_NONE;
_priorMode = CONVMODE_NONE;
- _val1 =_val5 = 0;
+ _val1 = 0;
+ _verbId = 0;
_vars = _nextStartNode = nullptr;
_heroTrigger = 0;
_heroTriggerMode = SEQUENCE_TRIGGER_PARSER;
_interlocutorTrigger = 0;
_interlocutorTriggerMode = SEQUENCE_TRIGGER_PARSER;
+ _currentNode = 0;
// Mark all conversation slots as empty
for (int idx = 0; idx < MAX_CONVERSATIONS; ++idx)
@@ -101,7 +103,7 @@ void GameConversations::run(int id) {
_interlocutorTrigger = 0;
_val1 = 0;
_currentMode = CONVMODE_0;
- _val5 = -1;
+ _verbId = -1;
_speakerVal = 1;
// Initialize speaker arrays
@@ -278,6 +280,125 @@ void GameConversations::reset(int id) {
}
void GameConversations::update(bool flag) {
+ // Only need to proceed if there is an active conversation
+ if (!active())
+ return;
+
+ ConversationVar &var0 = _runningConv->_cnd._vars[0];
+
+ switch (_currentMode) {
+ case CONVMODE_0:
+ assert(var0.isNumeric());
+ if (var0._val < 0) {
+ if (_vm->_game->_scene._frameStartTime >= _startFrameNumber) {
+ removeActiveWindow();
+ if (_heroTrigger) {
+ _vm->_game->_scene._action._activeAction._verbId = _verbId;
+ _vm->_game->_trigger = _heroTrigger;
+ _vm->_game->_triggerMode = _heroTriggerMode;
+ _heroTrigger = 0;
+ }
+
+ _currentMode = CONVMODE_STOP;
+ }
+ } else {
+ bool isActive = nextNode();
+ _currentNode = var0._val;
+
+ if (isActive) {
+ _verbId = _runningConv->_data._nodes[_currentNode]._index;
+ _vm->_game->_scene._action._activeAction._verbId = _verbId;
+ _vm->_game->_scene._action._inProgress = true;
+ _vm->_game->_scene._action._savedFields._commandError = false;
+ _currentMode = CONVMODE_1;
+ } else {
+ _currentMode = generateMenu();
+ }
+ }
+ break;
+
+ case CONVMODE_1:
+ if (flag)
+ _currentMode = CONVMODE_3;
+ break;
+
+ case CONVMODE_2:
+ if (flag) {
+ _vm->_game->_player._stepEnabled = false;
+ _verbId = _vm->_game->_scene._action._activeAction._verbId;
+
+ if (!(_runningConv->_cnd._entryFlags[_verbId] & ENTRYFLAG_2))
+ flagEntry(FLAGMODE_2, _verbId);
+
+ removeActiveWindow();
+ _vm->_game->_scene._userInterface.emptyConversationList();
+ _vm->_game->_scene._userInterface.setup(kInputConversation);
+ _vm->_events->clearEvents();
+ executeEntry(_verbId);
+
+ ConvDialog &dialog = _runningConv->_data._dialogs[_verbId];
+ if (dialog._speechIndex) {
+ _runningConv->_cnd._field50 = dialog._speechIndex;
+ _runningConv->_cnd._field10 = 1;
+ }
+
+ generateText(dialog._textLineIndex, _runningConv->_cnd._field10,
+ &_runningConv->_cnd._field50);
+ _currentMode = CONVMODE_0;
+
+ if (_heroTrigger) {
+ _vm->_game->_scene._action._activeAction._verbId = _verbId;
+ _vm->_game->_trigger = _heroTrigger;
+ _vm->_game->_triggerMode = _heroTriggerMode;
+ _heroTrigger = 0;
+ }
+ }
+ break;
+
+ case CONVMODE_3:
+ if (_vm->_game->_scene._frameStartTime >= _startFrameNumber) {
+ removeActiveWindow();
+ _vm->_events->clearEvents();
+ executeEntry(_verbId);
+ generateMessage(_runningConv->_cnd._fieldC, _runningConv->_cnd._field10,
+ &_runningConv->_cnd._field50, &_runningConv->_cnd._field28);
+
+ if (_heroTrigger && _val1) {
+ _vm->_game->_scene._action._activeAction._verbId = _verbId;
+ _vm->_game->_trigger = _heroTrigger;
+ _vm->_game->_triggerMode = _heroTriggerMode;
+ _heroTrigger = 0;
+ }
+
+ _currentMode = CONVMODE_4;
+ }
+ break;
+
+ case CONVMODE_4:
+ if (_vm->_game->_scene._frameStartTime >= _startFrameNumber) {
+ removeActiveWindow();
+ _vm->_events->clearEvents();
+
+ generateMessage(_runningConv->_cnd._fieldE, _runningConv->_cnd._field12,
+ &_runningConv->_cnd._field64, &_runningConv->_cnd._field3C);
+
+ if (_interlocutorTrigger && _val1) {
+ _vm->_game->_scene._action._activeAction._verbId = _verbId;
+ _vm->_game->_trigger = _interlocutorTrigger;
+ _vm->_game->_triggerMode = _interlocutorTriggerMode;
+ _interlocutorTrigger = 0;
+ }
+ }
+ break;
+
+ case CONVMODE_STOP:
+ stop();
+ break;
+
+ default:
+ break;
+ }
+
warning("TODO: GameConversations::update");
}
@@ -285,6 +406,28 @@ void GameConversations::removeActiveWindow() {
warning("TODO: GameConversations::removeActiveWindow");
}
+ConversationMode GameConversations::generateMenu() {
+ error("TODO: GameConversations::generateMenu");
+}
+
+void GameConversations::generateText(int textLineIndex, int v2, int *v3) {
+ error("TODO: GameConversations::generateText");
+}
+
+void GameConversations::generateMessage(int textLineIndex, int v2, int *v3, int *v4) {
+ error("TODO: GameConversations::generateMessage");
+}
+
+bool GameConversations::nextNode() {
+ ConversationVar &var0 = _runningConv->_cnd._vars[0];
+ _runningConv->_cnd._currentNode = var0._val;
+ return _runningConv->_data._nodes[var0._val]._active;
+}
+
+void GameConversations::executeEntry(int index) {
+
+}
+
/*------------------------------------------------------------------------*/
void ConversationData::load(const Common::String &filename) {
@@ -329,35 +472,31 @@ void ConversationData::load(const Common::String &filename) {
// **** Section 1: Nodes **************************************************
convFile = convFileUnpacked.getItemStream(1);
- _convNodes.clear();
+ _nodes.clear();
for (uint i = 0; i < _nodeCount; i++) {
ConvNode node;
node._index = convFile->readUint16LE();
node._dialogCount = convFile->readUint16LE();
node._unk1 = convFile->readSint16LE(); // TODO
- node._unk2 = convFile->readSint16LE(); // TODO
+ node._active = convFile->readSint16LE() != 0;
node._unk3 = convFile->readSint16LE(); // TODO
- _convNodes.push_back(node);
- //debug("Node %d, index %d, entries %d - %d, %d, %d", i, node.index, node.dialogCount, node.unk1, node.unk2, node.unk3);
+ _nodes.push_back(node);
}
+
delete convFile;
// **** Section 2: Dialogs ************************************************
convFile = convFileUnpacked.getItemStream(2);
assert(convFile->size() == _dialogCount * 8);
- for (uint idx = 0; idx < _nodeCount; ++idx) {
- uint dialogCount = _convNodes[idx]._dialogCount;
-
- for (uint j = 0; j < dialogCount; ++j) {
- ConvDialog dialog;
- dialog._textLineIndex = convFile->readSint16LE();
- dialog._speechIndex = convFile->readSint16LE();
- dialog._nodeOffset = convFile->readUint16LE();
- dialog._nodeSize = convFile->readUint16LE();
- _convNodes[idx]._dialogs.push_back(dialog);
- }
+ _dialogs.resize(_dialogCount);
+ for (uint idx = 0; idx < _dialogCount; ++idx) {
+ _dialogs[idx]._textLineIndex = convFile->readSint16LE();
+ _dialogs[idx]._speechIndex = convFile->readSint16LE();
+ _dialogs[idx]._nodeOffset = convFile->readUint16LE();
+ _dialogs[idx]._nodeSize = convFile->readUint16LE();
}
+
delete convFile;
// **** Section 3: Messages ***********************************************
@@ -402,7 +541,7 @@ void ConversationData::load(const Common::String &filename) {
assert(convFile->size() == _commandsSize);
for (uint16 i = 0; i < _nodeCount; i++) {
- uint16 dialogCount = _convNodes[i]._dialogCount;
+ uint16 dialogCount = _nodes[i]._dialogCount;
for (uint16 j = 0; j < dialogCount; j++) {
//ConvDialog dialog = _convNodes[i].dialogs[j];
@@ -480,17 +619,32 @@ void ConversationConditionals::load(const Common::String &filename) {
Common::File inFile;
Common::SeekableReadStream *convFile;
+ // Open up the file for access
inFile.open(filename);
MadsPack convFileUnpacked(&inFile);
// **** Section 0: Header *************************************************
convFile = convFileUnpacked.getItemStream(0);
- convFile->skip(2);
+ _currentNode = convFile->readUint16LE();
int entryFlagsCount = convFile->readUint16LE();
int varsCount = convFile->readUint16LE();
int importsCount = convFile->readUint16LE();
+ convFile->skip(2);
+ _fieldC = convFile->readUint16LE();
+ _fieldE = convFile->readUint16LE();
+ _field10 = convFile->readUint16LE();
+ _field12 = convFile->readUint16LE();
+ convFile->seek(0x28);
+ _field28 = convFile->readUint16LE();
+ convFile->seek(0x3C);
+ _field3C = convFile->readUint16LE();
+ convFile->seek(0x50);
+ _field50 = convFile->readUint16LE();
+ convFile->seek(0x64);
+ _field64 = convFile->readUint16LE();
+
delete convFile;
// **** Section: Imports *************************************************
diff --git a/engines/mads/conversations.h b/engines/mads/conversations.h
index e3e958ebc4..dbf000f5a5 100644
--- a/engines/mads/conversations.h
+++ b/engines/mads/conversations.h
@@ -45,7 +45,7 @@ enum ConversationMode {
CONVMODE_7 = 7,
CONVMODE_8 = 8,
CONVMODE_9 = 9,
- CONVMODE_10 = 10
+ CONVMODE_STOP = 10
};
enum DialogCommands {
@@ -69,6 +69,7 @@ enum ConvFlagMode {
};
enum ConvEntryFlag {
+ ENTRYFLAG_2 = 2,
ENTRYFLAG_4000 = 0x4000,
ENTRYFLAG_8000 = 0x8000
};
@@ -90,7 +91,7 @@ struct ConvNode {
uint16 _index;
uint16 _dialogCount;
int16 _unk1;
- int16 _unk2;
+ bool _active;
int16 _unk3;
Common::Array<ConvDialog> _dialogs;
@@ -115,7 +116,8 @@ struct ConversationData {
Common::String _speechFile;
Common::Array<uint> _messages;
Common::StringArray _textLines;
- Common::Array<ConvNode> _convNodes;
+ Common::Array<ConvNode> _nodes;
+ Common::Array<ConvDialog> _dialogs;
/**
* Load the specified conversation resource file
@@ -147,6 +149,16 @@ struct ConversationVar {
* 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; }
};
/**
@@ -158,6 +170,16 @@ struct ConversationConditionals {
Common::Array<ConversationVar> _vars;
int _numImports;
+ int _currentNode;
+ int _fieldC;
+ int _fieldE;
+ int _field10;
+ int _field12;
+ int _field28;
+ int _field3C;
+ int _field50;
+ int _field64;
+
/**
* Constructor
*/
@@ -194,9 +216,10 @@ private:
int _arr5[MAX_SPEAKERS];
int _arr6[MAX_SPEAKERS];
InputMode _inputMode;
- int _val1, _val5;
+ int _val1;
ConversationMode _currentMode;
ConversationMode _priorMode;
+ int _verbId;
int _speakerVal;
int _heroTrigger;
TriggerMode _heroTriggerMode;
@@ -208,6 +231,7 @@ private:
uint32 _startFrameNumber;
ConversationVar *_vars;
ConversationVar *_nextStartNode;
+ int _currentNode;
/**
* Returns the record for the specified conversation, if it's loaded
@@ -228,6 +252,31 @@ private:
* Flags a conversation option/entry
*/
void flagEntry(ConvFlagMode mode, int entryIndex);
+
+ /**
+ * Generate a menu
+ */
+ ConversationMode generateMenu();
+
+ /**
+ * Generate text
+ */
+ void generateText(int textLineIndex, int v2, int *v3);
+
+ /**
+ * Generate message
+ */
+ void generateMessage(int textLineIndex, int v2, int *v3, int *v4);
+
+ /**
+ * Gets the next node
+ */
+ bool nextNode();
+
+ /**
+ * Executes a conversation entry
+ */
+ void executeEntry(int index);
public:
/**
* Constructor
diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp
index 7ba9098935..7463704c4b 100644
--- a/engines/mads/events.cpp
+++ b/engines/mads/events.cpp
@@ -269,4 +269,9 @@ void EventsManager::initVars() {
_strokeGoing = 0;
}
+void EventsManager::clearEvents() {
+ _pendingKeys.clear();
+}
+
+
} // End of namespace MADS
diff --git a/engines/mads/events.h b/engines/mads/events.h
index 1a2579cae0..5750cb0f40 100644
--- a/engines/mads/events.h
+++ b/engines/mads/events.h
@@ -165,10 +165,18 @@ public:
void initVars();
/**
+ * Clears all currently pending keypresses
+ */
+ void clearEvents();
+
+ /**
* Returns true if there's any pending keys to be processed
*/
bool isKeyPressed() const { return !_pendingKeys.empty(); }
+ /**
+ * Gets the next pending keypress
+ */
Common::KeyState getKey() { return _pendingKeys.pop(); }
};