mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-01 06:14:07 +00:00
MADS: Implement conversation conditionals evaluation
This commit is contained in:
parent
9e672dab60
commit
a0eacd0537
@ -151,6 +151,9 @@ void GameConversations::start() {
|
||||
_runningConv->_cnd._currentNode = -1;
|
||||
_runningConv->_cnd._numImports = 0;
|
||||
_runningConv->_cnd._vars[0].setValue(_nextStartNode->_val);
|
||||
|
||||
// Store a reference to the variables list in the script handler for later reference
|
||||
ScriptEntry::Conditional::_vars = &_runningConv->_cnd._vars;
|
||||
}
|
||||
|
||||
void GameConversations::setVariable(uint idx, int val) {
|
||||
@ -441,7 +444,16 @@ int GameConversations::executeEntry(int index) {
|
||||
bool flag = true;
|
||||
for (uint scriptIdx = 0; scriptIdx < dlg._script.size(); ++scriptIdx) {
|
||||
DialogCommand cmd = dlg._script[scriptIdx]._command;
|
||||
// TODO
|
||||
|
||||
switch (cmd) {
|
||||
case CMD_1:
|
||||
case CMD_HIDE:
|
||||
case CMD_UNHIDE:
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Unknown script opcode");
|
||||
}
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
@ -774,10 +786,14 @@ void ScriptEntry::load(Common::SeekableReadStream &s) {
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEntry::Conditional::load(Common::SeekableReadStream &s) {
|
||||
_paramsFlag = s.readUint16LE();
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
if (_paramsFlag == 0xff) {
|
||||
Common::Array<ConversationVar> *ScriptEntry::Conditional::_vars = nullptr;
|
||||
|
||||
void ScriptEntry::Conditional::load(Common::SeekableReadStream &s) {
|
||||
_operation = (ConditionalOperation)s.readUint16LE();
|
||||
|
||||
if (_operation == CNVOP_ABORT) {
|
||||
_param1._isVariable = false;
|
||||
_param1._val = 0;
|
||||
_param2._isVariable = false;
|
||||
@ -790,62 +806,53 @@ void ScriptEntry::Conditional::load(Common::SeekableReadStream &s) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
do {
|
||||
command = convFile->readByte();
|
||||
chk = convFile->readUint16BE();
|
||||
if (chk != 0xFF00 && chk != 0x0000) {
|
||||
warning("Error while reading conversation node entries - bailing out");
|
||||
break;
|
||||
int ScriptEntry::Conditional::evaluate() const {
|
||||
if (_operation == CNVOP_NONE)
|
||||
return -1;
|
||||
|
||||
int param1 = get(0);
|
||||
if (_operation == CNVOP_VALUE)
|
||||
return param1;
|
||||
int param2 = get(1);
|
||||
|
||||
switch (_operation) {
|
||||
case CNVOP_ADD:
|
||||
return param1 + param2;
|
||||
case CNVOP_SUBTRACT:
|
||||
return param1 - param2;
|
||||
case CNVOP_MULTIPLY:
|
||||
return param1 * param2;
|
||||
case CNVOP_DIVIDE:
|
||||
return param1 / param2;
|
||||
case CNVOP_MODULUS:
|
||||
return param1 % param2;
|
||||
case CNVOP_LTEQ:
|
||||
return (param1 <= param2) ? 1 : 0;
|
||||
case CNVOP_GTEQ:
|
||||
return (param1 < param2) ? 1 : 0;
|
||||
case CNVOP_LT:
|
||||
return (param1 < param2) ? 1 : 0;
|
||||
case CNVOP_GT:
|
||||
return (param1 > param2) ? 1 : 0;
|
||||
case CNVOP_NEQ:
|
||||
return (param1 != param2) ? 1 : 0;
|
||||
case CNVOP_EQ:
|
||||
return (param1 == param2) ? 1 : 0;
|
||||
case CNVOP_AND:
|
||||
return (param1 || param2) ? 1 : 0;
|
||||
case CNVOP_OR:
|
||||
return (param1 && param2) ? 1 : 0;
|
||||
default:
|
||||
error("Unknown conditional operation");
|
||||
}
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case cmdNodeEnd:
|
||||
//debug("Node end");
|
||||
break;
|
||||
case cmdDialogEnd:
|
||||
//debug("Dialog end");
|
||||
break;
|
||||
case cmdHide: {
|
||||
byte count = convFile->readByte();
|
||||
for (byte k = 0; k < count; k++) {
|
||||
//uint16 nodeRef = convFile->readUint16LE();
|
||||
//debug("Hide node %d", nodeRef);
|
||||
int ScriptEntry::Conditional::get(int paramNum) const {
|
||||
const CondtionalParamEntry &p = (paramNum == 0) ? _param1 : _param2;
|
||||
return p._isVariable ? *(*_vars)[p._val].getValue() : p._val;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case cmdUnhide: {
|
||||
byte count = convFile->readByte();
|
||||
for (byte k = 0; k < count; k++) {
|
||||
//uint16 nodeRef = convFile->readUint16LE();
|
||||
//debug("Unhide node %d", nodeRef);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
}
|
||||
break;
|
||||
case cmdMessage:
|
||||
//debug("Message");
|
||||
convFile->skip(7); // TODO
|
||||
break;
|
||||
case cmdGoto: {
|
||||
convFile->skip(3); // unused?
|
||||
//byte nodeRef = convFile->readByte();
|
||||
//debug("Goto %d", nodeRef);
|
||||
}
|
||||
break;
|
||||
case cmdAssign: {
|
||||
convFile->skip(3); // unused?
|
||||
//uint16 value = convFile->readUint16LE();
|
||||
//uint16 variable = convFile->readUint16LE();
|
||||
//debug("Variable %d = %d", variable, value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error("Unknown conversation command %d", command);
|
||||
break;
|
||||
}
|
||||
} while (command != cmdNodeEnd && command != cmdDialogEnd);
|
||||
*/
|
||||
|
||||
} // End of namespace MADS
|
||||
|
@ -68,6 +68,62 @@ enum ConvEntryFlag {
|
||||
ENTRYFLAG_8000 = 0x8000
|
||||
};
|
||||
|
||||
enum ConditionalOperation {
|
||||
CNVOP_NONE = 0xff,
|
||||
CNVOP_VALUE = 0,
|
||||
CNVOP_ADD = 1,
|
||||
CNVOP_SUBTRACT = 2,
|
||||
CNVOP_MULTIPLY = 3,
|
||||
CNVOP_DIVIDE = 4,
|
||||
CNVOP_MODULUS = 5,
|
||||
CNVOP_LTEQ = 6,
|
||||
CNVOP_GTEQ = 7,
|
||||
CNVOP_LT = 8,
|
||||
CNVOP_GT = 9,
|
||||
CNVOP_NEQ = 10,
|
||||
CNVOP_EQ = 11,
|
||||
CNVOP_AND = 12,
|
||||
CNVOP_OR = 13,
|
||||
CNVOP_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 {
|
||||
@ -80,19 +136,30 @@ struct ScriptEntry {
|
||||
CondtionalParamEntry() : _isVariable(false), _val(0) {}
|
||||
};
|
||||
|
||||
uint _paramsFlag;
|
||||
static Common::Array<ConversationVar> *_vars;
|
||||
ConditionalOperation _operation;
|
||||
CondtionalParamEntry _param1;
|
||||
CondtionalParamEntry _param2;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Conditional() : _paramsFlag(false) {}
|
||||
Conditional() : _operation(CNVOP_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;
|
||||
};
|
||||
|
||||
DialogCommand _command;
|
||||
@ -178,42 +245,6 @@ struct ConversationData {
|
||||
void load(const Common::String &filename);
|
||||
};
|
||||
|
||||
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; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Conditional (i.e. changeable) data for the conversation
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user