mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-26 12:48:16 +00:00
SHERLOCK: Beginnings of talk loading, added skeleton Scripts class
This commit is contained in:
parent
3149ce0204
commit
943d0a702f
@ -40,7 +40,7 @@ Inventory::Inventory(SherlockEngine *vm) : Common::Array<InventoryItem>(), _vm(v
|
||||
_holdings = 0;
|
||||
_oldFlag = 0;
|
||||
_invFlag = 0;
|
||||
_invMode = 0;
|
||||
_invMode = INVMODE_EXIT;
|
||||
}
|
||||
|
||||
Inventory::~Inventory() {
|
||||
@ -117,7 +117,7 @@ void Inventory::loadGraphics() {
|
||||
* and returns the numer that matches the passed name
|
||||
*/
|
||||
int Inventory::findInv(const Common::String &name) {
|
||||
for (int idx = 0; idx < size(); ++idx) {
|
||||
for (int idx = 0; idx < (int)size(); ++idx) {
|
||||
if (scumm_stricmp(name.c_str(), _names[idx].c_str()) == 0)
|
||||
return idx;
|
||||
}
|
||||
@ -219,25 +219,25 @@ void Inventory::drawInventory(int flag) {
|
||||
|
||||
// Draw the buttons
|
||||
screen.makeButton(Common::Rect(INVENTORY_POINTS[0][0], CONTROLS_Y1, INVENTORY_POINTS[0][1],
|
||||
CONTROLS_Y1 + 9), INVENTORY_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit");
|
||||
CONTROLS_Y1 + 10), INVENTORY_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit");
|
||||
screen.makeButton(Common::Rect(INVENTORY_POINTS[1][0], CONTROLS_Y1, INVENTORY_POINTS[1][1],
|
||||
CONTROLS_Y1 + 9), INVENTORY_POINTS[1][2] - screen.stringWidth("Look") / 2, "Look");
|
||||
CONTROLS_Y1 + 10), INVENTORY_POINTS[1][2] - screen.stringWidth("Look") / 2, "Look");
|
||||
screen.makeButton(Common::Rect(INVENTORY_POINTS[2][0], CONTROLS_Y1, INVENTORY_POINTS[2][1],
|
||||
CONTROLS_Y1 + 9), INVENTORY_POINTS[2][2] - screen.stringWidth("Use") / 2, "Use");
|
||||
CONTROLS_Y1 + 10), INVENTORY_POINTS[2][2] - screen.stringWidth("Use") / 2, "Use");
|
||||
screen.makeButton(Common::Rect(INVENTORY_POINTS[3][0], CONTROLS_Y1, INVENTORY_POINTS[3][1],
|
||||
CONTROLS_Y1 + 9), INVENTORY_POINTS[3][2] - screen.stringWidth("Give") / 2, "Give");
|
||||
CONTROLS_Y1 + 10), INVENTORY_POINTS[3][2] - screen.stringWidth("Give") / 2, "Give");
|
||||
screen.makeButton(Common::Rect(INVENTORY_POINTS[4][0], CONTROLS_Y1, INVENTORY_POINTS[4][1],
|
||||
CONTROLS_Y1 + 9), INVENTORY_POINTS[4][2], "^^");
|
||||
CONTROLS_Y1 + 10), INVENTORY_POINTS[4][2], "^^");
|
||||
screen.makeButton(Common::Rect(INVENTORY_POINTS[5][0], CONTROLS_Y1, INVENTORY_POINTS[5][1],
|
||||
CONTROLS_Y1 + 9), INVENTORY_POINTS[5][2], "^");
|
||||
CONTROLS_Y1 + 10), INVENTORY_POINTS[5][2], "^");
|
||||
screen.makeButton(Common::Rect(INVENTORY_POINTS[6][0], CONTROLS_Y1, INVENTORY_POINTS[6][1],
|
||||
CONTROLS_Y1 + 9), INVENTORY_POINTS[6][2], "_");
|
||||
CONTROLS_Y1 + 10), INVENTORY_POINTS[6][2], "_");
|
||||
screen.makeButton(Common::Rect(INVENTORY_POINTS[7][0], CONTROLS_Y1, INVENTORY_POINTS[7][1],
|
||||
CONTROLS_Y1 + 9), INVENTORY_POINTS[7][2], "__");
|
||||
CONTROLS_Y1 + 10), INVENTORY_POINTS[7][2], "__");
|
||||
|
||||
if (tempFlag == 128)
|
||||
flag = 1;
|
||||
_invMode = flag;
|
||||
_invMode = (InvMode)flag;
|
||||
|
||||
if (flag) {
|
||||
ui._oldKey = INVENTORY_COMMANDS[flag];
|
||||
@ -334,7 +334,25 @@ void Inventory::doInvLite(int index, byte color) {
|
||||
}
|
||||
|
||||
void Inventory::doInvJF() {
|
||||
// TODO
|
||||
Screen &screen = *_vm->_screen;
|
||||
Talk &talk = *_vm->_talk;
|
||||
UserInterface &ui = *_vm->_ui;
|
||||
|
||||
ui._invLookFlag = true;
|
||||
freeInv();
|
||||
|
||||
ui._infoFlag = true;
|
||||
ui.clearInfo();
|
||||
|
||||
screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
|
||||
Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
|
||||
ui.examine();
|
||||
|
||||
if (!talk._talkToAbort) {
|
||||
screen._backBuffer2.blitFrom((*ui._controlPanel)[0]._frame,
|
||||
Common::Point(0, CONTROLS_Y));
|
||||
loadInv();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
@ -32,6 +32,19 @@ namespace Sherlock {
|
||||
|
||||
#define MAX_VISIBLE_INVENTORY 6
|
||||
|
||||
enum InvMode {
|
||||
INVMODE_EXIT = 0,
|
||||
INVMODE_LOOK = 1,
|
||||
INVMODE_USE = 2,
|
||||
INVMODE_GIVE = 3,
|
||||
INVMODE_FIRST = 4,
|
||||
INVMODE_PREVIOUS = 5,
|
||||
INVMODE_NEXT = 6,
|
||||
INVMODE_LAST = 7,
|
||||
INVMODE_INVALID = 8,
|
||||
INVMODE_USE55 = 255
|
||||
};
|
||||
|
||||
struct InventoryItem {
|
||||
int _requiredFlag;
|
||||
Common::String _name;
|
||||
@ -50,7 +63,7 @@ public:
|
||||
ImageFile *_invShapes[MAX_VISIBLE_INVENTORY];
|
||||
Common::StringArray _names;
|
||||
bool _invGraphicsLoaded;
|
||||
int _invMode;
|
||||
InvMode _invMode;
|
||||
int _invIndex;
|
||||
int _holdings;
|
||||
void freeGraphics();
|
||||
|
@ -18,6 +18,7 @@ MODULE_OBJS = \
|
||||
resources.o \
|
||||
scene.o \
|
||||
screen.o \
|
||||
scripts.o \
|
||||
sherlock.o \
|
||||
sound.o \
|
||||
talk.o \
|
||||
|
@ -52,17 +52,24 @@ enum {
|
||||
|
||||
class SherlockEngine;
|
||||
|
||||
class Person: public Sprite {
|
||||
public:
|
||||
Person() : Sprite() {}
|
||||
|
||||
Common::String _portrait;
|
||||
};
|
||||
|
||||
class People {
|
||||
private:
|
||||
SherlockEngine *_vm;
|
||||
Sprite _data[MAX_PEOPLE];
|
||||
Sprite &_player;
|
||||
Person _data[MAX_PEOPLE];
|
||||
bool _walkLoaded;
|
||||
int _oldWalkSequence;
|
||||
int _srcZone, _destZone;
|
||||
public:
|
||||
Common::Point _walkDest;
|
||||
Common::Stack<Common::Point> _walkTo;
|
||||
Person &_player;
|
||||
bool _holmesOn;
|
||||
bool _portraitLoaded;
|
||||
Object _portrait;
|
||||
@ -72,7 +79,7 @@ public:
|
||||
People(SherlockEngine *vm);
|
||||
~People();
|
||||
|
||||
Sprite &operator[](PeopleId id) { return _data[id]; }
|
||||
Person &operator[](PeopleId id) { return _data[id]; }
|
||||
|
||||
bool isHolmesActive() const { return _walkLoaded && _holmesOn; }
|
||||
|
||||
|
@ -99,7 +99,6 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) {
|
||||
_hsavedPos = Common::Point(-1, -1);
|
||||
_hsavedFs = -1;
|
||||
_cAnimFramePause = 0;
|
||||
_invMode = INVMODE_0;
|
||||
_restoreFlag = false;
|
||||
_invLookFlag = false;
|
||||
_lookHelp = false;
|
||||
@ -119,6 +118,7 @@ void Scene::selectScene() {
|
||||
Events &events = *_vm->_events;
|
||||
People &people = *_vm->_people;
|
||||
Screen &screen = *_vm->_screen;
|
||||
Scripts &scripts = *_vm->_scripts;
|
||||
UserInterface &ui = *_vm->_ui;
|
||||
|
||||
// Reset fields
|
||||
@ -150,8 +150,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 (_vm->_scriptMoreFlag == 3)
|
||||
_vm->_scriptMoreFlag = 0;
|
||||
if (scripts._scriptMoreFlag == 3)
|
||||
scripts._scriptMoreFlag = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1050,8 +1050,10 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
|
||||
*/
|
||||
void Scene::doBgAnim() {
|
||||
Events &events = *_vm->_events;
|
||||
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;
|
||||
@ -1079,7 +1081,7 @@ void Scene::doBgAnim() {
|
||||
|
||||
// Check for setting magnifying glass cursor
|
||||
if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) {
|
||||
if (_invMode == INVMODE_1) {
|
||||
if (inv._invMode == INVMODE_LOOK) {
|
||||
// Only show Magnifying glass cursor if it's not on the inventory command line
|
||||
if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13))
|
||||
events.setCursor(MAGNIFY);
|
||||
@ -1357,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 && _vm->_scriptMoreFlag == 3) {
|
||||
if (people._clearingThePortrait && scripts._scriptMoreFlag == 3) {
|
||||
// Reset the flags and call to talk
|
||||
people._clearingThePortrait = _vm->_scriptMoreFlag = 0;
|
||||
talk.talkTo(_vm->_scriptName);
|
||||
people._clearingThePortrait = scripts._scriptMoreFlag = 0;
|
||||
talk.talkTo(scripts._scriptName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,14 +35,6 @@ namespace Sherlock {
|
||||
#define MAX_ZONES 40
|
||||
#define INFO_LINE 140
|
||||
|
||||
enum InvMode {
|
||||
INVMODE_0 = 0,
|
||||
INVMODE_1 = 1,
|
||||
INVMODE_2 = 2,
|
||||
INVMODE_3 = 3,
|
||||
INVMODE_255 = 255
|
||||
};
|
||||
|
||||
class SherlockEngine;
|
||||
|
||||
struct BgFileHeader {
|
||||
@ -94,9 +86,7 @@ class Scene {
|
||||
private:
|
||||
SherlockEngine *_vm;
|
||||
Common::String _rrmName;
|
||||
InvMode _invMode;
|
||||
int _selector;
|
||||
bool _invLookFlag;
|
||||
bool _lookHelp;
|
||||
|
||||
bool loadScene(const Common::String &filename);
|
||||
@ -149,6 +139,7 @@ public:
|
||||
bool _doBgAnimDone;
|
||||
int _tempFadeStyle;
|
||||
int _cAnimFramePause;
|
||||
bool _invLookFlag;
|
||||
public:
|
||||
Scene(SherlockEngine *vm);
|
||||
~Scene();
|
||||
|
@ -468,4 +468,15 @@ void Screen::makePanel(const Common::Rect &r) {
|
||||
_backBuffer->hLine(r.left + 1, r.bottom - 2, r.right - 1, BUTTON_BOTTOM);
|
||||
}
|
||||
|
||||
void Screen::setDisplayBounds(const Common::Rect &r) {
|
||||
// TODO: See if needed
|
||||
}
|
||||
void Screen::resetDisplayBounds() {
|
||||
setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
|
||||
}
|
||||
|
||||
Common::Rect Screen::getDisplayBounds() {
|
||||
return Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
|
||||
}
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
@ -120,6 +120,10 @@ public:
|
||||
void buttonPrint(const Common::Point &pt, byte color, bool slamIt, const Common::String &str);
|
||||
|
||||
void makePanel(const Common::Rect &r);
|
||||
|
||||
void setDisplayBounds(const Common::Rect &r);
|
||||
void resetDisplayBounds();
|
||||
Common::Rect getDisplayBounds();
|
||||
};
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
35
engines/sherlock/scripts.cpp
Normal file
35
engines/sherlock/scripts.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sherlock/scripts.h"
|
||||
#include "sherlock/sherlock.h"
|
||||
|
||||
namespace Sherlock {
|
||||
|
||||
Scripts::Scripts(SherlockEngine *vm): _vm(vm) {
|
||||
_scriptMoreFlag = 0;
|
||||
_scriptSaveIndex = 0;
|
||||
_scriptSelect = 0;
|
||||
_abortFlag = false;
|
||||
}
|
||||
|
||||
} // End of namespace Sherlock
|
48
engines/sherlock/scripts.h
Normal file
48
engines/sherlock/scripts.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHERLOCK_SCRIPTS_H
|
||||
#define SHERLOCK_SCRIPTS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
|
||||
namespace Sherlock {
|
||||
|
||||
class SherlockEngine;
|
||||
|
||||
class Scripts {
|
||||
private:
|
||||
SherlockEngine *_vm;
|
||||
public:
|
||||
int _scriptMoreFlag;
|
||||
Common::String _scriptName;
|
||||
int _scriptSaveIndex;
|
||||
int _scriptSelect;
|
||||
bool _abortFlag;
|
||||
public:
|
||||
Scripts(SherlockEngine *vm);
|
||||
};
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
||||
#endif
|
@ -39,6 +39,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam
|
||||
_res = nullptr;
|
||||
_scene = nullptr;
|
||||
_screen = nullptr;
|
||||
_scripts = nullptr;
|
||||
_sound = nullptr;
|
||||
_talk = nullptr;
|
||||
_ui = nullptr;
|
||||
@ -47,7 +48,6 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam
|
||||
_loadingSavedGame = false;
|
||||
_onChessboard = false;
|
||||
_slowChess = false;
|
||||
_scriptMoreFlag = 0;
|
||||
}
|
||||
|
||||
SherlockEngine::~SherlockEngine() {
|
||||
@ -58,6 +58,7 @@ SherlockEngine::~SherlockEngine() {
|
||||
delete _people;
|
||||
delete _scene;
|
||||
delete _screen;
|
||||
delete _scripts;
|
||||
delete _sound;
|
||||
delete _talk;
|
||||
delete _ui;
|
||||
@ -82,6 +83,7 @@ void SherlockEngine::initialize() {
|
||||
_people = new People(this);
|
||||
_scene = new Scene(this);
|
||||
_screen = new Screen(this);
|
||||
_scripts = new Scripts(this);
|
||||
_sound = new Sound(this);
|
||||
_talk = new Talk(this);
|
||||
_ui = new UserInterface(this);
|
||||
@ -120,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 (_scriptMoreFlag == 1 || _scriptMoreFlag == 3)
|
||||
_talk->talkTo(_scriptName);
|
||||
if (_scripts->_scriptMoreFlag == 1 || _scripts->_scriptMoreFlag == 3)
|
||||
_talk->talkTo(_scripts->_scriptName);
|
||||
else
|
||||
_scriptMoreFlag = 0;
|
||||
_scripts->_scriptMoreFlag = 0;
|
||||
|
||||
// Handle any input from the keyboard or mouse
|
||||
handleInput();
|
||||
@ -171,4 +173,8 @@ void SherlockEngine::setFlags(int flagNum) {
|
||||
_scene->checkSceneFlags(true);
|
||||
}
|
||||
|
||||
void SherlockEngine::freeSaveGameList() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
} // End of namespace Comet
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "sherlock/resources.h"
|
||||
#include "sherlock/scene.h"
|
||||
#include "sherlock/screen.h"
|
||||
#include "sherlock/scripts.h"
|
||||
#include "sherlock/sound.h"
|
||||
#include "sherlock/talk.h"
|
||||
#include "sherlock/user_interface.h"
|
||||
@ -89,6 +90,7 @@ public:
|
||||
Resources *_res;
|
||||
Scene *_scene;
|
||||
Screen *_screen;
|
||||
Scripts *_scripts;
|
||||
Sound *_sound;
|
||||
Talk *_talk;
|
||||
UserInterface *_ui;
|
||||
@ -104,8 +106,6 @@ public:
|
||||
Common::Array<Common::Point> _map; // Map locations for each scene
|
||||
bool _onChessboard;
|
||||
bool _slowChess;
|
||||
int _scriptMoreFlag;
|
||||
Common::String _scriptName;
|
||||
public:
|
||||
SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
|
||||
virtual ~SherlockEngine();
|
||||
@ -125,6 +125,8 @@ public:
|
||||
bool readFlags(int flagNum);
|
||||
|
||||
void setFlags(int flagNum);
|
||||
|
||||
void freeSaveGameList();
|
||||
};
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
@ -25,13 +25,238 @@
|
||||
|
||||
namespace Sherlock {
|
||||
|
||||
/**
|
||||
* Load the data for a single statement within a talk file
|
||||
*/
|
||||
void Statement::synchronize(Common::SeekableReadStream &s, bool voices) {
|
||||
int length;
|
||||
|
||||
length = s.readUint16LE();
|
||||
for (int idx = 0; idx < length; ++idx)
|
||||
_statement += (char)s.readByte();
|
||||
|
||||
length = s.readUint16LE();
|
||||
for (int idx = 0; idx < length; ++idx)
|
||||
_reply += (char)s.readByte();
|
||||
|
||||
// If we don't have digital sound, we'll need to strip out voice commands from reply
|
||||
if (!voices) {
|
||||
// Scan for a 140 byte, which indicates playing a sound
|
||||
for (uint idx = 0; idx < _reply.size(); ++idx) {
|
||||
if (_reply[idx] == 140) {
|
||||
// Replace instruction character with a space, and delete the
|
||||
// rest of the name following it
|
||||
_reply = Common::String(_reply.c_str(), _reply.c_str() + idx) + " " +
|
||||
Common::String(_reply.c_str() + 9);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the last character of the reply is not a space from the prior
|
||||
// conversion loop, to avoid any issues with the space ever causing a page
|
||||
// wrap, and ending up displaying another empty page
|
||||
while (_reply.lastChar() == ' ')
|
||||
_reply.deleteLastChar();
|
||||
}
|
||||
|
||||
length = s.readUint16LE();
|
||||
for (int idx = 0; idx < length; ++idx)
|
||||
_linkFile += (char)s.readByte();
|
||||
|
||||
length = s.readUint16LE();
|
||||
for (int idx = 0; idx < length; ++idx)
|
||||
_voiceFile += (char)s.readByte();
|
||||
|
||||
_required.resize(s.readByte());
|
||||
_modified.resize(s.readByte());
|
||||
|
||||
// Read in flag required/modified data
|
||||
for (uint idx = 0; idx < _required.size(); ++idx)
|
||||
_required[idx] = s.readUint16LE();
|
||||
for (uint idx = 0; idx < _modified.size(); ++idx)
|
||||
_modified[idx] = s.readUint16LE();
|
||||
|
||||
_portraitSide = s.readByte();
|
||||
_quotient = s.readUint16LE();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
Talk::Talk(SherlockEngine *vm): _vm(vm) {
|
||||
_talkCounter = 0;
|
||||
_talkToAbort = false;
|
||||
_saveSeqNum = 0;
|
||||
_speaker = 0;
|
||||
_talkIndex = 0;
|
||||
_talkTo = 0;
|
||||
}
|
||||
|
||||
void Talk::talkTo(const Common::String &name) {
|
||||
// TODO
|
||||
/**
|
||||
* Called when either an NPC initiates a conversation or for inventory item
|
||||
* descriptions. It opens up a description window similar to how 'talk' does,
|
||||
* but shows a 'reply' directly instead of waiting for a statement option.
|
||||
*/
|
||||
void Talk::talkTo(const Common::String &filename) {
|
||||
Events &events = *_vm->_events;
|
||||
Inventory &inv = *_vm->_inventory;
|
||||
People &people = *_vm->_people;
|
||||
Scene &scene = *_vm->_scene;
|
||||
Screen &screen = *_vm->_screen;
|
||||
Scripts &scripts = *_vm->_scripts;
|
||||
Talk &talk = *_vm->_talk;
|
||||
UserInterface &ui = *_vm->_ui;
|
||||
Common::Rect savedBounds = screen.getDisplayBounds();
|
||||
|
||||
if (filename.empty())
|
||||
// No filename passed, so exit
|
||||
return;
|
||||
|
||||
// If there any canimations currently running, or a portrait is being cleared,
|
||||
// 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;
|
||||
|
||||
// Flag the selection, since we don't yet know which statement yet
|
||||
scripts._scriptSelect = 100;
|
||||
scripts._scriptMoreFlag = 3;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the ui mode temporarily and switch to talk mode
|
||||
int savedMode = ui._menuMode;
|
||||
ui._menuMode = TALK_MODE;
|
||||
|
||||
// Turn on the Exit option
|
||||
ui._endKeyActive = true;
|
||||
|
||||
if (people[AL]._walkCount || people._walkTo.size() > 0) {
|
||||
// Only interrupt if an action if trying to do an action, and not just
|
||||
// if the player is walking around the scene
|
||||
if (people._allowWalkAbort)
|
||||
scripts._abortFlag = true;
|
||||
|
||||
people.gotoStand(people._player);
|
||||
}
|
||||
|
||||
if (talk._talkToAbort)
|
||||
return;
|
||||
|
||||
talk.freeTalkVars();
|
||||
|
||||
// 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];
|
||||
for (uint idx2 = 0; idx2 < _savedSequences.size(); ++idx2)
|
||||
scene._bgShapes[ss._objNum]._sequences[idx2] = ss._sequences[idx2];
|
||||
|
||||
// Reset the object's frame to the beginning of the sequence
|
||||
scene._bgShapes[ss._objNum]._frameNumber = 0;
|
||||
}
|
||||
}
|
||||
|
||||
while (_sequenceStack.empty())
|
||||
pullSequence();
|
||||
|
||||
// Restore any pressed button
|
||||
if (!ui._windowOpen && savedMode != STD_MODE)
|
||||
ui.restoreButton(savedMode - 1);
|
||||
|
||||
// Clear the ui counter so that anything displayed on the info line
|
||||
// before the window was opened isn't cleared
|
||||
ui._menuCounter = 0;
|
||||
|
||||
// Close any previous window before starting the talk
|
||||
if (ui._windowOpen) {
|
||||
switch (savedMode) {
|
||||
case LOOK_MODE:
|
||||
events.setCursor(ARROW);
|
||||
|
||||
if (ui._invLookFlag) {
|
||||
screen.resetDisplayBounds();
|
||||
ui.drawInterface(2);
|
||||
}
|
||||
|
||||
ui.banishWindow();
|
||||
ui._windowBounds.top = CONTROLS_Y1;
|
||||
ui._temp = ui._oldTemp = ui._lookHelp = 0;
|
||||
ui._menuMode = STD_MODE;
|
||||
events._pressed = events._released = events._oldButtons = 0;
|
||||
ui._invLookFlag = false;
|
||||
break;
|
||||
|
||||
case TALK_MODE:
|
||||
if (_speaker < 128)
|
||||
clearTalking();
|
||||
if (_talkCounter)
|
||||
return;
|
||||
|
||||
// If we were in inventory mode looking at an object, restore the
|
||||
// back buffers before closing the window, so we get the ui restored
|
||||
// rather than the inventory again
|
||||
if (ui._invLookFlag) {
|
||||
screen.resetDisplayBounds();
|
||||
ui.drawInterface(2);
|
||||
ui._invLookFlag = ui._lookScriptFlag = false;
|
||||
}
|
||||
|
||||
ui.banishWindow();
|
||||
ui._windowBounds.top = CONTROLS_Y1;
|
||||
scripts._abortFlag = true;
|
||||
break;
|
||||
|
||||
case INV_MODE:
|
||||
case USE_MODE:
|
||||
case GIVE_MODE:
|
||||
inv.freeInv();
|
||||
if (ui._invLookFlag) {
|
||||
screen.resetDisplayBounds();
|
||||
ui.drawInterface(2);
|
||||
ui._invLookFlag = ui._lookScriptFlag = false;
|
||||
}
|
||||
|
||||
ui._infoFlag = true;
|
||||
ui.clearInfo();
|
||||
ui.banishWindow(false);
|
||||
ui._key = -1;
|
||||
break;
|
||||
|
||||
case FILES_MODE:
|
||||
ui.banishWindow(true);
|
||||
ui._windowBounds.top = CONTROLS_Y1;
|
||||
scripts._abortFlag = true;
|
||||
break;
|
||||
|
||||
case SETUP_MODE:
|
||||
ui.banishWindow(true);
|
||||
ui._windowBounds.top = CONTROLS_Y1;
|
||||
ui._temp = ui._oldTemp = ui._lookHelp = ui._invLookFlag = false;
|
||||
ui._menuMode = STD_MODE;
|
||||
events._pressed = events._released = events._oldButtons = 0;
|
||||
scripts._abortFlag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
screen.resetDisplayBounds();
|
||||
events._pressed = events._released = false;
|
||||
loadTalkFile(filename);
|
||||
ui._selector = ui._oldSelector = ui._key = ui._oldKey = -1;
|
||||
|
||||
// Find the first statement that has the correct flags
|
||||
int select = -1;
|
||||
for (uint idx = 0; idx < _statements.size() && select == -1; ++idx) {
|
||||
/*
|
||||
if (!_talkMap[idx])
|
||||
select = _talkIndex = idx;
|
||||
*/
|
||||
}
|
||||
|
||||
// TODOa
|
||||
}
|
||||
|
||||
void Talk::talk(int objNum) {
|
||||
@ -45,5 +270,67 @@ void Talk::freeTalkVars() {
|
||||
_statements.clear();
|
||||
}
|
||||
|
||||
void Talk::pullSequence() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the talk file 'talk.tlk' and searches the index for the specified
|
||||
* conversation. If found, the data for that conversation is loaded
|
||||
*/
|
||||
void Talk::loadTalkFile(const Common::String &filename) {
|
||||
People &people = *_vm->_people;
|
||||
Resources &res = *_vm->_res;
|
||||
Sound &sound = *_vm->_sound;
|
||||
|
||||
// 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)) {
|
||||
_talkTo = idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *chP = strchr(filename.c_str(), '.');
|
||||
Common::String talkFile = !chP ? filename + ".tlk" :
|
||||
Common::String(filename.c_str(), chP) + ".tlk";
|
||||
|
||||
// Open the talk file for reading
|
||||
Common::SeekableReadStream *talkStream = res.load(talkFile);
|
||||
talkStream->skip(2); // Skip talk file version num
|
||||
|
||||
_statements.resize(talkStream->readByte());
|
||||
for (uint idx = 0; idx < _statements.size(); ++idx)
|
||||
_statements[idx].synchronize(*talkStream, sound._voicesOn);
|
||||
|
||||
delete talkStream;
|
||||
setTalkMap();
|
||||
}
|
||||
|
||||
void Talk::clearTalking() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Form a translate table from the loaded statements from a talk file
|
||||
*/
|
||||
void Talk::setTalkMap() {
|
||||
int statementNum = 0;
|
||||
|
||||
for (uint sIdx = 0; sIdx < _statements.size(); ++sIdx) {
|
||||
Statement &statement = _statements[sIdx];
|
||||
|
||||
// Set up talk map entry for the statement
|
||||
bool valid = true;
|
||||
for (uint idx = 0; idx < statement._required.size(); ++idx) {
|
||||
if (!_vm->readFlags(statement._required[idx]))
|
||||
valid = false;
|
||||
}
|
||||
|
||||
statement._talkMap = valid ? statementNum++ : -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
@ -25,31 +25,58 @@
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
namespace Sherlock {
|
||||
|
||||
struct TalkHistoryEntry {
|
||||
private:
|
||||
int _data[2];
|
||||
public:
|
||||
TalkHistoryEntry() { _data[0] = _data[1] = 0; }
|
||||
struct SavedSequence {
|
||||
int _objNum;
|
||||
Common::Array<byte> _sequences;
|
||||
};
|
||||
|
||||
int &operator[](int idx) { return _data[idx]; }
|
||||
struct Statement {
|
||||
Common::String _statement;
|
||||
Common::String _reply;
|
||||
Common::String _linkFile;
|
||||
Common::String _voiceFile;
|
||||
Common::Array<int> _required;
|
||||
Common::Array<int> _modified;
|
||||
int _portraitSide;
|
||||
int _quotient;
|
||||
int _talkMap;
|
||||
|
||||
void synchronize(Common::SeekableReadStream &s, bool voices);
|
||||
};
|
||||
|
||||
class SherlockEngine;
|
||||
|
||||
class Talk {
|
||||
|
||||
private:
|
||||
SherlockEngine *_vm;
|
||||
int _saveSeqNum;
|
||||
Common::Array<SavedSequence> _savedSequences;
|
||||
Common::Stack<int> _sequenceStack;
|
||||
Common::Array<Statement> _statements;
|
||||
int _speaker;
|
||||
int _talkIndex;
|
||||
int _talkTo;
|
||||
|
||||
void pullSequence();
|
||||
|
||||
void loadTalkFile(const Common::String &filename);
|
||||
|
||||
void clearTalking();
|
||||
|
||||
void setTalkMap();
|
||||
public:
|
||||
Common::Array<TalkHistoryEntry> _statements;
|
||||
bool _talkToAbort;
|
||||
int _talkCounter;
|
||||
public:
|
||||
Talk(SherlockEngine *vm);
|
||||
|
||||
void talkTo(const Common::String &name);
|
||||
void talkTo(const Common::String &filename);
|
||||
|
||||
void talk(int objNum);
|
||||
|
||||
|
@ -43,14 +43,14 @@ const int MENU_POINTS[12][4] = {
|
||||
|
||||
// Inventory control locations */
|
||||
const int INVENTORY_POINTS[8][3] = {
|
||||
{ 4, 50, 28 },
|
||||
{ 52, 99, 76 },
|
||||
{ 101, 140, 122 },
|
||||
{ 142, 187, 165 },
|
||||
{ 189, 219, 197 },
|
||||
{ 221, 251, 233 },
|
||||
{ 253, 283, 265 },
|
||||
{ 285, 315, 293 }
|
||||
{ 4, 50, 29 },
|
||||
{ 52, 99, 77 },
|
||||
{ 101, 140, 123 },
|
||||
{ 142, 187, 166 },
|
||||
{ 189, 219, 198 },
|
||||
{ 221, 251, 234 },
|
||||
{ 253, 283, 266 },
|
||||
{ 285, 315, 294 }
|
||||
};
|
||||
|
||||
const char COMMANDS[13] = "LMTPOCIUGJFS";
|
||||
@ -85,6 +85,7 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) {
|
||||
_windowStyle = 1; // Sliding windows
|
||||
_find = 0;
|
||||
_oldUse = 0;
|
||||
_endKeyActive = true;
|
||||
}
|
||||
|
||||
UserInterface::~UserInterface() {
|
||||
@ -101,12 +102,15 @@ void UserInterface::reset() {
|
||||
/**
|
||||
* Draw the user interface onto the screen's back buffers
|
||||
*/
|
||||
void UserInterface::drawInterface() {
|
||||
void UserInterface::drawInterface(int bufferNum) {
|
||||
Screen &screen = *_vm->_screen;
|
||||
|
||||
screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK);
|
||||
screen._backBuffer1.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y));
|
||||
screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y));
|
||||
if (bufferNum & 1)
|
||||
screen._backBuffer1.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y));
|
||||
if (bufferNum & 2)
|
||||
screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y));
|
||||
if (bufferNum == 3)
|
||||
screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,6 +122,7 @@ 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)
|
||||
@ -143,7 +148,7 @@ void UserInterface::handleInput() {
|
||||
}
|
||||
|
||||
// Do button highlighting check
|
||||
if (!_vm->_scriptMoreFlag) { // Don't if scripts are running
|
||||
if (!scripts._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
|
||||
@ -276,7 +281,7 @@ void UserInterface::handleInput() {
|
||||
case GIVE_MODE:
|
||||
case INV_MODE:
|
||||
if (inv._invMode == 1 || inv._invMode == 2 || inv._invMode == 3) {
|
||||
if (pt.y < CONTROLS_Y)
|
||||
if (pt.y > CONTROLS_Y)
|
||||
lookInv();
|
||||
else
|
||||
lookScreen(pt);
|
||||
@ -713,7 +718,7 @@ void UserInterface::doInvControl() {
|
||||
screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), colors[1], true, "Look");
|
||||
screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), colors[1], true, "Use");
|
||||
screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), colors[1], true, "Give");
|
||||
inv._invMode = found;
|
||||
inv._invMode = (InvMode)found;
|
||||
_selector = -1;
|
||||
}
|
||||
|
||||
@ -734,7 +739,11 @@ void UserInterface::doInvControl() {
|
||||
bool flag = false;
|
||||
if (inv._invMode == 1 || inv._invMode == 2 || inv._invMode == 3) {
|
||||
Common::Rect r(15, CONTROLS_Y1 + 11, 314, SHERLOCK_SCREEN_HEIGHT - 2);
|
||||
flag = (_selector < inv._holdings);
|
||||
if (r.contains(mousePos)) {
|
||||
_selector = (mousePos.x - 6) / 52 + inv._invIndex;
|
||||
if (_selector < inv._holdings)
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag && mousePos.y >(CONTROLS_Y1 + 11))
|
||||
@ -753,13 +762,13 @@ void UserInterface::doInvControl() {
|
||||
int temp = inv._invMode;
|
||||
|
||||
const char *chP = strchr(INVENTORY_COMMANDS, _key);
|
||||
inv._invMode = !chP ? 8 : chP - INVENTORY_COMMANDS;
|
||||
inv._invMode = !chP ? INVMODE_INVALID : (InvMode)(chP - INVENTORY_COMMANDS);
|
||||
inv.invCommands(true);
|
||||
|
||||
inv._invMode = temp;
|
||||
inv._invMode = (InvMode)temp;
|
||||
_keyboardInput = true;
|
||||
if (_key == 'E')
|
||||
inv._invMode = STD_MODE;
|
||||
inv._invMode = INVMODE_EXIT;
|
||||
_selector = -1;
|
||||
} else {
|
||||
_selector = -1;
|
||||
@ -789,11 +798,11 @@ void UserInterface::doInvControl() {
|
||||
events.clearEvents();
|
||||
events.setCursor(ARROW);
|
||||
} else if ((found == 1 && events._released) || (_key == 'L')) {
|
||||
inv._invMode = 1;
|
||||
inv._invMode = INVMODE_LOOK;
|
||||
} else if ((found == 2 && events._released) || (_key == 'U')) {
|
||||
inv._invMode = 2;
|
||||
inv._invMode = INVMODE_USE;
|
||||
} else if ((found == 3 && events._released) || (_key == 'G')) {
|
||||
inv._invMode = 3;
|
||||
inv._invMode = INVMODE_GIVE;
|
||||
} else if (((found == 4 && events._released) || _key == ',') && inv._invIndex) {
|
||||
if (inv._invIndex >= 6)
|
||||
inv._invIndex -= 6;
|
||||
@ -855,7 +864,8 @@ void UserInterface::doInvControl() {
|
||||
// If it's -1, then no inventory item is highlighted yet. Otherwise,
|
||||
// an object in the scene has been clicked.
|
||||
|
||||
if (_selector != -1 && inv._invMode == 1 && mousePos.y >(CONTROLS_Y1 + 11))
|
||||
if (_selector != -1 && inv._invMode == INVMODE_LOOK
|
||||
&& mousePos.y >(CONTROLS_Y1 + 11))
|
||||
inv.doInvJF();
|
||||
|
||||
if (talk._talkToAbort)
|
||||
@ -879,7 +889,7 @@ void UserInterface::doInvControl() {
|
||||
inv.putInv(1);
|
||||
_selector = temp; // Restore it
|
||||
temp = inv._invMode;
|
||||
inv._invMode = -1;
|
||||
inv._invMode = INVMODE_USE55;
|
||||
inv.invCommands(true);
|
||||
|
||||
_infoFlag = true;
|
||||
|
@ -57,9 +57,11 @@ extern const char INVENTORY_COMMANDS[9];
|
||||
|
||||
class SherlockEngine;
|
||||
class Inventory;
|
||||
class Talk;
|
||||
|
||||
class UserInterface {
|
||||
friend class Inventory;
|
||||
friend class Talk;
|
||||
private:
|
||||
SherlockEngine *_vm;
|
||||
ImageFile *_controlPanel;
|
||||
@ -72,7 +74,6 @@ private:
|
||||
int _help, _oldHelp;
|
||||
int _key, _oldKey;
|
||||
int _temp, _oldTemp;
|
||||
int _invLookFlag;
|
||||
int _oldLook;
|
||||
bool _keyboardInput;
|
||||
bool _pause;
|
||||
@ -89,8 +90,6 @@ private:
|
||||
private:
|
||||
void depressButton(int num);
|
||||
|
||||
void restoreButton(int num);
|
||||
|
||||
void pushButton(int num);
|
||||
|
||||
void toggleButton(int num);
|
||||
@ -120,13 +119,15 @@ public:
|
||||
int _menuCounter;
|
||||
bool _infoFlag;
|
||||
bool _windowOpen;
|
||||
bool _endKeyActive;
|
||||
int _invLookFlag;
|
||||
public:
|
||||
UserInterface(SherlockEngine *vm);
|
||||
~UserInterface();
|
||||
|
||||
void reset();
|
||||
|
||||
void drawInterface();
|
||||
void drawInterface(int bufferNum = 3);
|
||||
|
||||
void handleInput();
|
||||
|
||||
@ -140,6 +141,8 @@ public:
|
||||
void summonWindow(const Surface &bgSurface, bool slideUp = true);
|
||||
void summonWindow(bool slideUp = true, int height = CONTROLS_Y);
|
||||
void banishWindow(bool slideUp = true);
|
||||
|
||||
void restoreButton(int num);
|
||||
};
|
||||
|
||||
} // End of namespace Sherlock
|
||||
|
Loading…
x
Reference in New Issue
Block a user