mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-05 09:49:14 +00:00
SHERLOCK: Implemented doScript and support methods
This commit is contained in:
parent
d45d167213
commit
96e04ab797
@ -144,7 +144,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f
|
||||
Common::String::format("%s%01d", baseName.c_str(), soundNumber) :
|
||||
Common::String::format("%s%02d", baseName.c_str(), soundNumber);
|
||||
|
||||
if (sound._voicesOn)
|
||||
if (sound._voices)
|
||||
sound.playSound(fname);
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,14 @@ bool Events::isCursorVisible() const {
|
||||
return CursorMan.isVisible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the mouse
|
||||
*/
|
||||
void Events::moveMouse(const Common::Point &pt) {
|
||||
g_system->warpMouse(pt.x, pt.y);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check for any pending events
|
||||
*/
|
||||
|
@ -72,6 +72,8 @@ public:
|
||||
|
||||
bool isCursorVisible() const;
|
||||
|
||||
void moveMouse(const Common::Point &pt);
|
||||
|
||||
void pollEvents();
|
||||
|
||||
void pollEventsAndWait();
|
||||
|
@ -366,4 +366,116 @@ void Inventory::doInvJF() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a shape from the scene to the player's inventory
|
||||
*/
|
||||
int Inventory::putNameInInventory(const Common::String &name) {
|
||||
Scene &scene = *_vm->_scene;
|
||||
int matches = 0;
|
||||
|
||||
for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
|
||||
Object &o = scene._bgShapes[idx];
|
||||
if (scumm_stricmp(name.c_str(), o._name.c_str()) == 0 && o._type != INVALID) {
|
||||
putItemInInventory(o);
|
||||
++matches;
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a specified item into the player's inventory If the item has a *PICKUP* use action,
|
||||
* then the item in the use action are added to the inventory.
|
||||
*/
|
||||
int Inventory::putItemInInventory(Object &obj) {
|
||||
Scene &scene = *_vm->_scene;
|
||||
int matches = 0;
|
||||
bool pickupFound = false;
|
||||
|
||||
if (obj._pickupFlag)
|
||||
_vm->setFlags(obj._pickupFlag);
|
||||
|
||||
for (int useNum = 0; useNum < 4; ++useNum) {
|
||||
if (scumm_stricmp(obj._use[useNum]._target.c_str(), "*PICKUP*") == 0) {
|
||||
pickupFound = true;
|
||||
|
||||
for (int namesNum = 0; namesNum < 4; ++namesNum) {
|
||||
for (uint bgNum = 0; bgNum < scene._bgShapes.size(); ++bgNum) {
|
||||
Object &bgObj = scene._bgShapes[bgNum];
|
||||
if (scumm_stricmp(obj._use[useNum]._names[namesNum].c_str(), bgObj._name.c_str()) == 0) {
|
||||
copyToInventory(bgObj);
|
||||
if (bgObj._pickupFlag)
|
||||
_vm->setFlags(bgObj._pickupFlag);
|
||||
|
||||
if (bgObj._type == ACTIVE_BG_SHAPE || bgObj._type == NO_SHAPE || bgObj._type == HIDE_SHAPE) {
|
||||
if (bgObj._imageFrame == nullptr || bgObj._frameNumber < 0)
|
||||
// No shape to erase, so flag as hidden
|
||||
bgObj._type = INVALID;
|
||||
else
|
||||
bgObj._type = REMOVE;
|
||||
} else if (bgObj._type == HIDDEN) {
|
||||
bgObj._type = INVALID;
|
||||
}
|
||||
|
||||
++matches;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pickupFound) {
|
||||
// No pickup item found, so add the passed item
|
||||
copyToInventory(obj);
|
||||
matches = 0;
|
||||
}
|
||||
|
||||
if (matches == 0) {
|
||||
if (!pickupFound)
|
||||
matches = 1;
|
||||
|
||||
if (obj._type == ACTIVE_BG_SHAPE || obj._type == NO_SHAPE || obj._type == HIDE_SHAPE) {
|
||||
if (obj._imageFrame == nullptr || obj._frameNumber < 0)
|
||||
// No shape to erase, so flag as hidden
|
||||
obj._type = INVALID;
|
||||
else
|
||||
obj._type = REMOVE;
|
||||
} else if (obj._type == HIDDEN) {
|
||||
obj._type = INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the passed object into the inventory
|
||||
*/
|
||||
void Inventory::copyToInventory(Object &obj) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a specified item from the player's inventory
|
||||
*/
|
||||
int Inventory::deleteItemFromInventory(const Common::String &name) {
|
||||
int invNum = -1;
|
||||
|
||||
for (int idx = 0; idx < (int)size() && invNum == -1; ++idx) {
|
||||
if (scumm_stricmp(name.c_str(), (*this)[idx]._name.c_str()) == 0)
|
||||
invNum = idx;
|
||||
}
|
||||
|
||||
if (invNum == -1)
|
||||
// Item not present
|
||||
return 0;
|
||||
|
||||
// Item found, so delete it
|
||||
remove_at(invNum);
|
||||
--_holdings;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/str-array.h"
|
||||
#include "sherlock/objects.h"
|
||||
#include "sherlock/resources.h"
|
||||
|
||||
namespace Sherlock {
|
||||
@ -59,6 +60,10 @@ struct InventoryItem {
|
||||
class Inventory : public Common::Array<InventoryItem> {
|
||||
private:
|
||||
SherlockEngine *_vm;
|
||||
|
||||
int putItemInInventory(Object &obj);
|
||||
|
||||
void copyToInventory(Object &obj);
|
||||
public:
|
||||
ImageFile *_invShapes[MAX_VISIBLE_INVENTORY];
|
||||
Common::StringArray _names;
|
||||
@ -90,6 +95,10 @@ public:
|
||||
void highlight(int index, byte color);
|
||||
|
||||
void doInvJF();
|
||||
|
||||
int putNameInInventory(const Common::String &name);
|
||||
|
||||
int deleteItemFromInventory(const Common::String &name);
|
||||
};
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
@ -61,6 +61,8 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) {
|
||||
_clearingThePortrait = false;
|
||||
_srcZone = _destZone = 0;
|
||||
_talkPics = nullptr;
|
||||
_portraitSide = 0;
|
||||
_speakerFlip = false;
|
||||
}
|
||||
|
||||
People::~People() {
|
||||
|
@ -77,6 +77,8 @@ public:
|
||||
Object _portrait;
|
||||
bool _clearingThePortrait;
|
||||
bool _allowWalkAbort;
|
||||
int _portraitSide;
|
||||
bool _speakerFlip;
|
||||
public:
|
||||
People(SherlockEngine *vm);
|
||||
~People();
|
||||
|
@ -89,7 +89,8 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) {
|
||||
_currentScene = -1;
|
||||
_goToScene = -1;
|
||||
_changes = false;
|
||||
_charPoint = _oldCharPoint = 0;
|
||||
_charPoint = 0;
|
||||
_oldCharPoint = 39;
|
||||
_keyboardInput = 0;
|
||||
_walkedInScene = false;
|
||||
_ongoingCans = 0;
|
||||
@ -118,7 +119,7 @@ void Scene::selectScene() {
|
||||
Events &events = *_vm->_events;
|
||||
People &people = *_vm->_people;
|
||||
Screen &screen = *_vm->_screen;
|
||||
Scripts &scripts = *_vm->_scripts;
|
||||
Talk &talk = *_vm->_talk;
|
||||
UserInterface &ui = *_vm->_ui;
|
||||
|
||||
// Reset fields
|
||||
@ -150,8 +151,8 @@ void Scene::selectScene() {
|
||||
|
||||
// If there were any scripst waiting to be run, but were interrupt by a running
|
||||
// canimation (probably the last scene's exit canim), clear the _scriptMoreFlag
|
||||
if (scripts._scriptMoreFlag == 3)
|
||||
scripts._scriptMoreFlag = 0;
|
||||
if (talk._scriptMoreFlag == 3)
|
||||
talk._scriptMoreFlag = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1053,7 +1054,6 @@ void Scene::doBgAnim() {
|
||||
Inventory &inv = *_vm->_inventory;
|
||||
People &people = *_vm->_people;
|
||||
Screen &screen = *_vm->_screen;
|
||||
Scripts &scripts = *_vm->_scripts;
|
||||
Sound &sound = *_vm->_sound;
|
||||
Talk &talk = *_vm->_talk;
|
||||
UserInterface &ui = *_vm->_ui;
|
||||
@ -1359,10 +1359,10 @@ void Scene::doBgAnim() {
|
||||
// Check if the method was called for calling a portrait, and a talk was
|
||||
// interrupting it. This talk file would not have been executed at the time,
|
||||
// since we needed to finish the 'doBgAnim' to finish clearing the portrait
|
||||
if (people._clearingThePortrait && scripts._scriptMoreFlag == 3) {
|
||||
if (people._clearingThePortrait && talk._scriptMoreFlag == 3) {
|
||||
// Reset the flags and call to talk
|
||||
people._clearingThePortrait = scripts._scriptMoreFlag = 0;
|
||||
talk.talkTo(scripts._scriptName);
|
||||
people._clearingThePortrait = talk._scriptMoreFlag = 0;
|
||||
talk.talkTo(talk._scriptName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,21 +26,16 @@
|
||||
namespace Sherlock {
|
||||
|
||||
Scripts::Scripts(SherlockEngine *vm): _vm(vm) {
|
||||
_scriptMoreFlag = 0;
|
||||
_scriptSaveIndex = 0;
|
||||
_scriptSelect = 0;
|
||||
}
|
||||
|
||||
void Scripts::doScript(const Common::String &str) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void Scripts::popStack() {
|
||||
/*
|
||||
ScriptEntry script = _scriptStack.pop();
|
||||
_scriptName = script._name;
|
||||
_scriptSaveIndex = script._index;
|
||||
// _scriptSaveIndex = script._index;
|
||||
_scriptSelect = script._select;
|
||||
_scriptMoreFlag = true;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,11 +40,7 @@ class Scripts {
|
||||
private:
|
||||
SherlockEngine *_vm;
|
||||
public:
|
||||
Common::Stack<ScriptEntry> _scriptStack;
|
||||
int _scriptMoreFlag;
|
||||
Common::String _scriptName;
|
||||
int _scriptSaveIndex;
|
||||
int _scriptSelect;
|
||||
|
||||
public:
|
||||
Scripts(SherlockEngine *vm);
|
||||
|
||||
|
@ -122,10 +122,10 @@ void SherlockEngine::sceneLoop() {
|
||||
while (!shouldQuit() && _scene->_goToScene == -1) {
|
||||
// See if a script needs to be completed from either a goto room code,
|
||||
// or a script that was interrupted by another script
|
||||
if (_scripts->_scriptMoreFlag == 1 || _scripts->_scriptMoreFlag == 3)
|
||||
_talk->talkTo(_scripts->_scriptName);
|
||||
if (_talk->_scriptMoreFlag == 1 || _talk->_scriptMoreFlag == 3)
|
||||
_talk->talkTo(_talk->_scriptName);
|
||||
else
|
||||
_scripts->_scriptMoreFlag = 0;
|
||||
_talk->_scriptMoreFlag = 0;
|
||||
|
||||
// Handle any input from the keyboard or mouse
|
||||
handleInput();
|
||||
|
@ -27,7 +27,8 @@ namespace Sherlock {
|
||||
Sound::Sound(SherlockEngine *vm): _vm(vm) {
|
||||
_soundOn = true;
|
||||
_musicOn = true;
|
||||
_voicesOn = true;
|
||||
_speechOn = true;
|
||||
_voices = 0;
|
||||
_playingEpilogue = false;
|
||||
_music = false;
|
||||
_digitized = false;
|
||||
@ -89,5 +90,9 @@ void Sound::freeSong() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void Sound::stopSndFuncPtr(int v1, int v2) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
@ -40,7 +40,8 @@ private:
|
||||
public:
|
||||
bool _soundOn;
|
||||
bool _musicOn;
|
||||
bool _voicesOn;
|
||||
bool _speechOn;
|
||||
int _voices;
|
||||
bool _playingEpilogue;
|
||||
bool _music;
|
||||
bool _digitized;
|
||||
@ -64,6 +65,7 @@ public:
|
||||
|
||||
void playMusic(const Common::String &name);
|
||||
void stopMusic();
|
||||
void stopSndFuncPtr(int v1, int v2);
|
||||
};
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
@ -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
|
||||
|
@ -33,16 +33,19 @@ namespace Sherlock {
|
||||
|
||||
#define MAX_TALK_SEQUENCES 11
|
||||
|
||||
struct SavedSequence {
|
||||
struct SequenceEntry {
|
||||
int _objNum;
|
||||
Common::Array<byte> _sequences;
|
||||
};
|
||||
|
||||
struct SequenceEntry : public SavedSequence {
|
||||
int _frameNumber;
|
||||
int _seqTo;
|
||||
};
|
||||
|
||||
struct ScriptStackEntry : public SequenceEntry {
|
||||
Common::String _name;
|
||||
int _currentIndex;
|
||||
int _select;
|
||||
};
|
||||
|
||||
struct Statement {
|
||||
Common::String _statement;
|
||||
Common::String _reply;
|
||||
@ -84,8 +87,8 @@ private:
|
||||
private:
|
||||
SherlockEngine *_vm;
|
||||
int _saveSeqNum;
|
||||
Common::Array<SavedSequence> _savedSequences;
|
||||
Common::Stack<SequenceEntry> _sequenceStack;
|
||||
Common::Stack<SequenceEntry> _savedSequences;
|
||||
Common::Stack<ScriptStackEntry> _scriptStack;
|
||||
Common::Array<Statement> _statements;
|
||||
TalkHistoryEntry _talkHistory[500];
|
||||
int _speaker;
|
||||
@ -95,17 +98,28 @@ private:
|
||||
int _talkStealth;
|
||||
int _talkToFlag;
|
||||
bool _moreTalkUp, _moreTalkDown;
|
||||
|
||||
int _scriptSaveIndex;
|
||||
int _scriptCurrentIndex;
|
||||
private:
|
||||
void stripVoiceCommands();
|
||||
void setTalkMap();
|
||||
|
||||
bool displayTalk(bool slamIt);
|
||||
|
||||
int talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt);
|
||||
|
||||
void doScript(const Common::String &script);
|
||||
|
||||
void clearTalking();
|
||||
void setTalking(int speaker);
|
||||
|
||||
int waitForMore(int delay);
|
||||
public:
|
||||
bool _talkToAbort;
|
||||
int _talkCounter;
|
||||
int _talkTo;
|
||||
int _scriptMoreFlag;
|
||||
Common::String _scriptName;
|
||||
public:
|
||||
Talk(SherlockEngine *vm);
|
||||
void setSequences(const byte *talkSequences, const byte *stillSequences,
|
||||
@ -127,7 +141,8 @@ public:
|
||||
void clearSequences();
|
||||
void pullSequence();
|
||||
void pushSequence(int speaker);
|
||||
bool isSequencesEmpty() const { return _sequenceStack.empty(); }
|
||||
void setSequence(int speaker);
|
||||
bool isSequencesEmpty() const { return _scriptStack.empty(); }
|
||||
};
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
@ -122,7 +122,6 @@ void UserInterface::handleInput() {
|
||||
People &people = *_vm->_people;
|
||||
Scene &scene = *_vm->_scene;
|
||||
Screen &screen = *_vm->_screen;
|
||||
Scripts &scripts = *_vm->_scripts;
|
||||
Talk &talk = *_vm->_talk;
|
||||
|
||||
if (_menuCounter)
|
||||
@ -148,7 +147,7 @@ void UserInterface::handleInput() {
|
||||
}
|
||||
|
||||
// Do button highlighting check
|
||||
if (!scripts._scriptMoreFlag) { // Don't if scripts are running
|
||||
if (!talk._scriptMoreFlag) { // Don't if scripts are running
|
||||
if (((events._rightPressed || events._rightReleased) && _helpStyle) ||
|
||||
(!_helpStyle && !_menuCounter)) {
|
||||
// Handle any default commands if we're in STD_MODE
|
||||
@ -532,6 +531,13 @@ void UserInterface::examine() {
|
||||
_vm->setFlags(inv[_selector]._lookFlag);
|
||||
}
|
||||
|
||||
if (_invLookFlag) {
|
||||
// Dont close the inventory window when starting an examine display, since it's
|
||||
// window will slide up to replace the inventory display
|
||||
_windowOpen = false;
|
||||
_menuMode = LOOK_MODE;
|
||||
}
|
||||
|
||||
if (!talk._talkToAbort) {
|
||||
if (!scene._cAnimFramePause)
|
||||
printObjectDesc(_cAnimStr, true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user