diff options
author | Nicola Mettifogo | 2009-01-04 14:23:20 +0000 |
---|---|---|
committer | Nicola Mettifogo | 2009-01-04 14:23:20 +0000 |
commit | f2b495ba2d31fc6cdfd07130c9491dea026c07cb (patch) | |
tree | 64e20efe7bdaf26335cc6eb8163a3c1c984233d9 | |
parent | 4273d0db92f37dcaefea280022e9d6b2effafeb9 (diff) | |
download | scummvm-rg350-f2b495ba2d31fc6cdfd07130c9491dea026c07cb.tar.gz scummvm-rg350-f2b495ba2d31fc6cdfd07130c9491dea026c07cb.tar.bz2 scummvm-rg350-f2b495ba2d31fc6cdfd07130c9491dea026c07cb.zip |
Implemented counters in BRA. Only valid answer options are shown, and counter calculations in scripts are performed.
svn-id: r35723
-rw-r--r-- | engines/parallaction/dialogue.cpp | 97 | ||||
-rw-r--r-- | engines/parallaction/exec_br.cpp | 31 | ||||
-rw-r--r-- | engines/parallaction/objects.cpp | 1 | ||||
-rw-r--r-- | engines/parallaction/objects.h | 10 | ||||
-rw-r--r-- | engines/parallaction/parallaction.h | 16 | ||||
-rw-r--r-- | engines/parallaction/parallaction_br.cpp | 58 | ||||
-rw-r--r-- | engines/parallaction/parser.h | 7 | ||||
-rw-r--r-- | engines/parallaction/parser_br.cpp | 57 | ||||
-rw-r--r-- | engines/parallaction/parser_ns.cpp | 86 |
9 files changed, 259 insertions, 104 deletions
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index 217af71eff..264e61ac7d 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -102,7 +102,7 @@ class DialogueManager { public: DialogueManager(Parallaction *vm, ZonePtr z); - ~DialogueManager(); + virtual ~DialogueManager(); bool isOver() { return _state == DIALOGUE_OVER; @@ -115,7 +115,8 @@ public: protected: bool displayQuestion(); bool displayAnswers(); - bool displayAnswer(uint16 i); + bool testAnswerFlags(Answer *a); + virtual bool canDisplayAnswer(Answer *a) = 0; int16 selectAnswer1(); int16 selectAnswerN(); @@ -132,6 +133,46 @@ protected: void accumPassword(uint16 ascii); }; +class DialogueManager_ns : public DialogueManager { + Parallaction_ns *_vm; + +public: + DialogueManager_ns(Parallaction_ns *vm, ZonePtr z) : DialogueManager(vm, z), _vm(vm) { + } + + virtual bool canDisplayAnswer(Answer *a) { + return testAnswerFlags(a); + } +}; + +class DialogueManager_br : public DialogueManager { + Parallaction_br *_vm; + + bool testAnswerCounter(Answer *a) { + if (!a->_hasCounterCondition) { + return true; + } + _vm->testCounterCondition(a->_counterName, a->_counterOp, a->_counterValue); + return (_vm->getLocationFlags() & kFlagsTestTrue) != 0; + } + +public: + DialogueManager_br(Parallaction_br *vm, ZonePtr z) : DialogueManager(vm, z), _vm(vm) { + } + + virtual bool canDisplayAnswer(Answer *a) { + if (!a) + return false; + + if (testAnswerFlags(a)) { + return true; + } + + return testAnswerCounter(a); + } +}; + + DialogueManager::DialogueManager(Parallaction *vm, ZonePtr z) : _vm(vm), _z(z) { int gtype = vm->getGameType(); if (gtype == GType_Nippon) { @@ -163,36 +204,31 @@ DialogueManager::~DialogueManager() { _z = nullZonePtr; } -bool DialogueManager::displayAnswer(uint16 i) { - - Answer *a = _q->_answers[i]; +bool DialogueManager::testAnswerFlags(Answer *a) { uint32 flags = _vm->getLocationFlags(); if (a->_yesFlags & kFlagsGlobal) flags = _globalFlags | kFlagsGlobal; - - // display suitable answers - if (((a->_yesFlags & flags) == a->_yesFlags) && ((a->_noFlags & ~flags) == a->_noFlags)) { - - int id = _vm->_balloonMan->setDialogueBalloon(a->_text.c_str(), 1, BalloonManager::kUnselectedColor); - assert(id >= 0); - _visAnswers[id] = i; - - _askPassword = a->_text.contains("%P"); - _numVisAnswers++; - - return true; - } - - return false; + return ((a->_yesFlags & flags) == a->_yesFlags) && ((a->_noFlags & ~flags) == a->_noFlags); } bool DialogueManager::displayAnswers() { _numVisAnswers = 0; + Answer *a; for (int i = 0; i < NUM_ANSWERS && _q->_answers[i]; i++) { - displayAnswer(i); + a = _q->_answers[i]; + if (!canDisplayAnswer(a)) { + continue; + } + + int id = _vm->_balloonMan->setDialogueBalloon(a->_text.c_str(), 1, BalloonManager::kUnselectedColor); + assert(id >= 0); + _visAnswers[id] = i; + _askPassword = a->_text.contains("%P"); + + _numVisAnswers++; } int mood = 0; @@ -201,8 +237,9 @@ bool DialogueManager::displayAnswers() { resetPassword(); } else if (_numVisAnswers == 1) { - mood = _q->_answers[0]->_mood & 0xF; - _vm->_balloonMan->setBalloonText(0, _q->_answers[_visAnswers[0]]->_text.c_str(), BalloonManager::kNormalColor); + Answer *a = _q->_answers[_visAnswers[0]]; + mood = a->_mood & 0xF; + _vm->_balloonMan->setBalloonText(0, a->_text.c_str(), BalloonManager::kNormalColor); } else if (_numVisAnswers > 1) { mood = _q->_answers[_visAnswers[0]]->_mood & 0xF; @@ -273,9 +310,12 @@ int16 DialogueManager::askPassword() { } int16 DialogueManager::selectAnswer1() { + if (!_q->_answers[_visAnswers[0]]->_text.compareToIgnoreCase("null")) { + return _visAnswers[0]; + } if (_mouseButtons == kMouseLeftUp) { - return 0; + return _visAnswers[0]; } return -1; @@ -400,7 +440,7 @@ void DialogueManager::run() { void Parallaction::enterDialogueMode(ZonePtr z) { debugC(1, kDebugDialogue, "Parallaction::enterDialogueMode(%s)", z->u.speak->_name); - _dialogueMan = new DialogueManager(this, z); + _dialogueMan = _vm->createDialogueManager(z); _input->_inputMode = Input::kInputModeDialogue; } @@ -436,5 +476,12 @@ void Parallaction::runDialogueFrame() { return; } +DialogueManager *Parallaction_ns::createDialogueManager(ZonePtr z) { + return new DialogueManager_ns(this, z); +} + +DialogueManager *Parallaction_br::createDialogueManager(ZonePtr z) { + return new DialogueManager_br(this, z); +} } // namespace Parallaction diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp index cc07578859..40c9de8cda 100644 --- a/engines/parallaction/exec_br.cpp +++ b/engines/parallaction/exec_br.cpp @@ -199,42 +199,36 @@ DECLARE_COMMAND_OPCODE(leave) { DECLARE_COMMAND_OPCODE(inc) { - _vm->_counters[_ctxt.cmd->u._lvalue] += _ctxt.cmd->u._rvalue; + int v = _vm->getCounterValue(_ctxt.cmd->u._counterName); + _vm->setCounterValue(_ctxt.cmd->u._counterName, v + _ctxt.cmd->u._counterValue); } DECLARE_COMMAND_OPCODE(dec) { - _vm->_counters[_ctxt.cmd->u._lvalue] -= _ctxt.cmd->u._rvalue; + int v = _vm->getCounterValue(_ctxt.cmd->u._counterName); + _vm->setCounterValue(_ctxt.cmd->u._counterName, v - _ctxt.cmd->u._counterValue); } +// these definitions must match those in parser_br.cpp +#define CMD_TEST 25 +#define CMD_TEST_GT 26 +#define CMD_TEST_LT 27 DECLARE_COMMAND_OPCODE(ifeq) { - if (_vm->_counters[_ctxt.cmd->u._lvalue] == _ctxt.cmd->u._rvalue) { - _vm->setLocationFlags(kFlagsTestTrue); - } else { - _vm->clearLocationFlags(kFlagsTestTrue); - } + _vm->testCounterCondition(_ctxt.cmd->u._counterName, CMD_TEST, _ctxt.cmd->u._counterValue); } DECLARE_COMMAND_OPCODE(iflt) { - if (_vm->_counters[_ctxt.cmd->u._lvalue] < _ctxt.cmd->u._rvalue) { - _vm->setLocationFlags(kFlagsTestTrue); - } else { - _vm->clearLocationFlags(kFlagsTestTrue); - } + _vm->testCounterCondition(_ctxt.cmd->u._counterName, CMD_TEST_LT, _ctxt.cmd->u._counterValue); } DECLARE_COMMAND_OPCODE(ifgt) { - if (_vm->_counters[_ctxt.cmd->u._lvalue] > _ctxt.cmd->u._rvalue) { - _vm->setLocationFlags(kFlagsTestTrue); - } else { - _vm->clearLocationFlags(kFlagsTestTrue); - } + _vm->testCounterCondition(_ctxt.cmd->u._counterName, CMD_TEST_GT, _ctxt.cmd->u._counterValue); } DECLARE_COMMAND_OPCODE(let) { - _vm->_counters[_ctxt.cmd->u._lvalue] = _ctxt.cmd->u._rvalue; + _vm->setCounterValue(_ctxt.cmd->u._counterName, _ctxt.cmd->u._counterValue); } @@ -545,4 +539,5 @@ ProgramExec_br::ProgramExec_br(Parallaction_br *vm) : ProgramExec_ns(vm), _vm(vm ProgramExec_br::~ProgramExec_br() { } + } // namespace Parallaction diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp index 00a09ec62d..1016ddd670 100644 --- a/engines/parallaction/objects.cpp +++ b/engines/parallaction/objects.cpp @@ -249,6 +249,7 @@ Answer::Answer() { _followingQuestion = NULL; _noFlags = 0; _yesFlags = 0; + _hasCounterCondition = false; } Question::Question() { diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h index 4e586d4d2b..6a2b1b442f 100644 --- a/engines/parallaction/objects.h +++ b/engines/parallaction/objects.h @@ -123,8 +123,8 @@ struct CommandData { // BRA specific Common::Point _startPos; Common::Point _startPos2; - uint _lvalue; - int _rvalue; + Common::String _counterName; + int _counterValue; int _zeta0; int _zeta1; int _zeta2; @@ -171,6 +171,12 @@ struct Answer { uint32 _noFlags; uint32 _yesFlags; + // BRA specific + bool _hasCounterCondition; + Common::String _counterName; + int _counterValue; + int _counterOp; + Answer(); }; diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 291ab56eb2..f7c79e1a3c 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -362,6 +362,7 @@ public: virtual void callFunction(uint index, void* parm) = 0; virtual void runPendingZones() = 0; virtual void cleanupGame() = 0; + virtual DialogueManager *createDialogueManager(ZonePtr z) = 0; }; @@ -384,6 +385,8 @@ public: virtual void runPendingZones(); virtual void cleanupGame(); + virtual DialogueManager *createDialogueManager(ZonePtr z); + void switchBackground(const char* background, const char* mask); private: @@ -474,11 +477,18 @@ public: virtual void runPendingZones(); virtual void cleanupGame(); + virtual DialogueManager *createDialogueManager(ZonePtr z); + void setupSubtitles(char *s, char *s2, int y); void clearSubtitles(); + void testCounterCondition(const Common::String &name, int op, int value); + public: - Table *_countersNames; + bool counterExists(const Common::String &name); + int getCounterValue(const Common::String &name); + void setCounterValue(const Common::String &name, int value); + const char **_audioCommandsNamesRes; static const char *_partNames[]; int _part; @@ -489,7 +499,6 @@ public: int _subtitleY; int _subtitle[2]; ZonePtr _activeZone2; - int32 _counters[32]; uint32 _zoneFlags[NUM_LOCATIONS][NUM_ZONES]; @@ -497,6 +506,9 @@ private: LocationParser_br *_locationParser; ProgramParser_br *_programParser; + int32 _counters[32]; + Table *_countersNames; + private: void initResources(); void initFonts(); diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 7d7fe660bc..5989d2c9b1 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -326,6 +326,64 @@ void Parallaction_br::changeCharacter(const char *name) { _char._ani->_flags |= kFlagsActive; } +bool Parallaction_br::counterExists(const Common::String &name) { + return Table::notFound != _countersNames->lookup(name.c_str()); +} + +int Parallaction_br::getCounterValue(const Common::String &name) { + int index = _countersNames->lookup(name.c_str()); + if (index != Table::notFound) { + return _counters[index - 1]; + } + return 0; +} + +void Parallaction_br::setCounterValue(const Common::String &name, int value) { + int index = _countersNames->lookup(name.c_str()); + if (index != Table::notFound) { + _counters[index - 1] = value; + } +} + +void Parallaction_br::testCounterCondition(const Common::String &name, int op, int value) { + int index = _countersNames->lookup(name.c_str()); + if (index == Table::notFound) { + clearLocationFlags(kFlagsTestTrue); + return; + } + + int c = _counters[index - 1]; + +// these definitions must match those in parser_br.cpp +#define CMD_TEST 25 +#define CMD_TEST_GT 26 +#define CMD_TEST_LT 27 + + bool res = false; + switch (op) { + case CMD_TEST: + res = (c == value); + break; + + case CMD_TEST_GT: + res = (c > value); + break; + + case CMD_TEST_LT: + res = (c < value); + break; + + default: + error("unknown operator in testCounterCondition"); + } + + if (res) { + setLocationFlags(kFlagsTestTrue); + } else { + clearLocationFlags(kFlagsTestTrue); + } +} + } // namespace Parallaction diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h index f83fc1384b..2858054ac9 100644 --- a/engines/parallaction/parser.h +++ b/engines/parallaction/parser.h @@ -189,8 +189,9 @@ protected: Common::String parseDialogueString(); Dialogue *parseDialogue(); void resolveDialogueForwards(Dialogue *dialogue, uint numQuestions, Table &forwards); - Answer *parseAnswer(); - void parseAnswerVariants(Answer *answer); + virtual Answer *parseAnswer(); + void parseAnswerFlags(Answer *answer); + void parseAnswerBody(Answer *answer); Question *parseQuestion(); void parseZone(ZoneList &list, char *name); @@ -306,6 +307,8 @@ protected: virtual void parseZoneTypeBlock(ZonePtr z); void parsePathData(ZonePtr z); void parseGetData(ZonePtr z); + void parseAnswerCounter(Answer *answer); + virtual Answer *parseAnswer(); public: LocationParser_br(Parallaction_br *vm) : LocationParser_ns((Parallaction_ns*)vm), _vm(vm), diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp index 8abf8fc4c4..b48db587db 100644 --- a/engines/parallaction/parser_br.cpp +++ b/engines/parallaction/parser_br.cpp @@ -564,9 +564,13 @@ DECLARE_COMMAND_PARSER(math) { createCommand(_parser->_lookup); - ctxt.cmd->u._lvalue = _vm->_countersNames->lookup(_tokens[1]); + if (!_vm->counterExists(_tokens[1])) { + error("counter '%s' doesn't exists", _tokens[1]); + } + + ctxt.cmd->u._counterName = _tokens[1]; ctxt.nextToken++; - ctxt.cmd->u._rvalue = atoi(_tokens[2]); + ctxt.cmd->u._counterValue = atoi(_tokens[2]); ctxt.nextToken++; parseCommandFlags(); @@ -578,19 +582,17 @@ DECLARE_COMMAND_PARSER(test) { debugC(7, kDebugParser, "COMMAND_PARSER(test) "); createCommand(_parser->_lookup); - - uint counter = _vm->_countersNames->lookup(_tokens[1]); ctxt.nextToken++; - if (counter == Table::notFound) { + if (!_vm->counterExists(_tokens[1])) { if (!scumm_stricmp("SFX", _tokens[1])) { ctxt.cmd->_id = CMD_TEST_SFX; } else { error("unknown counter '%s' in test opcode", _tokens[1]); } } else { - ctxt.cmd->u._lvalue = counter; - ctxt.cmd->u._rvalue = atoi(_tokens[3]); + ctxt.cmd->u._counterName = _tokens[1]; + ctxt.cmd->u._counterValue = atoi(_tokens[3]); ctxt.nextToken++; if (_tokens[2][0] == '>') { @@ -704,7 +706,7 @@ DECLARE_COMMAND_PARSER(unary) { createCommand(_parser->_lookup); - ctxt.cmd->u._rvalue = atoi(_tokens[1]); + ctxt.cmd->u._counterValue = atoi(_tokens[1]); ctxt.nextToken++; parseCommandFlags(); @@ -895,6 +897,45 @@ DECLARE_ANIM_PARSER(endanimation) { } +void LocationParser_br::parseAnswerCounter(Answer *answer) { + if (!_tokens[1][0]) { + return; + } + + if (scumm_stricmp(_tokens[1], "counter")) { + return; + } + + if (!_vm->counterExists(_tokens[2])) { + error("unknown counter '%s' in dialogue", _tokens[2]); + } + + answer->_hasCounterCondition = true; + + answer->_counterName = _tokens[2]; + answer->_counterValue = atoi(_tokens[4]); + + if (_tokens[3][0] == '>') { + answer->_counterOp = CMD_TEST_GT; + } else + if (_tokens[3][0] == '<') { + answer->_counterOp = CMD_TEST_LT; + } else { + answer->_counterOp = CMD_TEST; + } + +} + + + +Answer *LocationParser_br::parseAnswer() { + Answer *answer = new Answer; + assert(answer); + parseAnswerFlags(answer); + parseAnswerCounter(answer); + parseAnswerBody(answer); + return answer; +} diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp index 07e364fecc..bce99de730 100644 --- a/engines/parallaction/parser_ns.cpp +++ b/engines/parallaction/parser_ns.cpp @@ -862,53 +862,7 @@ Question *LocationParser_ns::parseQuestion() { return question; } -void LocationParser_ns::parseAnswerVariants(Answer *answer) { - if (!_tokens[1][0]) { - return; - } - - if (!scumm_stricmp(_tokens[1], "counter")) { - // TODO: parse the counter and the condition. This is done creating a new - // Command and usng the command parser for CMD_TEST in the original. - - } else { - - Table* flagNames; - uint16 token; - - if (!scumm_stricmp(_tokens[1], "global")) { - token = 2; - flagNames = _vm->_globalFlagsNames; - answer->_yesFlags |= kFlagsGlobal; - } else { - token = 1; - flagNames = _vm->_localFlagNames; - } - - do { - - if (!scumm_strnicmp(_tokens[token], "no", 2)) { - byte _al = flagNames->lookup(_tokens[token]+2); - answer->_noFlags |= 1 << (_al - 1); - } else { - byte _al = flagNames->lookup(_tokens[token]); - answer->_yesFlags |= 1 << (_al - 1); - } - - token++; - - } while (!scumm_stricmp(_tokens[token++], "|")); - - } -} - -Answer *LocationParser_ns::parseAnswer() { - - Answer *answer = new Answer; - assert(answer); - - parseAnswerVariants(answer); - +void LocationParser_ns::parseAnswerBody(Answer *answer) { answer->_text = parseDialogueString(); _script->readLineToken(true); @@ -927,7 +881,45 @@ Answer *LocationParser_ns::parseAnswer() { _script->readLineToken(true); } +} + +void LocationParser_ns::parseAnswerFlags(Answer *answer) { + if (!_tokens[1][0]) { + return; + } + + Table* flagNames; + uint16 token; + + if (!scumm_stricmp(_tokens[1], "global")) { + token = 2; + flagNames = _vm->_globalFlagsNames; + answer->_yesFlags |= kFlagsGlobal; + } else { + token = 1; + flagNames = _vm->_localFlagNames; + } + do { + + if (!scumm_strnicmp(_tokens[token], "no", 2)) { + byte _al = flagNames->lookup(_tokens[token]+2); + answer->_noFlags |= 1 << (_al - 1); + } else { + byte _al = flagNames->lookup(_tokens[token]); + answer->_yesFlags |= 1 << (_al - 1); + } + + token++; + + } while (!scumm_stricmp(_tokens[token++], "|")); +} + +Answer *LocationParser_ns::parseAnswer() { + Answer *answer = new Answer; + assert(answer); + parseAnswerFlags(answer); + parseAnswerBody(answer); return answer; } |