aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/parallaction/dialogue.cpp97
-rw-r--r--engines/parallaction/exec_br.cpp31
-rw-r--r--engines/parallaction/objects.cpp1
-rw-r--r--engines/parallaction/objects.h10
-rw-r--r--engines/parallaction/parallaction.h16
-rw-r--r--engines/parallaction/parallaction_br.cpp58
-rw-r--r--engines/parallaction/parser.h7
-rw-r--r--engines/parallaction/parser_br.cpp57
-rw-r--r--engines/parallaction/parser_ns.cpp86
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;
}