SHERLOCK: Implemented doScript and support methods

This commit is contained in:
Paul Gilbert 2015-04-10 23:35:26 -05:00
parent d45d167213
commit 96e04ab797
16 changed files with 1002 additions and 59 deletions

View file

@ -26,7 +26,42 @@
namespace Sherlock {
#define SFX_COMMAND 140
enum {
SWITCH_SPEAKER = 128,
RUN_CANIMATION = 129,
ASSIGN_PORTRAIT_LOCATION = 130,
PAUSE = 131,
REMOVE_PORTRAIT = 132,
CLEAR_WINDOW = 133,
ADJUST_OBJ_SEQUENCE = 134,
WALK_TO_COORDS = 135,
PAUSE_WITHOUT_CONTROL = 136,
BANISH_WINDOW = 137,
SUMMON_WINDOW = 138,
SET_FLAG = 139,
SFX_COMMAND = 140,
TOGGLE_OBJECT = 141,
STEALTH_MODE_ACTIVE = 142,
IF_STATEMENT = 143,
ELSE_STATEMENT = 144,
END_IF_STATEMENT = 145,
STEALTH_MODE_DEACTIVATE = 146,
TURN_HOLMES_OFF = 147,
TURN_HOLMES_ON = 148,
GOTO_SCENE = 149,
PLAY_PROLOGUE = 150,
ADD_ITEM_TO_INVENTORY = 151,
SET_OBJECT = 152,
CALL_TALK_FILE = 153,
MOVE_MOUSE = 154,
DISPLAY_INFO_LINE = 155,
CLEAR_INFO_LINE = 156,
WALK_TO_CANIMATION = 157,
REMOVE_ITEM_FROM_INVENTORY = 158,
ENABLE_END_KEY = 159,
DISABLE_END_KEY = 160,
COMMAND_161 = 161
};
/*----------------------------------------------------------------*/
@ -99,6 +134,9 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) {
_talkStealth = 0;
_talkToFlag = -1;
_moreTalkDown = _moreTalkUp = false;
_scriptMoreFlag = 1;
_scriptSaveIndex = -1;
_scriptCurrentIndex = -1;
}
void Talk::setSequences(const byte *talkSequences, const byte *stillSequences, int maxPeople) {
@ -136,13 +174,13 @@ void Talk::talkTo(const Common::String &filename) {
// save the filename for later executing when the canimation is done
if (scene._ongoingCans || people._clearingThePortrait) {
// Make sure we're not in the middle of a script
if (!scripts._scriptMoreFlag) {
scripts._scriptName = filename;
scripts._scriptSaveIndex = 0;
if (!_scriptMoreFlag) {
_scriptName = filename;
_scriptSaveIndex = 0;
// Flag the selection, since we don't yet know which statement yet
scripts._scriptSelect = 100;
scripts._scriptMoreFlag = 3;
_scriptSelect = 100;
_scriptMoreFlag = 3;
}
return;
@ -172,7 +210,7 @@ void Talk::talkTo(const Common::String &filename) {
// If any sequences have changed in the prior talk file, restore them
if (_savedSequences.size() > 0) {
for (uint idx = 0; idx < _savedSequences.size(); ++idx) {
SavedSequence &ss = _savedSequences[idx];
SequenceEntry &ss = _savedSequences[idx];
for (uint idx2 = 0; idx2 < _savedSequences.size(); ++idx2)
scene._bgShapes[ss._objNum]._sequences[idx2] = ss._sequences[idx2];
@ -181,7 +219,7 @@ void Talk::talkTo(const Common::String &filename) {
}
}
while (!_sequenceStack.empty())
while (!_scriptStack.empty())
pullSequence();
// Restore any pressed button
@ -276,7 +314,7 @@ void Talk::talkTo(const Common::String &filename) {
select = _talkIndex = idx;
}
if (scripts._scriptMoreFlag && _scriptSelect != 0)
if (_scriptMoreFlag && _scriptSelect != 0)
select = _scriptSelect;
if (select == -1)
@ -288,7 +326,7 @@ void Talk::talkTo(const Common::String &filename) {
_talkHistory[_converseNum][select] = true;
// Check if the talk file is meant to be a non-seen comment
if (filename[7] != '*') {
if (filename.size() < 8 || filename[7] != '*') {
// Should we start in stealth mode?
if (_statements[select]._statement.hasPrefix("^")) {
_talkStealth = 2;
@ -305,13 +343,13 @@ void Talk::talkTo(const Common::String &filename) {
// Handle replies until there's no further linked file,
// or the link file isn't a reply first cnversation
for (;;) {
while (!_vm->shouldQuit()) {
clearSequences();
_scriptSelect = select;
_speaker = _talkTo;
Statement &statement = _statements[select];
scripts.doScript(_statements[select]._reply);
doScript(_statements[select]._reply);
if (_talkToAbort)
return;
@ -327,7 +365,7 @@ void Talk::talkTo(const Common::String &filename) {
}
// Check for a linked file
if (!statement._linkFile.empty() && !scripts._scriptMoreFlag) {
if (!statement._linkFile.empty() && !_scriptMoreFlag) {
freeTalkVars();
loadTalkFile(statement._linkFile);
@ -422,7 +460,7 @@ void Talk::talkTo(const Common::String &filename) {
// If a script was added to the script stack, restore state so that the
// previous script can continue
if (!scripts._scriptStack.empty()) {
if (!_scriptStack.empty()) {
scripts.popStack();
}
@ -547,7 +585,7 @@ void Talk::loadTalkFile(const Common::String &filename) {
// Check for an existing person being talked to
_talkTo = -1;
for (int idx = 0; idx < MAX_PEOPLE; ++idx) {
if (scumm_strnicmp(filename.c_str(), people[(PeopleId)idx]._portrait.c_str(), 4)) {
if (!scumm_strnicmp(filename.c_str(), people[(PeopleId)idx]._portrait.c_str(), 4)) {
_talkTo = idx;
break;
}
@ -568,7 +606,7 @@ void Talk::loadTalkFile(const Common::String &filename) {
delete talkStream;
if (!sound._voicesOn)
if (!sound._voices)
stripVoiceCommands();
setTalkMap();
}
@ -833,7 +871,7 @@ int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt
* Clears the stack of pending object sequences associated with speakers in the scene
*/
void Talk::clearSequences() {
_sequenceStack.clear();
_scriptStack.clear();
}
/**
@ -843,7 +881,7 @@ void Talk::clearSequences() {
void Talk::pullSequence() {
Scene &scene = *_vm->_scene;
SequenceEntry seq = _sequenceStack.pop();
SequenceEntry seq = _scriptStack.pop();
if (seq._objNum != -1) {
Object &obj = scene._bgShapes[seq._objNum];
@ -871,7 +909,7 @@ void Talk::pushSequence(int speaker) {
if (speaker == -1)
return;
SequenceEntry seqEntry;
ScriptStackEntry seqEntry;
if (!speaker) {
seqEntry._objNum = -1;
} else {
@ -885,9 +923,13 @@ void Talk::pushSequence(int speaker) {
seqEntry._seqTo = obj._seqTo;
}
_sequenceStack.push(seqEntry);
if (_sequenceStack.size() >= 5)
error("sequence stack overflow");
_scriptStack.push(seqEntry);
if (_scriptStack.size() >= 5)
error("script stack overflow");
}
void Talk::setSequence(int speaker) {
// TODO
}
/**
@ -923,4 +965,751 @@ void Talk::setStillSeq(int speaker) {
}
}
/**
* 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 Talk::doScript(const Common::String &script) {
Animation &anim = *_vm->_animation;
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
Sound &sound = *_vm->_sound;
UserInterface &ui = *_vm->_ui;
int wait = 0;
bool pauseFlag = false;
bool endStr = false;
int yp = CONTROLS_Y + 12;
int charCount = 0;
int line = 0;
bool noTextYet = true;
bool openTalkWindow = false;
int obj;
int seqCount;
_saveSeqNum = 0;
const char *str = script.c_str();
if (_scriptMoreFlag) {
_scriptMoreFlag = 0;
str = script.c_str() + _scriptSaveIndex;
}
// Check if the script begins with a Stealh Mode Active command
if (str[0] == STEALTH_MODE_ACTIVE || _talkStealth) {
_talkStealth = 2;
_speaker |= 128;
} else {
pushSequence(_speaker);
ui.clearWindow();
// Need to switch speakers?
if (str[0] == SWITCH_SPEAKER) {
_speaker = str[1] - 1;
str += 2;
pullSequence();
pushSequence(_speaker);
setSequence(_speaker);
}
else {
setSequence(_speaker);
}
// Assign portrait location?
if (str[0] == ASSIGN_PORTRAIT_LOCATION) {
switch (str[1] & 15) {
case 1:
people._portraitSide = 20;
break;
case 2:
people._portraitSide = 220;
break;
case 3:
people._portraitSide = 120;
break;
default:
break;
}
if (str[1] > 15)
people._speakerFlip = true;
str += 2;
}
// Remove portrait?
if (str[0] == REMOVE_PORTRAIT) {
_speaker = 255;
}
else {
// Nope, so set the first speaker
setTalking(_speaker);
}
}
do {
Common::String tempString;
wait = 0;
if (!str[0]) {
endStr = true;
} else if (str[0] == '{') {
// Start of comment, so skip over it
while (*str++ != '}')
;
} else if (str[0] >= 128) {
// Handle control code
switch (str[0]) {
case SWITCH_SPEAKER:
// Save the current point in the script, since it might be intterupted by
// doing bg anims in the next call, so we need to know where to return to
_scriptCurrentIndex = str - script.c_str();
if (!(_speaker & 128))
clearTalking();
if (_talkToAbort)
return;
ui.clearWindow();
yp = CONTROLS_Y + 12;
charCount = line = 0;
_speaker = *++str - 1;
setTalking(_speaker);
pullSequence();
pushSequence(_speaker);
setSequence(_speaker);
break;
case RUN_CANIMATION:
// Save the current point in the script, since it might be intterupted by
// doing bg anims in the next call, so we need to know where to return to
_scriptCurrentIndex = str - script.c_str();
scene.startCAnim((str[0] - 1) & 127, 1 + (str[0] & 128));
if (_talkToAbort)
return;
// Check if next character is changing side or changing portrait
if (charCount && (str[1] == SWITCH_SPEAKER || str[1] == ASSIGN_PORTRAIT_LOCATION))
wait = 1;
break;
case ASSIGN_PORTRAIT_LOCATION:
++str;
switch (str[0] & 15) {
case 1:
people._portraitSide = 20;
break;
case 2:
people._portraitSide = 220;
break;
case 3:
people._portraitSide = 120;
break;
default:
break;
}
if (str[0] > 15)
people._speakerFlip = true;
break;
case PAUSE:
// Pause
charCount = *++str;
wait = pauseFlag = true;
break;
case REMOVE_PORTRAIT:
// Save the current point in the script, since it might be intterupted by
// doing bg anims in the next call, so we need to know where to return to
_scriptCurrentIndex = str - script.c_str();
if (_speaker < 128)
clearTalking();
pullSequence();
if (_talkToAbort)
return;
_speaker |= 128;
break;
case CLEAR_WINDOW:
ui.clearWindow();
yp = CONTROLS_Y + 12;
charCount = line = 0;
break;
case ADJUST_OBJ_SEQUENCE:
// Get the name of the object to adjust
++str;
for (int idx = 0; idx < (str[0] & 127); ++idx)
tempString += str[idx + 2];
// Scan for object
obj = -1;
for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
if (scumm_stricmp(tempString.c_str(), scene._bgShapes[idx]._name.c_str()) == 0)
obj = idx;
}
if (obj == -1)
error("Could not find object %s to change", tempString.c_str());
// Should the script be overwritten?
if (str[0] > 128) {
// Save the current sequence
_savedSequences.push(SequenceEntry());
SequenceEntry &seqEntry = _savedSequences.top();
seqEntry._objNum = obj;
seqEntry._seqTo = scene._bgShapes[obj]._seqTo;
for (uint idx = 0; idx < scene._bgShapes[obj]._seqSize; ++idx)
seqEntry._sequences.push_back(scene._bgShapes[obj]._sequences[idx]);
}
// Get number of bytes to change
seqCount = str[1];
str += (str[0] & 127) + 2;
// Copy in the new sequence
for (int idx = 0; idx < seqCount; ++idx, ++str)
scene._bgShapes[obj]._sequences[idx] = str[0] - 1;
// Reset object back to beginning of new sequence
scene._bgShapes[obj]._frameNumber = 0;
continue;
case WALK_TO_COORDS:
// Save the current point in the script, since it might be intterupted by
// doing bg anims in the next call, so we need to know where to return to
_scriptCurrentIndex = str - script.c_str();
people.walkToCoords(Common::Point(((str[0] - 1) * 256 + str[1] - 1) * 100, str[2] * 100), str[3] - 1);
if (_talkToAbort)
return;
str += 3;
break;
case PAUSE_WITHOUT_CONTROL:
// Save the current point in the script, since it might be intterupted by
// doing bg anims in the next call, so we need to know where to return to
_scriptCurrentIndex = str - script.c_str();
for (int idx = 0; idx < (str[0] - 1); ++idx) {
scene.doBgAnim();
if (_talkToAbort)
return;
// Check for button press
events.pollEvents();
events.setButtonState();
}
break;
case BANISH_WINDOW:
// Save the current point in the script, since it might be intterupted by
// doing bg anims in the next call, so we need to know where to return to
_scriptCurrentIndex = str - script.c_str();
if (!(_speaker & 128))
clearTalking();
pullSequence();
if (_talkToAbort)
return;
_speaker |= 128;
ui.banishWindow();
ui._menuMode = TALK_MODE;
noTextYet = true;
break;
case SUMMON_WINDOW:
drawInterface();
events._pressed = events._released = false;
events.clearKeyboard();
noTextYet = false;
if (_speaker != -1) {
screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, false, "Exit");
screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, false, "Up");
screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, false, "Down");
}
break;
case SET_FLAG: {
++str;
int flag1 = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0);
int flag = (flag1 & 0x7fff) * (flag1 >= 0x8000 ? -1 : 1);
_vm->setFlags(flag);
++str;
break;
}
case SFX_COMMAND:
++str;
if (sound._voices) {
for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
tempString += str[idx];
sound.playSound(tempString);
// Set voices to wait for more
sound._voices = 2;
sound._speechOn = (*sound._soundIsOn);
}
wait = 1;
str += 7;
break;
case TOGGLE_OBJECT:
for (int idx = 0; idx < str[0]; ++idx)
tempString += str[idx + 1];
scene.toggleObject(tempString);
str += str[0];
break;
case STEALTH_MODE_ACTIVE:
_talkStealth = 2;
break;
case IF_STATEMENT: {
++str;
int flag = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0);
++str;
wait = 0;
bool result = flag < 0x8000;
if (_vm->readFlags(flag & 0x7fff) != result) {
do {
++str;
} while (str[0] && str[0] != ELSE_STATEMENT && str[0] != END_IF_STATEMENT);
if (!str[0])
endStr = true;
}
break;
}
case ELSE_STATEMENT:
// If this is encountered here, it means that a preceeding IF statement was found,
// and evaluated to true. Now all the statements for the true block are finished,
// so skip over the block of code that would have executed if the result was false
wait = 0;
do {
++str;
} while (str[0] && str[0] != END_IF_STATEMENT);
break;
case STEALTH_MODE_DEACTIVATE:
_talkStealth = 0;
events.clearKeyboard();
break;
case TURN_HOLMES_OFF:
people._holmesOn = false;
break;
case TURN_HOLMES_ON:
people._holmesOn = true;
break;
case GOTO_SCENE:
scene._goToScene = str[1] - 1;
if (scene._goToScene != 100) {
// Not going to the map overview
scene._oldCharPoint = scene._goToScene;
scene._overPos.x = _vm->_map[scene._goToScene].x * 100 - 600;
scene._overPos.y = _vm->_map[scene._goToScene].y * 100 + 900;
// Run a canimation?
if (str[2] > 100) {
scene._hsavedFs = str[2];
scene._hsavedPos = Common::Point(160, 100);
}
}
str += 6;
_scriptMoreFlag = (scene._goToScene == 100) ? 2 : 1;
_scriptSaveIndex = str - script.c_str();
endStr = true;
wait = 0;
break;
case PLAY_PROLOGUE:
++str;
for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
tempString += str[idx];
anim.playPrologue(tempString, 1, 3, true, 4);
break;
case ADD_ITEM_TO_INVENTORY:
++str;
for (int idx = 0; idx < str[0]; ++idx)
tempString += str[idx];
str += str[0];
inv.putNameInInventory(tempString);
break;
case SET_OBJECT: {
++str;
for (int idx = 0; idx < (str[0] & 127); ++idx)
tempString += str[idx + 1];
str += str[0];
// Set comparison state according to if we want to hide or unhide
bool state = (str[0] >= 128);
for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
Object &obj = scene._bgShapes[idx];
if (scumm_stricmp(tempString.c_str(), obj._name.c_str()) == 0) {
// Only toggle the object if it's not in the desired state already
if ((obj._type == HIDDEN && state) || (obj._type != HIDDEN && !state))
obj.toggleHidden();
}
}
break;
}
case CALL_TALK_FILE:
++str;
for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
tempString += str[idx];
str += 8;
_scriptCurrentIndex = str - script.c_str();
// Save the current script position and new talk file
if (_scriptStack.size() < 10) {
ScriptStackEntry rec;
rec._name = _scriptName;
rec._currentIndex = _scriptCurrentIndex;
rec._select = _scriptSelect;
} else {
error("Script stack overflow");
}
_scriptMoreFlag = true;
endStr = true;
wait = 0;
break;
case MOVE_MOUSE:
// Save the current point in the script, since it might be intterupted by
// doing bg anims in the next call, so we need to know where to return to
_scriptCurrentIndex = str - script.c_str();
events.moveMouse(Common::Point((str[0] - 1) * 256 + str[1] - 1, str[2]));
if (_talkToAbort)
return;
str += 3;
break;
case DISPLAY_INFO_LINE:
++str;
for (int idx = 0; idx < str[0]; ++idx)
tempString += str[idx + 1];
str += str[0];
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, tempString.c_str());
break;
case CLEAR_INFO_LINE:
ui._infoFlag = true;
ui.clearInfo();
break;
case WALK_TO_CANIMATION: {
++str;
int animIndex = str[0] - 1;
// Save the current point in the script, since it might be intterupted by
// doing bg anims in the next call, so we need to know where to return to
_scriptCurrentIndex = (str + 1) - script.c_str();
if (_talkToAbort)
return;
break;
}
case REMOVE_ITEM_FROM_INVENTORY:
++str;
for (int idx = 0; idx < str[0]; ++idx)
tempString += str[idx + 1];
str += str[0];
inv.deleteItemFromInventory(tempString);
break;
case ENABLE_END_KEY:
ui._endKeyActive = true;
break;
case DISABLE_END_KEY:
ui._endKeyActive = false;
break;
default:
break;
}
++str;
} else {
// If the window isn't yet open, draw the window before printing starts
if (!ui._windowOpen && noTextYet) {
noTextYet = false;
drawInterface();
if (_talkTo != -1) {
screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, false, "Exit");
screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, false, "Up");
screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, false, "Down");
}
}
// If it's the first line, display the speaker
if (!line && _speaker >= 0 && _speaker < MAX_PEOPLE) {
// If the window is open, display the name directly on-screen.
// Otherwise, simply draw it on the back buffer
if (ui._windowOpen) {
screen.print(Common::Point(16, yp), TALK_FOREGROUND, inv._names[_speaker & 127].c_str());
} else {
screen.gPrint(Common::Point(16, yp - 1), TALK_FOREGROUND, inv._names[_speaker & 127].c_str());
openTalkWindow = true;
}
yp += 9;
}
// Find amound of text that will fit on the line
int width = 0, idx = 0;
do {
width += screen.charWidth(str[idx]);
} while (width < 298 && str[idx] && str[idx] != '{' && str[idx] < 128);
if (str[idx] || width >= 298) {
if (str[idx] < 128 && str[idx] != '{') {
--idx;
--charCount;
}
} else {
endStr = true;
}
// If word wrap is needed, find the start of the current word
if (width >= 298) {
while (str[idx] != ' ') {
--idx;
--charCount;
}
}
// Print the line
Common::String lineStr(str, str + idx);
// If the speaker indicates a description file, print it in yellow
if (_speaker != -1) {
if (ui._windowOpen) {
screen.print(Common::Point(16, yp), INV_FOREGROUND, lineStr.c_str());
} else {
screen.gPrint(Common::Point(16, yp - 1), INV_FOREGROUND, lineStr.c_str());
}
} else {
if (ui._windowOpen) {
screen.print(Common::Point(16, yp), COMMAND_FOREGROUND, lineStr.c_str());
}
else {
screen.gPrint(Common::Point(16, yp - 1), COMMAND_FOREGROUND, lineStr.c_str());
}
}
// Move to end of displayed line
str += idx;
// If line wrap occurred, then move to after the separating space between the words
if (str[0] < 128 && str[0] != '{')
++str;
yp += 9;
++line;
// Certain different conditions require a wait
if ((line == 4 && str[0] != SFX_COMMAND && str[0] != PAUSE && _speaker != -1) ||
(line == 5 && str[0] != PAUSE && _speaker != -1) ||
endStr) {
wait = 1;
}
switch (str[0]) {
case SWITCH_SPEAKER:
case ASSIGN_PORTRAIT_LOCATION:
case BANISH_WINDOW:
case IF_STATEMENT:
case ELSE_STATEMENT:
case END_IF_STATEMENT:
case GOTO_SCENE:
case CALL_TALK_FILE:
wait = 1;
break;
default:
break;
}
}
// Open window if it wasn't already open, and text has already been printed
if ((openTalkWindow && wait) || (openTalkWindow && str[0] >= 128 && str[0] != COMMAND_161)) {
if (!ui._windowStyle) {
screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
} else {
ui.summonWindow();
}
ui._windowOpen = true;
openTalkWindow = false;
}
if (wait) {
// Save the current point in the script, since it might be intterupted by
// doing bg anims in the next call, so we need to know where to return to
_scriptCurrentIndex = str - script.c_str();
// Handling pausing
if (!pauseFlag && charCount < 160)
charCount = 160;
wait = waitForMore(charCount);
if (wait == -1)
endStr = true;
// If a key was pressed to finish the window, see if further voice files should be skipped
if (wait >= 0 && wait < 254) {
if (str[0] == SFX_COMMAND)
str += 9;
}
// Clear the window unless the wait was due to a PAUSE command
if (!pauseFlag && wait != -1 && str[0] != SFX_COMMAND) {
if (!_talkStealth)
ui.clearWindow();
yp = CONTROLS_Y + 12;
charCount = line = 0;
}
pauseFlag = false;
}
} while (!_vm->shouldQuit() && !endStr);
if (wait != -1) {
for (int ssIndex = 0; ssIndex < (int)_savedSequences.size(); ++ssIndex) {
SequenceEntry &seq = _savedSequences[ssIndex];
Object &obj = scene._bgShapes[seq._objNum];
for (uint idx = 0; idx < seq._sequences.size(); ++idx)
obj._sequences[idx] = seq._sequences[idx];
obj._frameNumber = seq._frameNumber;
obj._seqTo = seq._seqTo;
}
pullSequence();
if (_speaker < 128)
clearTalking();
}
}
void Talk::clearTalking() {
// TODO
}
void Talk::setTalking(int speaker) {
// TODO
}
/**
* When the talk window has been displayed, waits a period of time proportional to
* the amount of text that's been displayed
*/
int Talk::waitForMore(int delay) {
Events &events = *_vm->_events;
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
Sound &sound = *_vm->_sound;
UserInterface &ui = *_vm->_ui;
CursorId oldCursor = events.getCursor();
int key2 = 254;
// Unless we're in stealth mode, show the appropriate cursor
if (!_talkStealth) {
events.setCursor(ui._lookScriptFlag ? MAGNIFY : ARROW);
}
do {
if (sound._speechOn && !*sound._soundIsOn)
people._portrait._frameNumber = -1;
scene.doBgAnim();
// If talkTo call was done via doBgAnim, abort out of talk quietly
if (_talkToAbort) {
key2 = -1;
events._released = true;
} else {
// See if there's been a button press
events.setButtonState();
if (events.kbHit()) {
Common::KeyState keyState = events.getKey();
if (keyState.keycode >= 32 && keyState.keycode < 128)
key2 = keyState.keycode;
}
if (_talkStealth) {
key2 = 254;
events._released = false;
}
}
// Count down the delay
if ((delay > 0 && !ui._invLookFlag && !ui._lookScriptFlag) || _talkStealth)
--delay;
// If there are voices playing, reset delay so that they keep playing
if (sound._voices == 2 && *sound._soundIsOn)
delay = 0;
} while (!_vm->shouldQuit() && key2 == 254 && (delay || (sound._voices == 2 && *sound._soundIsOn))
&& !events._released && !events._rightReleased);
// If voices was set 2 to indicate a voice file was place, then reset it back to 1
if (sound._voices == 2)
sound._voices = 1;
if (delay > 0 && sound._diskSoundPlaying)
sound.stopSndFuncPtr(0, 0);
// Adjust _talkStealth mode:
// mode 1 - It was by a pause without stealth being on before the pause, so reset back to 0
// mode 3 - It was set by a pause with stealth being on before the pause, to set it to active
// mode 0/2 (Inactive/active) No change
switch (_talkStealth) {
case 1:
_talkStealth = 0;
break;
case 2:
_talkStealth = 2;
break;
default:
break;
}
sound._speechOn = false;
events.setCursor(_talkToAbort ? ARROW : oldCursor);
events._pressed = events._released = false;
return key2;
}
} // End of namespace Sherlock