aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction/dialogue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/parallaction/dialogue.cpp')
-rw-r--r--engines/parallaction/dialogue.cpp430
1 files changed, 278 insertions, 152 deletions
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index 70db637699..21584a0525 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -33,7 +33,7 @@
namespace Parallaction {
#define MAX_PASSWORD_LENGTH 7
-
+/*
#define QUESTION_BALLOON_X 140
#define QUESTION_BALLOON_Y 10
#define QUESTION_CHARACTER_X 190
@@ -41,118 +41,127 @@ namespace Parallaction {
#define ANSWER_CHARACTER_X 10
#define ANSWER_CHARACTER_Y 80
+*/
+struct BalloonPositions {
+ Common::Point _questionBalloon;
+ Common::Point _questionChar;
+
+ Common::Point _answerChar;
+};
+
+BalloonPositions _balloonPositions_NS = {
+ Common::Point(140, 10),
+ Common::Point(190, 80),
+ Common::Point(10, 80)
+};
+
+BalloonPositions _balloonPositions_BR = {
+ Common::Point(0, 0),
+ Common::Point(380, 80),
+ Common::Point(10, 80)
+};
+
class DialogueManager {
+ enum {
+ RUN_QUESTION,
+ RUN_ANSWER,
+ NEXT_QUESTION,
+ NEXT_ANSWER,
+ DIALOGUE_OVER
+ } _state;
+
Parallaction *_vm;
- SpeakData *_data;
Dialogue *_dialogue;
bool _askPassword;
+ int _passwordLen;
+ bool _passwordChanged;
bool isNpc;
- Frames *_questioner;
- Frames *_answerer;
+ GfxObj *_questioner;
+ GfxObj *_answerer;
Question *_q;
uint16 _visAnswers[5];
int _numVisAnswers;
+ int _answerId;
+
+ int _selection, _oldSelection;
+
+ uint32 _mouseButtons;
+ Common::Point _mousePos;
+ bool _isKeyDown;
+ uint16 _downKey;
+
+ BalloonPositions _ballonPos;
+
public:
- DialogueManager(Parallaction *vm, SpeakData *data) : _vm(vm), _data(data) {
- _dialogue = _data->_dialogue;
- isNpc = scumm_stricmp(_data->_name, "yourself") && _data->_name[0] != '\0';
- _questioner = isNpc ? _vm->_disk->loadTalk(_data->_name) : _vm->_char._talk;
- _answerer = _vm->_char._talk;
- }
+ DialogueManager(Parallaction *vm, ZonePtr z);
+ ~DialogueManager();
- ~DialogueManager() {
- if (isNpc) {
- delete _questioner;
- }
+ bool isOver() {
+ return _state == DIALOGUE_OVER;
}
-
void run();
+ ZonePtr _z;
+ CommandList *_cmdList;
+
protected:
- void displayQuestion();
+ bool displayQuestion();
bool displayAnswers();
bool displayAnswer(uint16 i);
- uint16 getAnswer();
- int16 selectAnswer();
- uint16 askPassword();
+ int16 selectAnswer1();
+ int16 selectAnswerN();
+ int16 askPassword();
int16 getHoverAnswer(int16 x, int16 y);
-};
-
-uint16 DialogueManager::askPassword() {
- debugC(3, kDebugExec, "checkDialoguePassword()");
-
- uint16 passwordLen = 0;
- _password[0] = '\0';
-
- _vm->_gfx->setDialogueBalloon(_q->_answers[0]->_text, 1, 3);
- int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
- _vm->_gfx->setItemFrame(id, 0);
-
- Common::Event e;
- bool changed = true; // force first refresh
-
- while (true) {
- e.kbd.ascii = 0;
-
- if (g_system->getEventManager()->pollEvent(e)) {
- if (e.type == Common::EVENT_QUIT) {
- // TODO: don't quit() here, just have caller routines to check
- // on kEngineQuit and exit gracefully to allow the engine to shut down
- _engineFlags |= kEngineQuit;
- g_system->quit();
- }
-
- if ((e.type == Common::EVENT_KEYDOWN) && isdigit(e.kbd.ascii)) {
- _password[passwordLen] = e.kbd.ascii;
- passwordLen++;
- _password[passwordLen] = '\0';
- changed = true;
- }
- }
-
- if (changed) {
- _vm->_gfx->setBalloonText(0, _q->_answers[0]->_text, 3);
- _vm->_gfx->updateScreen();
- changed = false;
- }
-
- if ((passwordLen == MAX_PASSWORD_LENGTH) || (e.kbd.ascii == Common::KEYCODE_RETURN)) {
+ void runQuestion();
+ void runAnswer();
+ void nextQuestion();
+ void nextAnswer();
- if ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(_password, "1732461", 7)) ||
- (!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(_password, "1622", 4)) ||
- (!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(_password, "179", 3))) {
+ bool checkPassword();
+ void resetPassword();
+ void accumPassword(uint16 ascii);
+};
- break;
+DialogueManager::DialogueManager(Parallaction *vm, ZonePtr z) : _vm(vm), _z(z) {
+ int gtype = vm->getGameType();
+ if (gtype == GType_Nippon) {
+ _ballonPos = _balloonPositions_NS;
+ } else
+ if (gtype == GType_BRA) {
+ _ballonPos = _balloonPositions_BR;
+ } else
+ error("unsupported game in DialogueManager");
+
+ _dialogue = _z->u.speak->_dialogue;
+ isNpc = scumm_stricmp(_z->u.speak->_name, "yourself") && _z->u.speak->_name[0] != '\0';
+ _questioner = isNpc ? _vm->_disk->loadTalk(_z->u.speak->_name) : _vm->_char._talk;
+ _answerer = _vm->_char._talk;
- } else {
- passwordLen = 0;
- _password[0] = '\0';
- changed = true;
- }
+ _askPassword = false;
+ _q = _dialogue->_questions[0];
- }
+ _cmdList = 0;
+ _answerId = 0;
- g_system->delayMillis(20);
+ _state = displayQuestion() ? RUN_QUESTION : NEXT_ANSWER;
+}
+DialogueManager::~DialogueManager() {
+ if (isNpc) {
+ delete _questioner;
}
-
- _vm->_gfx->hideDialogueStuff();
-
- return 0;
-
+ _z = nullZonePtr;
}
-
-
bool DialogueManager::displayAnswer(uint16 i) {
Answer *a = _q->_answers[i];
@@ -164,11 +173,11 @@ bool DialogueManager::displayAnswer(uint16 i) {
// display suitable answers
if (((a->_yesFlags & flags) == a->_yesFlags) && ((a->_noFlags & ~flags) == a->_noFlags)) {
- int id = _vm->_gfx->setDialogueBalloon(a->_text, 1, 3);
+ int id = _vm->_balloonMan->setDialogueBalloon(a->_text, 1, 3);
assert(id >= 0);
_visAnswers[id] = i;
- _askPassword = (strstr(a->_text, "%p") != NULL);
+ _askPassword = (strstr(a->_text, "%P") != NULL);
_numVisAnswers++;
return true;
@@ -185,126 +194,243 @@ bool DialogueManager::displayAnswers() {
displayAnswer(i);
}
+ if (_askPassword) {
+ resetPassword();
+// _vm->_balloonMan->setDialogueBalloon(_q->_answers[0]->_text, 1, 3);
+ int id = _vm->_gfx->setItem(_answerer, _ballonPos._answerChar.x, _ballonPos._answerChar.y);
+ _vm->_gfx->setItemFrame(id, 0);
+ } else
+ if (_numVisAnswers == 1) {
+ int id = _vm->_gfx->setItem(_answerer, _ballonPos._answerChar.x, _ballonPos._answerChar.y);
+ _vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF);
+ _vm->_balloonMan->setBalloonText(0, _q->_answers[_visAnswers[0]]->_text, 0);
+ } else
+ if (_numVisAnswers > 1) {
+ int id = _vm->_gfx->setItem(_answerer, _ballonPos._answerChar.x, _ballonPos._answerChar.y);
+ _vm->_gfx->setItemFrame(id, _q->_answers[_visAnswers[0]]->_mood & 0xF);
+ _oldSelection = -1;
+ _selection = 0;
+ }
+
return _numVisAnswers > 0;
}
-void DialogueManager::displayQuestion() {
-
- if (!scumm_stricmp(_q->_text, "NULL")) return;
+bool DialogueManager::displayQuestion() {
+ if (!scumm_stricmp(_q->_text, "NULL")) return false;
- _vm->_gfx->setSingleBalloon(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, _q->_mood & 0x10, 0);
- int id = _vm->_gfx->setItem(_questioner, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y);
+ _vm->_balloonMan->setSingleBalloon(_q->_text, _ballonPos._questionBalloon.x, _ballonPos._questionBalloon.y, _q->_mood & 0x10, 0);
+ int id = _vm->_gfx->setItem(_questioner, _ballonPos._questionChar.x, _ballonPos._questionChar.y);
_vm->_gfx->setItemFrame(id, _q->_mood & 0xF);
- _vm->_gfx->updateScreen();
- _vm->_input->waitUntilLeftClick();
- _vm->_gfx->hideDialogueStuff();
+ return true;
+}
- return;
+
+bool DialogueManager::checkPassword() {
+ return ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(_password, "1732461", 7)) ||
+ (!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(_password, "1622", 4)) ||
+ (!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(_password, "179", 3)));
}
-uint16 DialogueManager::getAnswer() {
+void DialogueManager::resetPassword() {
+ _passwordLen = 0;
+ _password[0] = '\0';
+ _passwordChanged = true;
+}
+
+void DialogueManager::accumPassword(uint16 ascii) {
+ if (!isdigit(ascii)) {
+ return;
+ }
- uint16 answer = 0;
+ _password[_passwordLen] = ascii;
+ _passwordLen++;
+ _password[_passwordLen] = '\0';
+ _passwordChanged = true;
+}
- if (_askPassword == false) {
- answer = selectAnswer();
- } else {
- answer = askPassword();
+int16 DialogueManager::askPassword() {
+
+ if (_isKeyDown) {
+ accumPassword(_downKey);
+ }
+
+ if (_passwordChanged) {
+ _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3);
+ _passwordChanged = false;
}
- debugC(3, kDebugExec, "runDialogue: user selected answer #%i", answer);
+ if ((_passwordLen == MAX_PASSWORD_LENGTH) || ((_isKeyDown) && (_downKey == Common::KEYCODE_RETURN))) {
+ if (checkPassword()) {
+ return 0;
+ } else {
+ resetPassword();
+ }
+ }
- return answer;
+ return -1;
}
-void DialogueManager::run() {
+int16 DialogueManager::selectAnswer1() {
- _askPassword = false;
- CommandList *cmdlist = NULL;
+ if (_mouseButtons == kMouseLeftUp) {
+ return 0;
+ }
- _q = _dialogue->_questions[0];
- int16 answer;
+ return -1;
+}
- while (_q) {
+int16 DialogueManager::selectAnswerN() {
- answer = 0;
+ _selection = _vm->_balloonMan->hitTestDialogueBalloon(_mousePos.x, _mousePos.y);
- displayQuestion();
- if (_q->_answers[0] == NULL) break;
+ if (_selection != _oldSelection) {
+ if (_oldSelection != -1) {
+ _vm->_balloonMan->setBalloonText(_oldSelection, _q->_answers[_visAnswers[_oldSelection]]->_text, 3);
+ }
- if (scumm_stricmp(_q->_answers[0]->_text, "NULL")) {
- if (!displayAnswers()) break;
- answer = getAnswer();
- cmdlist = &_q->_answers[answer]->_commands;
+ if (_selection != -1) {
+ _vm->_balloonMan->setBalloonText(_selection, _q->_answers[_visAnswers[_selection]]->_text, 0);
+ _vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[_selection]]->_mood & 0xF);
}
+ }
+
+ _oldSelection = _selection;
- _q = _q->_answers[answer]->_following._question;
+ if ((_mouseButtons == kMouseLeftUp) && (_selection != -1)) {
+ return _visAnswers[_selection];
}
- if (cmdlist)
- _vm->runCommands(*cmdlist);
+ return -1;
+}
+
+void DialogueManager::runQuestion() {
+ debugC(9, kDebugDialogue, "runQuestion\n");
+
+ if (_mouseButtons == kMouseLeftUp) {
+ _vm->hideDialogueStuff();
+ _state = NEXT_ANSWER;
+ }
}
-int16 DialogueManager::selectAnswer() {
- int16 numAvailableAnswers = _numVisAnswers;
+void DialogueManager::nextAnswer() {
+ debugC(9, kDebugDialogue, "nextAnswer\n");
- int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
- _vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF);
+ if (_q->_answers[0] == NULL) {
+ _state = DIALOGUE_OVER;
+ return;
+ }
- if (numAvailableAnswers == 1) {
- _vm->_gfx->setBalloonText(0, _q->_answers[0]->_text, 0);
- _vm->_input->waitUntilLeftClick();
- _vm->_gfx->hideDialogueStuff();
- return 0;
+ if (!scumm_stricmp(_q->_answers[0]->_text, "NULL")) {
+ _answerId = 0;
+ _state = NEXT_QUESTION;
+ return;
+ }
+
+ _state = displayAnswers() ? RUN_ANSWER : DIALOGUE_OVER;
+}
+
+void DialogueManager::runAnswer() {
+ debugC(9, kDebugDialogue, "runAnswer\n");
+
+ if (_askPassword) {
+ _answerId = askPassword();
+ } else
+ if (_numVisAnswers == 1) {
+ _answerId = selectAnswer1();
+ } else {
+ _answerId = selectAnswerN();
+ }
+
+ if (_answerId != -1) {
+ _cmdList = &_q->_answers[_answerId]->_commands;
+ _vm->hideDialogueStuff();
+ _state = NEXT_QUESTION;
}
+}
+
+void DialogueManager::nextQuestion() {
+ debugC(9, kDebugDialogue, "nextQuestion\n");
- int oldSelection = -1;
- int selection;
+ _q = _q->_answers[_answerId]->_following._question;
+ if (_q == 0) {
+ _state = DIALOGUE_OVER;
+ } else {
+ _state = displayQuestion() ? RUN_QUESTION : NEXT_ANSWER;
+ }
+}
- uint32 event;
- Common::Point p;
- while (true) {
- _vm->_input->readInput();
- _vm->_input->getCursorPos(p);
- event = _vm->_input->getLastButtonEvent();
- selection = _vm->_gfx->hitTestDialogueBalloon(p.x, p.y);
+void DialogueManager::run() {
- if (selection != oldSelection) {
- if (oldSelection != -1) {
- _vm->_gfx->setBalloonText(oldSelection, _q->_answers[_visAnswers[oldSelection]]->_text, 3);
- }
+ // cache event data
+ _mouseButtons = _vm->_input->getLastButtonEvent();
+ _vm->_input->getCursorPos(_mousePos);
+ _isKeyDown = _vm->_input->getLastKeyDown(_downKey);
- if (selection != -1) {
- _vm->_gfx->setBalloonText(selection, _q->_answers[_visAnswers[selection]]->_text, 0);
- _vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[selection]]->_mood & 0xF);
- }
- }
+ switch (_state) {
+ case RUN_QUESTION:
+ runQuestion();
+ break;
- if ((selection != -1) && (event == kMouseLeftUp)) {
- break;
- }
+ case NEXT_ANSWER:
+ nextAnswer();
+ break;
- _vm->_gfx->updateScreen();
- g_system->delayMillis(20);
+ case NEXT_QUESTION:
+ nextQuestion();
+ break;
- oldSelection = selection;
+ case RUN_ANSWER:
+ runAnswer();
+ break;
+
+ case DIALOGUE_OVER:
+ break;
+
+ default:
+ error("unknown state in DialogueManager");
+
+ }
+
+}
+
+void Parallaction::enterDialogueMode(ZonePtr z) {
+ debugC(1, kDebugDialogue, "Parallaction::enterDialogueMode(%s)", z->u.speak->_name);
+ _dialogueMan = new DialogueManager(this, z);
+ _input->_inputMode = Input::kInputModeDialogue;
+}
+
+void Parallaction::exitDialogueMode() {
+ debugC(1, kDebugDialogue, "Parallaction::exitDialogueMode()");
+ _input->_inputMode = Input::kInputModeGame;
+
+ if (_dialogueMan->_cmdList) {
+ _vm->_cmdExec->run(*_dialogueMan->_cmdList);
}
- _vm->_gfx->hideDialogueStuff();
+ // The current instance of _dialogueMan must be destroyed before the zone commands
+ // are executed, because they may create another instance of _dialogueMan that
+ // overwrite the current one. This would cause headaches (and it did, actually).
+ ZonePtr z = _dialogueMan->_z;
+ delete _dialogueMan;
+ _dialogueMan = 0;
- return _visAnswers[selection];
+ _cmdExec->run(z->_commands, z);
}
+void Parallaction::runDialogueFrame() {
+ if (_input->_inputMode != Input::kInputModeDialogue) {
+ return;
+ }
-void Parallaction::runDialogue(SpeakData *data) {
- debugC(1, kDebugExec, "runDialogue: starting dialogue '%s'", data->_name);
+ _dialogueMan->run();
- DialogueManager man(this, data);
- man.run();
+ if (_dialogueMan->isOver()) {
+ exitDialogueMode();
+ }
return;
}