Implemented counters in BRA. Only valid answer options are shown, and counter calculations in scripts are performed.

svn-id: r35723
This commit is contained in:
Nicola Mettifogo
2009-01-04 14:23:20 +00:00
parent 4273d0db92
commit f2b495ba2d
9 changed files with 259 additions and 104 deletions
+72 -25
View File
@@ -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
+13 -18
View File
@@ -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
+1
View File
@@ -249,6 +249,7 @@ Answer::Answer() {
_followingQuestion = NULL;
_noFlags = 0;
_yesFlags = 0;
_hasCounterCondition = false;
}
Question::Question() {
+8 -2
View File
@@ -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();
};
+14 -2
View File
@@ -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();
+58
View File
@@ -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
+5 -2
View File
@@ -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),
+49 -8
View File
@@ -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;
}
+39 -47
View File
@@ -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;
}