aboutsummaryrefslogtreecommitdiff
path: root/engines/mads/conversations.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mads/conversations.cpp')
-rw-r--r--engines/mads/conversations.cpp253
1 files changed, 202 insertions, 51 deletions
diff --git a/engines/mads/conversations.cpp b/engines/mads/conversations.cpp
index 0f51d96c0c..2af74541f7 100644
--- a/engines/mads/conversations.cpp
+++ b/engines/mads/conversations.cpp
@@ -31,11 +31,17 @@ namespace MADS {
GameConversations::GameConversations(MADSEngine *vm) : _vm(vm) {
_runningConv = nullptr;
_restoreRunning = 0;
- _nextStartNode = nullptr;
_playerEnabled = false;
_inputMode = kInputBuildingSentences;
_startFrameNumber = 0;
- _val1 = _val2 = _val3 = _val4 = _val5 = 0;
+ _speakerVal = 0;
+ _heldVal = _releaseVal = 0;
+ _val1 =_val5 = 0;
+ _vars = _nextStartNode = nullptr;
+ _heroTrigger = 0;
+ _heroTriggerMode = SEQUENCE_TRIGGER_PARSER;
+ _interlocutorTrigger = 0;
+ _interlocutorTriggerMode = SEQUENCE_TRIGGER_PARSER;
// Mark all conversation slots as empty
for (int idx = 0; idx < MAX_CONVERSATIONS; ++idx)
@@ -90,8 +96,10 @@ void GameConversations::run(int id) {
_startFrameNumber = _vm->_events->getFrameCounter();
_playerEnabled = _vm->_game->_player._stepEnabled;
_inputMode = _vm->_game->_screenObjects._inputMode;
- _val1 = _val2 = _val3 = 0;
- _val4 = 0;
+ _heroTrigger = 0;
+ _interlocutorTrigger = 0;
+ _val1 = 0;
+ _heldVal = 0;
_val5 = -1;
// Initialize speaker arrays
@@ -105,28 +113,14 @@ void GameConversations::run(int id) {
// Start the conversation
start();
- // Set variables
- setVariable(2, 0x4F78);
- setVariable(3, 0x4F50);
- setVariable(4, 0x4F52);
- setVariable(5, 0x4F54);
- setVariable(6, 0x4F56);
- setVariable(7, 0x4F58);
- setVariable(8, 0x4F5A);
- setVariable(9, 0x4F5C);
- setVariable(10, 0x4F5E);
- setVariable(11, 0x4F60);
- setVariable(12, 0x4F62);
- setVariable(13, 0x4F64);
- setVariable(14, 0x4F66);
- setVariable(15, 0x4F68);
- setVariable(16, 0x4F6A);
- setVariable(17, 0x4F6C);
- setVariable(18, 0x4F6E);
- setVariable(19, 0x4F70);
- setVariable(20, 0x4F72);
- setVariable(21, 0x4F74);
- setVariable(22, 0x4F76);
+ // Setup variables to point to data in the speaker arrays
+ setVariable(2, &_speakerVal);
+ for (int idx = 0; idx < MAX_SPEAKERS; ++idx) {
+ setVariable(3 + idx, &_speakerExists[idx]);
+ setVariable(8 + idx, &_arr4[idx]);
+ setVariable(13 + idx, &_arr5[idx]);
+ setVariable(18 + idx, &_arr6[idx]);
+ }
// Load sprite data for speaker portraits
for (uint idx = 0; idx < _runningConv->_data._speakerCount; ++idx) {
@@ -145,58 +139,148 @@ void GameConversations::run(int id) {
}
void GameConversations::start() {
+ assert(_runningConv->_cnd._vars.size() >= 2);
+ _vars = &_runningConv->_cnd._vars[0];
+ _nextStartNode = &_runningConv->_cnd._vars[1];
warning("TODO: GameConversations::start");
}
-void GameConversations::setVariable(uint idx, int v1, int v2) {
- if (active()) {
- _runningConv->_cnd._vars[idx].v1 = v1;
- _runningConv->_cnd._vars[idx].v2 = v2;
- }
+void GameConversations::setVariable(uint idx, int val) {
+ if (active())
+ _runningConv->_cnd._vars[idx].setValue(val);
+}
+
+void GameConversations::setVariable(uint idx, int *val) {
+ if (active())
+ _runningConv->_cnd._vars[idx].setValue(val);
+}
+
+void GameConversations::setStartNode(uint nodeIndex) {
+ assert(_nextStartNode && _nextStartNode->_isPtr == false);
+ _nextStartNode->_val = nodeIndex;
}
void GameConversations::stop() {
- warning("TODO GameConversations::stop");
+ // Only need to proceed if there is an active conversation
+ if (!active())
+ return;
+
+ // Reset player enabled state if needed
+ if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE)
+ _vm->_game->_player._stepEnabled = _playerEnabled;
+
+ // Remove any visible dialog window
+ removeActiveWindow();
+
+ // Release any sprites used for character portraits
+ for (int idx = 0; idx < _runningConv->_data._speakerCount; ++idx) {
+ if (_speakerActive[idx])
+ _vm->_game->_scene._sprites.remove(_speakerPortraits[idx]);
+ }
+
+ // Flag conversation as no longer running
+ _runningConv = nullptr;
+
+ if (_inputMode == kInputConversation)
+ _vm->_game->_scene._userInterface.emptyConversationList();
+
+ _vm->_game->_scene._userInterface.setup(_inputMode);
}
-void GameConversations::exportPointer(int *val) {
- warning("TODO GameConversations::exportPointer");
+void GameConversations::exportPointer(int *ptr) {
+ // Only need to proceed if there is an active conversation
+ if (!active())
+ return;
+
+ // Also don't proceed if the number of allowed imports has already been reached
+ if (_runningConv->_cnd._numImports >= _runningConv->_data._maxImports)
+ return;
+
+ // Get the variable to use for this next import and set it's value
+ int variableIndex = _runningConv->_cnd._importVariables[
+ _runningConv->_cnd._numImports++];
+ setVariable(variableIndex, ptr);
}
void GameConversations::exportValue(int val) {
- warning("TODO GameConversations::exportValue");
+ // Only need to proceed if there is an active conversation
+ if (!active())
+ return;
+
+ // Also don't proceed if the number of allowed imports has already been reached
+ if (_runningConv->_cnd._numImports >= _runningConv->_data._maxImports)
+ return;
+
+ // Get the variable to use for this next import and set it's value
+ int variableIndex = _runningConv->_cnd._importVariables[
+ _runningConv->_cnd._numImports++];
+ setVariable(variableIndex, val);
}
void GameConversations::setHeroTrigger(int val) {
- _vm->_game->_trigger = val; // HACK
- //_running = -1; // HACK
- warning("TODO: GameConversations::setHeroTrigger");
+ _heroTrigger = val;
+ _heroTriggerMode = _vm->_game->_triggerSetupMode;
}
void GameConversations::setInterlocutorTrigger(int val) {
- warning("TODO: GameConversations::setInterlocutorTrigger");
+ _interlocutorTrigger = val;
+ _interlocutorTriggerMode = _vm->_game->_triggerSetupMode;
}
-int* GameConversations::getVariable(int idx) {
- warning("TODO: GameConversations::getVariable");
- return nullptr;
+int *GameConversations::getVariable(int idx) {
+ return _vars[idx].getValue();
}
void GameConversations::hold() {
- warning("TODO: GameConversations::hold");
+ if (_heldVal != -1) {
+ _releaseVal = _heldVal;
+ _heldVal = -1;
+ }
}
void GameConversations::release() {
- warning("TODO: GameConversations::release");
+ if (_heldVal == -1) {
+ _heldVal = _releaseVal;
+ if (_heldVal == 1 || _heldVal == 2)
+ update(true);
+ }
+}
+
+void GameConversations::flagEntry(ConvFlagMode mode, int entryIndex) {
+ assert(_runningConv);
+ uint &flags = _runningConv->_cnd._entryFlags[entryIndex];
+
+ switch (mode) {
+ case FLAGMODE_1:
+ flags |= ENTRYFLAG_4000;
+ flags &= ~ENTRYFLAG_8000;
+ break;
+
+ case FLAGMODE_2:
+ flags &= ~ENTRYFLAG_8000;
+ break;
+
+ case FLAGMODE_3:
+ if (!(flags & ENTRYFLAG_4000))
+ flags |= ENTRYFLAG_8000;
+ break;
+
+ default:
+ break;
+ }
}
void GameConversations::reset(int id) {
warning("TODO: GameConversations::reset");
}
-void GameConversations::abortConv() {
- warning("TODO: GameConversations::abort");
+void GameConversations::update(bool isRelease) {
+ warning("TODO: GameConversations::update");
+}
+
+void GameConversations::removeActiveWindow() {
+ warning("TODO: GameConversations::removeActiveWindow");
}
/*------------------------------------------------------------------------*/
@@ -207,15 +291,16 @@ void ConversationData::load(const Common::String &filename) {
inFile.open(filename);
MadsPack convFileUnpacked(&inFile);
- Common::SeekableReadStream *convFile = convFileUnpacked.getItemStream(0);
// **** Section 0: Header *************************************************
+ Common::SeekableReadStream *convFile = convFileUnpacked.getItemStream(0);
+
_nodeCount = convFile->readUint16LE();
_dialogCount = convFile->readUint16LE();
_messageCount = convFile->readUint16LE();
_textLineCount = convFile->readUint16LE();
_unk2 = convFile->readUint16LE();
- _importCount = convFile->readUint16LE();
+ _maxImports = convFile->readUint16LE();
_speakerCount = convFile->readUint16LE();
for (uint idx = 0; idx < MAX_SPEAKERS; ++idx) {
@@ -275,7 +360,7 @@ void ConversationData::load(const Common::String &filename) {
// **** Section 3: Messages ***********************************************
convFile = convFileUnpacked.getItemStream(3);
- assert(convFile->size() == _messageCount * 8);
+ assert(convFile->size() == _messageCount * 4);
_messages.resize(_messageCount);
for (uint idx = 0; idx < _messageCount; ++idx)
@@ -389,8 +474,74 @@ void ConversationData::load(const Common::String &filename) {
/*------------------------------------------------------------------------*/
-void ConversationCnd::load(const Common::String &filename) {
- // TODO
+void ConversationConditionals::load(const Common::String &filename) {
+ Common::File inFile;
+ Common::SeekableReadStream *convFile;
+
+ inFile.open(filename);
+ MadsPack convFileUnpacked(&inFile);
+
+ // **** Section 0: Header *************************************************
+ convFile = convFileUnpacked.getItemStream(0);
+
+ convFile->skip(2);
+ int entryFlagsCount = convFile->readUint16LE();
+ int varsCount = convFile->readUint16LE();
+ int importsCount = convFile->readUint16LE();
+
+ delete convFile;
+
+ // **** Section: Imports *************************************************
+ int streamNum = 1;
+
+ _importVariables.resize(importsCount);
+ if (importsCount > 0) {
+ convFile = convFileUnpacked.getItemStream(streamNum++);
+
+ // Read in the variable indexes that each import value will be stored in
+ for (int idx = 0; idx < importsCount; ++idx)
+ _importVariables[idx] = convFile->readUint16LE();
+
+ delete convFile;
+ }
+
+ // **** Section: Entry Flags *********************************************
+ convFile = convFileUnpacked.getItemStream(streamNum++);
+ assert(convFile->size() == (entryFlagsCount * 2));
+
+ _entryFlags.resize(entryFlagsCount);
+ for (int idx = 0; idx < entryFlagsCount; ++idx)
+ _entryFlags[idx] = convFile->readUint16LE();
+
+ delete convFile;
+
+ // **** Section: Variables ***********************************************
+ convFile = convFileUnpacked.getItemStream(streamNum);
+ assert(convFile->size() == (varsCount * 6));
+
+ _vars.resize(varsCount);
+ for (int idx = 0; idx < varsCount; ++idx) {
+ convFile->skip(2); // Loaded values are never pointers, so don't need this
+ _vars[idx]._isPtr = false;
+ _vars[idx]._val = convFile->readSint16LE();
+ convFile->skip(2); // Unused segment selector for pointer values
+ }
+
+ delete convFile;
+}
+
+/*------------------------------------------------------------------------*/
+
+void ConversationVar::setValue(int val) {
+ _isPtr = false;
+ _valPtr = nullptr;
+ _val = val;
+}
+
+void ConversationVar::setValue(int *val) {
+ _isPtr = true;
+ _valPtr = val;
+ _val = 0;
}
} // End of namespace MADS