aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2015-07-03 14:46:52 -0400
committerPaul Gilbert2015-07-03 14:46:52 -0400
commit895d2277e68d6ab7759be4b182f1c021059be883 (patch)
treef988b91bc891ea956a7d5a864ebda8f95d7dc5e3
parent273f4ae9458069b5a2057e670ad093079c724f77 (diff)
downloadscummvm-rg350-895d2277e68d6ab7759be4b182f1c021059be883.tar.gz
scummvm-rg350-895d2277e68d6ab7759be4b182f1c021059be883.tar.bz2
scummvm-rg350-895d2277e68d6ab7759be4b182f1c021059be883.zip
SHERLOCK: RT: Implement talk dialog handleEvents
-rw-r--r--engines/sherlock/sound.h2
-rw-r--r--engines/sherlock/talk.h22
-rw-r--r--engines/sherlock/tattoo/tattoo_fixed_text.cpp3
-rw-r--r--engines/sherlock/tattoo/tattoo_fixed_text.h3
-rw-r--r--engines/sherlock/tattoo/tattoo_people.h2
-rw-r--r--engines/sherlock/tattoo/widget_talk.cpp326
-rw-r--r--engines/sherlock/tattoo/widget_talk.h3
7 files changed, 343 insertions, 18 deletions
diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h
index a2e7715b21..414b1ef49b 100644
--- a/engines/sherlock/sound.h
+++ b/engines/sherlock/sound.h
@@ -59,6 +59,8 @@ public:
bool _soundPlaying;
bool *_soundIsOn;
byte *_digiBuf;
+
+ Common::String _talkSoundFile;
public:
Sound(SherlockEngine *vm, Audio::Mixer *mixer);
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index 4230a03644..066a9d8425 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -178,23 +178,12 @@ private:
* Remove any voice commands from a loaded statement list
*/
void stripVoiceCommands();
-
- /**
- * Form a table of the display indexes for statements
- */
- void setTalkMap();
/**
* Parses a reply for control codes and display text. The found text is printed within
* the text window, handles delays, animations, and animating portraits.
*/
void doScript(const Common::String &script);
-
- /**
- * When the talk window has been displayed, waits a period of time proportional to
- * the amount of text that's been displayed
- */
- int waitForMore(int delay);
protected:
SherlockEngine *_vm;
OpcodeMethod *_opcodeTable;
@@ -246,6 +235,17 @@ protected:
* Checks, if a character is an opcode
*/
bool isOpcode(byte checkCharacter);
+
+ /**
+ * Form a table of the display indexes for statements
+ */
+ void setTalkMap();
+
+ /**
+ * When the talk window has been displayed, waits a period of time proportional to
+ * the amount of text that's been displayed
+ */
+ int waitForMore(int delay);
/**
* Display the talk interface window
diff --git a/engines/sherlock/tattoo/tattoo_fixed_text.cpp b/engines/sherlock/tattoo/tattoo_fixed_text.cpp
index 06704a59f2..1a40c704ee 100644
--- a/engines/sherlock/tattoo/tattoo_fixed_text.cpp
+++ b/engines/sherlock/tattoo/tattoo_fixed_text.cpp
@@ -55,7 +55,8 @@ static const char *const FIXED_TEXT_ENGLISH[] = {
"Options",
"Solve",
"with",
- "No effect..."
+ "No effect...",
+ "This person has nothing to say at the moment"
};
TattooFixedText::TattooFixedText(SherlockEngine *vm) : FixedText(vm) {
diff --git a/engines/sherlock/tattoo/tattoo_fixed_text.h b/engines/sherlock/tattoo/tattoo_fixed_text.h
index d48f8496d6..06f6d765d9 100644
--- a/engines/sherlock/tattoo/tattoo_fixed_text.h
+++ b/engines/sherlock/tattoo/tattoo_fixed_text.h
@@ -55,7 +55,8 @@ enum FixedTextId {
kFixedText_Options,
kFixedText_Solve,
kFixedText_With,
- kFixedText_NoEffect
+ kFixedText_NoEffect,
+ kFixedText_NothingToSay
};
class TattooFixedText: public FixedText {
diff --git a/engines/sherlock/tattoo/tattoo_people.h b/engines/sherlock/tattoo/tattoo_people.h
index 6883b9d0e6..79794c2dae 100644
--- a/engines/sherlock/tattoo/tattoo_people.h
+++ b/engines/sherlock/tattoo/tattoo_people.h
@@ -220,7 +220,7 @@ public:
* @param speaker Who is speaking
* @param sequenceNum Which listen sequence to use
*/
- void setListenSequence(int speaker, int sequenceNum);
+ void setListenSequence(int speaker, int sequenceNum = 1);
/**
* Restore any saved NPC walk path data from any of the NPCs
diff --git a/engines/sherlock/tattoo/widget_talk.cpp b/engines/sherlock/tattoo/widget_talk.cpp
index e53a3d8170..562fc4377c 100644
--- a/engines/sherlock/tattoo/widget_talk.cpp
+++ b/engines/sherlock/tattoo/widget_talk.cpp
@@ -21,6 +21,8 @@
*/
#include "sherlock/tattoo/widget_talk.h"
+#include "sherlock/tattoo/tattoo_fixed_text.h"
+#include "sherlock/tattoo/tattoo_journal.h"
#include "sherlock/tattoo/tattoo_people.h"
#include "sherlock/tattoo/tattoo_talk.h"
#include "sherlock/tattoo/tattoo_scene.h"
@@ -32,12 +34,13 @@ namespace Sherlock {
namespace Tattoo {
#define STATEMENT_NUM_X 6
-#define VISIBLE_TALK_LINES 6
+#define NUM_VISIBLE_TALK_LINES 6
WidgetTalk::WidgetTalk(SherlockEngine *vm) : WidgetBase(vm) {
_talkScrollIndex = 0;
_selector = _oldSelector = -1;
_talkTextX = 0;
+ _dialogTimer = 0;
}
void WidgetTalk::getTalkWindowSize() {
@@ -139,9 +142,319 @@ void WidgetTalk::load() {
}
void WidgetTalk::handleEvents() {
- handleScrollbarEvents(_talkScrollIndex, VISIBLE_TALK_LINES, _statementLines.size());
+ Events &events = *_vm->_events;
+ TattooJournal &journal = *(TattooJournal *)_vm->_journal;
+ TattooPeople &people = *(TattooPeople *)_vm->_people;
+ TattooScene &scene = *(TattooScene *)_vm->_scene;
+ Sound &sound = *_vm->_sound;
+ TattooTalk &talk = *(TattooTalk *)_vm->_talk;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+ Common::KeyCode keycode = ui._keyState.keycode;
+ bool hotkey = false;
+ bool callParrotFile = false;
+
+ // Handle scrollbar events
+ ScrollHighlight oldHighlight = ui._scrollHighlight;
+ handleScrollbarEvents(_talkScrollIndex, NUM_VISIBLE_TALK_LINES, _statementLines.size());
+
+ // If the highlight has changed, redraw the scrollbar
+ if (ui._scrollHighlight != oldHighlight)
+ render(HL_SCROLLBAR_ONLY);
+
+ if (ui._scrollHighlight != SH_NONE || keycode == Common::KEYCODE_HOME || keycode == Common::KEYCODE_END
+ || keycode == Common::KEYCODE_PAGEUP || keycode == Common::KEYCODE_PAGEDOWN) {
+ int scrollIndex = _talkScrollIndex;
+
+ // Check for the scrollbar
+ if (ui._scrollHighlight == SH_THUMBNAIL) {
+ int yp = mousePos.y;
+ yp = CLIP(yp, _bounds.top + BUTTON_SIZE + 3, _bounds.bottom - BUTTON_SIZE - 3);
+
+ // Calculate the line number that corresponds to the position that the mouse is on the scrollbar
+ int lineNum = (yp - _bounds.top - BUTTON_SIZE - 3) * 100 / (_bounds.height() - BUTTON_SIZE * 2 - 6)
+ * _statementLines.size() / 100 - 3;
+
+ // If the new position would place part of the text outsidethe text window, adjust it so it doesn't
+ if (lineNum < 0)
+ lineNum = 0;
+ else if (lineNum + NUM_VISIBLE_TALK_LINES > (int)_statementLines.size()) {
+ lineNum = (int)_statementLines.size() - NUM_VISIBLE_TALK_LINES;
+
+ // Make sure it's not below zero now
+ if (lineNum < 0)
+ lineNum = 0;
+ }
- // TODO
+ _talkScrollIndex = lineNum;
+ }
+
+ // Get the current frame so we can check the scroll timer against it
+ uint32 frameNum = events.getFrameCounter();
+
+ if (frameNum > _dialogTimer) {
+ // Set the timeout for the next scroll if the mouse button remains held down
+ _dialogTimer = (_dialogTimer == 0) ? frameNum + NUM_VISIBLE_TALK_LINES : frameNum + 1;
+
+ // Check for Scroll Up
+ if (ui._scrollHighlight == SH_SCROLL_UP && _talkScrollIndex)
+ --_talkScrollIndex;
+
+ // Check for Page Up
+ if ((ui._scrollHighlight == SH_PAGE_UP || keycode == Common::KEYCODE_PAGEUP) && _talkScrollIndex)
+ _talkScrollIndex -= NUM_VISIBLE_TALK_LINES;
+
+ // Check for Page Down
+ if ((ui._scrollHighlight == SH_PAGE_DOWN || keycode == Common::KEYCODE_PAGEDOWN)
+ && (_talkScrollIndex + NUM_VISIBLE_TALK_LINES < (int)_statementLines.size())) {
+ _talkScrollIndex += 6;
+ if (_talkScrollIndex + NUM_VISIBLE_TALK_LINES >(int)_statementLines.size())
+ _talkScrollIndex = _statementLines.size() - NUM_VISIBLE_TALK_LINES;
+ }
+
+ // Check for Scroll Down
+ if (ui._scrollHighlight == SH_SCROLL_DOWN && (_talkScrollIndex + NUM_VISIBLE_TALK_LINES < (int)_statementLines.size()))
+ _talkScrollIndex++;
+ }
+
+ if (keycode == Common::KEYCODE_END)
+ _talkScrollIndex = _statementLines.size() - NUM_VISIBLE_TALK_LINES;
+
+ if (_talkScrollIndex < 0 || keycode == Common::KEYCODE_HOME)
+ _talkScrollIndex = 0;
+
+ // Only redraw the window if the the scrollbar position has changed
+ if (scrollIndex != _talkScrollIndex) {
+ _surface.fillRect(Common::Rect(4, 5, _surface.w() - BUTTON_SIZE - 8, _surface.h() - 4), TRANSPARENCY);
+ render(HL_NO_HIGHLIGHTING);
+ }
+ }
+
+ // Flag if they started pressing outside of the window
+ if (events._firstPress && !_bounds.contains(mousePos))
+ _outsideMenu = true;
+
+ // Check for which statement they are pointing at
+ _selector = -1;
+ if (ui._scrollHighlight == SH_NONE) {
+ if (Common::Rect(_bounds.left, _bounds.top + 5, _bounds.right - 3, _bounds.bottom - 5).contains(mousePos)) {
+ if (_scroll) {
+ // Disregard the scrollbar when setting the statement number
+ if (Common::Rect(_bounds.right - BUTTON_SIZE - 6, _bounds.top + 3, _bounds.right - 3, _bounds.bottom - 3).contains(mousePos))
+ _selector = (mousePos.y - _bounds.top - 5) / (_surface.fontHeight() + 1) + _talkScrollIndex;
+ } else {
+ _selector = (mousePos.y - _bounds.top - 5) / (_surface.fontHeight() + 1);
+ }
+
+ // Now translate the line number of the displayed line into the appropriate
+ // Statement number or set it to 255 to indicate no Statement selected
+ if (_selector < (int)_statementLines.size())
+ _selector = _statementLines[_selector]._num;
+ else
+ _selector = -1;
+ }
+ }
+
+ // Check for the tab keys
+ if (keycode == Common::KEYCODE_TAB && ui._scrollHighlight == SH_NONE) {
+ if (_selector == -1) {
+ _selector = _statementLines[_scroll ? _talkScrollIndex : 0]._num;
+
+ events.warpMouse(Common::Point(_bounds.right - BUTTON_SIZE - 10, _bounds.top + _surface.fontHeight() + 2));
+ } else {
+ if (ui._keyState.flags & Common::KBD_SHIFT) {
+ _selector = (mousePos.y - _bounds.top - 5) / (_surface.fontHeight() + 1) + _talkScrollIndex;
+ if (_statementLines[_selector]._num == _statementLines[_talkScrollIndex]._num) {
+ _selector = (_bounds.height() - 10) / (_surface.fontHeight() + 1) + _talkScrollIndex;
+ } else {
+ int idx = _selector;
+ do {
+ --_selector;
+ } while (_selector > 0 && _statementLines[idx]._num == _statementLines[_selector]._num);
+ }
+
+ int idx = _selector;
+ while ((_statementLines[idx]._num == _statementLines[_selector - 1]._num) && (_selector > _talkScrollIndex))
+ --_selector;
+ } else {
+ _selector = (mousePos.y - _bounds.top - 5) / (_surface.fontHeight() + 1) + _talkScrollIndex;
+ if (_statementLines[_selector]._num == _statementLines[(_bounds.height() - 10) / (_surface.fontHeight() + 1) + _talkScrollIndex]._num) {
+ _selector = _talkScrollIndex;
+ } else {
+ int idx = _selector;
+ do {
+ ++_selector;
+ } while (_selector < (int)_statementLines.size() && _statementLines[idx]._num == _statementLines[_selector]._num);
+ }
+ }
+
+ events.warpMouse(Common::Point(mousePos.x, _bounds.top + _surface.fontHeight() + 2 + (_surface.fontHeight() + 1)
+ * (_selector - _talkScrollIndex)));
+ _selector = _statementLines[_selector]._num;
+ }
+ }
+
+ // Handle selecting a talk entry if a numeric key has been pressed
+ if (keycode >= Common::KEYCODE_1 && keycode <= Common::KEYCODE_9) {
+ int x = 0, t = 0, y = 0;
+
+ do {
+ if (y == (keycode - Common::KEYCODE_1)) {
+ _selector = _statementLines[t]._num;
+ _outsideMenu = false;
+ hotkey = true;
+ break;
+ }
+
+ ++t;
+ if (_statementLines[x]._num != _statementLines[t]._num) {
+ x = t;
+ ++y;
+ }
+ } while (t < (int)_statementLines.size());
+ }
+
+ // Display the selected statement highlighted and reset the last statement.
+ if (_selector != _oldSelector) {
+ render(HL_CHANGED_HIGHLIGHTS);
+ _oldSelector = _selector;
+ }
+
+ if (events._released || events._rightReleased || keycode == Common::KEYCODE_ESCAPE || hotkey) {
+ _dialogTimer = 0;
+ ui._scrollHighlight = SH_NONE;
+
+ // See if they want to close the menu (click outside the window or Escape pressed)
+ if ((_outsideMenu && _bounds.contains(mousePos)) || keycode == Common::KEYCODE_ESCAPE) {
+ if (keycode == Common::KEYCODE_ESCAPE)
+ _selector = -1;
+
+ talk.freeTalkVars();
+ talk.pullSequence();
+
+ for (int idx = 1; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._type == CHARACTER) {
+ while (people[idx]._pathStack.empty())
+ people[idx].pullNPCPath();
+ }
+ }
+
+ banishWindow();
+ ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE;
+
+ if (scene._currentScene == 52)
+ callParrotFile = true;
+ }
+
+ _outsideMenu = false;
+
+ // See if they have selected a statement to say
+ if (_selector != -1) {
+ if (!talk._talkHistory[talk._converseNum][_selector] && talk._statements[_selector]._journal)
+ journal.record(talk._converseNum, _selector);
+ talk._talkHistory[talk._converseNum][_selector] = true;
+
+ talk._speaker = _vm->readFlags(76) ? HOLMES : WATSON;
+ _scroll = false;
+ const byte *msg = (const byte *)talk._statements[_selector]._statement.c_str();
+ talk.talkInterface(msg);
+
+ if (sound._speechOn)
+ sound._talkSoundFile += Common::String::format("%02dA", _selector + 1);
+
+ int msgLen = MAX((int)talk._statements[_selector]._statement.size(), 160);
+ people.setTalkSequence(talk._speaker);
+
+ talk.waitForMore(msgLen);
+ if (talk._talkToAbort)
+ return;
+
+ people.setListenSequence(talk._speaker);
+
+ do {
+ talk._scriptSelect = _selector;
+ talk._speaker = talk._talkTo;
+ talk.talkTo(talk._statements[_selector]._reply);
+
+ // Reset the misc field in case any people changed their sequences
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx)
+ people[idx]._misc = 0;
+
+ if (!talk._talkToAbort) {
+ 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();
+ }
+
+ // See if there is another talk file linked to this.
+ if (!talk._statements[_selector]._linkFile.empty() && !talk._scriptMoreFlag) {
+ Common::String linkFile = talk._statements[_selector]._linkFile;
+ talk.freeTalkVars();
+ talk.loadTalkFile(linkFile);
+
+ _talkScrollIndex = 0;
+ int select = -1;
+ _selector = _oldSelector = -1;
+
+ // Find the first statement that has all it's flags set correctly
+ for (uint idx = 0; idx < talk._statements.size() && select == -1; ++select) {
+ if (!talk._statements[idx]._talkMap)
+ select = idx;
+ }
+
+ if (select == -1) {
+ talk.freeTalkVars();
+ ui.putMessage("%s", FIXED(NothingToSay));
+ return;
+ }
+
+ // See is the new statement is in stealth mode
+ talk._talkStealth = (talk._statements[select]._statement.hasPrefix("^")) ? 2 : 0;
+
+ // See if the new file is a standard file, a reply first file, or a Stealth Mode file
+ if (!talk._statements[select]._statement.hasPrefix("*") && !talk._statements[select]._statement.hasPrefix("^")) {
+ talk.openTalkWindow();
+ setStatementLines();
+ render(HL_NO_HIGHLIGHTING);
+ break;
+ } else {
+ _selector = select;
+
+ if (!talk._talkHistory[talk._converseNum][_selector] && talk._statements[_selector]._journal)
+ journal.record(talk._converseNum, _selector);
+
+ talk._talkHistory[talk._converseNum][_selector] = true;
+ }
+ } else {
+ talk.freeTalkVars();
+ talk.pullSequence();
+
+ for (int idx = 1; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._type == CHARACTER)
+ while (!people[idx]._pathStack.empty())
+ people[idx].pullNPCPath();
+ }
+
+ banishWindow();
+ ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE;
+ break;
+ }
+ } else {
+ break;
+ }
+ } while (!_vm->shouldQuit());
+
+ events.clearEvents();
+
+ // Now, if a script was pushed onto the script stack, restore them to allow the previous script to continue.
+ talk.popStack();
+ }
+ }
+
+ if (callParrotFile)
+ talk.talkTo("POUT52A");
}
void WidgetTalk::render(Highlight highlightMode) {
@@ -191,9 +504,14 @@ void WidgetTalk::render(Highlight highlightMode) {
// See if the scroll bar needs to be drawn
if (_scroll && highlightMode != HL_CHANGED_HIGHLIGHTS)
- drawScrollBar(_talkScrollIndex, VISIBLE_TALK_LINES, _statementLines.size());
+ drawScrollBar(_talkScrollIndex, NUM_VISIBLE_TALK_LINES, _statementLines.size());
}
+void WidgetTalk::setStatementLines() {
+ // TODO
+}
+
+
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/widget_talk.h b/engines/sherlock/tattoo/widget_talk.h
index 72a6441a4e..11b1b64ce4 100644
--- a/engines/sherlock/tattoo/widget_talk.h
+++ b/engines/sherlock/tattoo/widget_talk.h
@@ -47,6 +47,7 @@ private:
Common::Array<StatementLine> _statementLines;
int _selector, _oldSelector;
int _talkTextX;
+ uint32 _dialogTimer;
void getTalkWindowSize();
@@ -54,6 +55,8 @@ private:
* Re-renders the contenst of the window to the widget's surface
*/
void render(Highlight highlightMode);
+
+ void setStatementLines();
public:
WidgetTalk(SherlockEngine *vm);
virtual ~WidgetTalk() {}