mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-03 07:11:49 +00:00
MADS: Implement GameConversations::update
This commit is contained in:
parent
2b1f7d6ebc
commit
a745010998
@ -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 *************************************************
|
||||
|
@ -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
|
||||
|
@ -269,4 +269,9 @@ void EventsManager::initVars() {
|
||||
_strokeGoing = 0;
|
||||
}
|
||||
|
||||
void EventsManager::clearEvents() {
|
||||
_pendingKeys.clear();
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace MADS
|
||||
|
@ -164,11 +164,19 @@ 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(); }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user