diff options
| -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;  }  | 
