diff options
-rw-r--r-- | engines/mads/conversations.cpp | 192 | ||||
-rw-r--r-- | engines/mads/conversations.h | 57 | ||||
-rw-r--r-- | engines/mads/events.cpp | 5 | ||||
-rw-r--r-- | engines/mads/events.h | 8 |
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(); } }; |