From c9890cbacc7bf6a1216cadf6eddc04832f0ebbe4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 12 Apr 2015 17:55:55 -0500 Subject: SHERLOCK: Implementing event handling for talk display --- engines/sherlock/people.cpp | 1 + engines/sherlock/people.h | 1 + engines/sherlock/talk.h | 4 +- engines/sherlock/user_interface.cpp | 254 +++++++++++++++++++++++++++++++++++- 4 files changed, 258 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 5c7f9ef506..e6a4eeed0f 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -203,6 +203,7 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _portraitSide = 0; _speakerFlip = false; _holmesFlip = false; + _homesQuotient = 0; } People::~People() { diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index ba870d041d..601fe6006b 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -81,6 +81,7 @@ public: int _portraitSide; bool _speakerFlip; bool _holmesFlip; + int _homesQuotient; public: People(SherlockEngine *vm); ~People(); diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 1a7dd587da..c4b5fe46d2 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -79,8 +79,10 @@ struct TalkSequences { }; class SherlockEngine; +class UserInterface; class Talk { + friend class UserInterface; private: Common::Array STILL_SEQUENCES; Common::Array TALK_SEQUENCES; @@ -97,7 +99,6 @@ private: int _converseNum; int _talkStealth; int _talkToFlag; - bool _moreTalkUp, _moreTalkDown; int _scriptSaveIndex; int _scriptCurrentIndex; private: @@ -117,6 +118,7 @@ public: int _talkTo; int _scriptMoreFlag; Common::String _scriptName; + bool _moreTalkUp, _moreTalkDown; public: Talk(SherlockEngine *vm); void setSequences(const byte *talkSequences, const byte *stillSequences, diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 9104c761a0..70f284c359 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -1222,8 +1222,260 @@ void UserInterface::doPickControl() { } } +/** + * Handles input when in talk mode. It highlights the buttons and available statements, + * and handles allowing the user to click on them + */ void UserInterface::doTalkControl() { - // TODO + Events &events = *_vm->_events; + Journal &journal = *_vm->_journal; + People &people = *_vm->_people; + Screen &screen = *_vm->_screen; + Sound &sound = *_vm->_sound; + Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; + Common::Point mousePos = events.mousePos(); + int select; + + _key = _oldKey = -1; + _keyboardInput = false; + + if (events._pressed || events._released) { + events.clearKeyboard(); + + // Handle button printing + if (mousePos.x > 99 && mousePos.x < 138 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && !_endKeyActive) + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Exit"); + else if (_endKeyActive) + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_FOREGROUND, true, "Exit"); + + if (mousePos.x > 140 && mousePos.x < 170 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && talk._moreTalkUp) + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Up"); + else if (talk._moreTalkUp) + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_FOREGROUND, true, "Up"); + + if (mousePos.x > 181&& mousePos.x < 220 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && talk._moreTalkDown) + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Down"); + else if (talk._moreTalkDown) + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, true, "Down"); + + bool found = false; + for (_selector = talk._talkIndex; _selector < (int)talk._statements.size() && !found; ++_selector) { + if (mousePos.y > talk._statements[_selector]._talkPos.top && + mousePos.y < talk._statements[_selector]._talkPos.bottom) + found = true; + } + --_selector; + if (!found) + _selector = -1; + } + + if (_keycode != Common::KEYCODE_INVALID) { + _key = toupper(_keycode); + if (_key == Common::KEYCODE_ESCAPE) + _key = 'E'; + + // Check for number press indicating reply line + if (_key >= '1' && _key <= ('1' + (int)talk._statements.size() - 1)) { + for (uint idx = 0; idx < talk._statements.size(); ++idx) { + if (talk._statements[idx]._talkMap == (_key - '1')) { + // Found the given statement + _selector = idx; + _key = -1; + _keyboardInput = true; + break; + } + } + } else if (_key == 'E' || _key == 'U' || _key == 'D') { + _keyboardInput = true; + } else { + _selector = -1; + } + } + + if (_selector != _oldSelector) { + // Remove highlighting from previous line, if any + if (_oldSelector != -1) { + if (!((talk._talkHistory[talk._converseNum][_oldSelector] >> (_oldSelector & 7)) & 1)) + talk.talkLine(_oldSelector, talk._statements[_oldSelector]._talkMap, INV_FOREGROUND, + talk._statements[_oldSelector]._talkPos.top, true); + else + talk.talkLine(_oldSelector, talk._statements[_oldSelector]._talkMap, TALK_NULL, + talk._statements[_oldSelector]._talkPos.top, true); + } + + // Add highlighting to new line, if any + if (_selector != -1) + talk.talkLine(_selector, talk._statements[_selector]._talkMap, TALK_FOREGROUND, + talk._statements[_selector]._talkPos.top, true); + } + + if (events._released || _keyboardInput) { + if (_endKeyActive && ((mousePos.x > 99 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) + && talk._moreTalkUp && events._released) || _key == 'E')) { + talk.freeTalkVars(); + talk.pullSequence(); + banishWindow(); + _windowBounds.top = CONTROLS_Y1; + } else if ((mousePos.x > 140 && mousePos.x < 179 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) + && talk._moreTalkUp && events._released) || (talk._moreTalkUp && _key == 'U')) { + while (talk._statements[--talk._talkIndex]._talkMap == -1) + ; + screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND); + talk.displayTalk(false); + + screen.slamRect(Common::Rect(5, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH - 5, SHERLOCK_SCREEN_HEIGHT - 2)); + } else if ((mousePos.x > 181 && mousePos.x < 220 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) + && talk._moreTalkDown && events._released) || (talk._moreTalkDown && _key == 'D')) { + do { + ++talk._talkIndex; + } while (talk._talkIndex < (int)talk._statements.size() && talk._statements[talk._talkIndex]._talkMap == -1); + + screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND); + talk.displayTalk(false); + + screen.slamRect(Common::Rect(5, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH - 5, SHERLOCK_SCREEN_HEIGHT - 2)); + } else if (_selector != -1) { + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, true, "Exit"); + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, true, "Up"); + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, true, "Down"); + + // If the reply is new, add it to the journal + if (!talk._talkHistory[talk._converseNum][_selector]) { + journal.record(talk._converseNum, _selector); + + // Add any Holmes point to Holmes' total, if any + if (talk._statements[_selector]._quotient) + people._homesQuotient += talk._statements[_selector]._quotient; + } + + // Flag the response as having been used + talk._talkHistory[talk._converseNum][_selector] = true; + + clearWindow(); + screen.print(Common::Point(16, CONTROLS_Y + 12), TALK_FOREGROUND, "Sherlock Holmes"); + talk.talkLine(_selector + 128, talk._statements[_selector]._talkMap, COMMAND_FOREGROUND, CONTROLS_Y + 21, true); + + switch (talk._statements[_selector]._portraitSide & 3) { + case 0: + case 1: + people._portraitSide = 20; + break; + case 2: + people._portraitSide = 220; + break; + case 3: + people._portraitSide = 120; + break; + } + + // Check for flipping Holmes + if (talk._statements[_selector]._portraitSide & REVERSE_DIRECTION) + people._holmesFlip = true; + + talk._speaker = 0; + people.setTalking(0); + + if (!talk._statements[_selector]._voiceFile.empty() && sound._voices) { + sound.playSound(talk._statements[_selector]._voiceFile); + + // Set voices as an indicator for waiting + sound._voices = 2; + sound._speechOn = *sound._soundIsOn; + } else { + sound._speechOn = false; + } + + // Set the _scriptCurrentIndex so if the statement is irrupted, the entire + // reply will be shown when it's restarted + talk._scriptCurrentIndex = 0; + talk.waitForMore(talk._statements[_selector]._statement.size()); + if (talk._talkToAbort) + return; + + people.clearTalking(); + if (talk._talkToAbort) + return; + + while (!_vm->shouldQuit()) { + talk._scriptSelect = _selector; + talk._speaker = talk._talkTo; + talk.doScript(talk._statements[_selector]._reply); + + if (!talk._talkToAbort) { + if (!talk._talkStealth) + clearWindow(); + + if (!talk._statements[_selector]._modified.empty()) { + for (uint idx = 0; idx < talk._statements[_selector]._modified.size(); ++idx) { + _vm->setFlags(talk._statements[_selector]._modified[idx]); + } + + talk.setTalkMap(); + } + + // Check for another linked talk file + Common::String linkFilename = talk._statements[_selector]._linkFile; + if (!linkFilename.empty() && !talk._scriptMoreFlag) { + talk.freeTalkVars(); + talk.loadTalkFile(linkFilename); + + // Find the first new statement + select = _selector = _oldSelector = -1; + for (uint idx = 0; idx < talk._statements.size() && select == -1; ++idx) { + if (!talk._statements[idx]._talkMap) + select = talk._talkIndex = idx; + } + + // See if the new statement is a stealth reply + talk._talkStealth = talk._statements[select]._statement.hasPrefix("^") ? 2 : 0; + + // Is the new talk file a standard file, reply first file, or a stealth file + if (!talk._statements[select]._statement.hasPrefix("*") && + !talk._statements[select]._statement.hasPrefix("^")) { + // Not a reply first file, so display the new selections + if (_endKeyActive) + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_FOREGROUND, true, "Exit"); + else + screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, true, "Exit"); + + talk.displayTalk(true); + events.setCursor(ARROW); + break; + } else { + _selector = select; + + if (!talk._talkHistory[talk._converseNum][_selector]) + journal.record(talk._converseNum, _selector); + + talk._talkHistory[talk._converseNum][_selector] = true; + } + } else { + talk.freeTalkVars(); + talk.pullSequence(); + banishWindow(); + _windowBounds.top = CONTROLS_Y1; + break; + } + } else { + break; + } + } + + events._pressed = events._released = false; + events._oldButtons = 0; + talk._talkStealth = 0; + + // If a script was pushed onto the script stack, restore it + if (!talk._scriptStack.empty()) { + SequenceEntry seqEntry = talk._scriptStack.pop(); +// talk._scriptName = seqEntry. + // TODO + } + } + } } void UserInterface::journalControl() { -- cgit v1.2.3