scummvm/engines/vcruise/runtime.h
2025-01-24 08:23:54 +02:00

1555 lines
44 KiB
C++

/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef VCRUISE_RUNTIME_H
#define VCRUISE_RUNTIME_H
#include "graphics/pixelformat.h"
#include "common/hashmap.h"
#include "common/keyboard.h"
#include "common/mutex.h"
#include "common/rect.h"
#include "vcruise/detection.h"
class OSystem;
class MidiDriver;
namespace Common {
class MemoryReadStream;
class RandomSource;
class ReadStream;
class WriteStream;
} // End of namespace Commom
namespace Audio {
class AudioStream;
class SeekableAudioStream;
class LoopingAudioStream;
} // End of namespace Audio
namespace Graphics {
struct PixelFormat;
struct WinCursorGroup;
class ManagedSurface;
class Font;
class Cursor;
} // End of namespace Graphics
namespace Video {
class AVIDecoder;
} // End of namespace Video
namespace Image {
class AniDecoder;
} // End of namespace Image
namespace VCruise {
static const uint kNumDirections = 8;
static const uint kNumHighPrecisionDirections = 256;
static const uint kHighPrecisionDirectionMultiplier = kNumHighPrecisionDirections / kNumDirections;
static const uint kNumStartConfigs = 3;
enum StartConfig {
kStartConfigCheatMenu,
kStartConfigInitial,
kStartConfigAlt,
};
class AudioPlayer;
class CircuitPuzzle;
class MidiPlayer;
class MenuInterface;
class MenuPage;
class RuntimeMenuInterface;
class TextParser;
struct ScriptSet;
struct Script;
struct IScriptCompilerGlobalState;
struct Instruction;
struct RoomScriptSet;
struct SoundLoopInfo;
class SampleLoopAudioStream;
struct AD2044Graphics;
enum GameState {
kGameStateBoot, // Booting the game
kGameStateWaitingForAnimation, // Waiting for a blocking animation with no stop frame to complete, then resuming script
kGameStateWaitingForAnimationToDelay, // Waiting for a blocking animation with no stop frame to complete, then going to delay
kGameStateWaitingForFacing, // Waiting for a blocking animation with a stop frame to complete, then resuming script
kGameStateWaitingForFacingToAnim, // Waiting for a blocking animation to complete, then playing _postFacingAnimDef and switching to kGameStateWaitingForAnimation
kGameStateQuit, // Quitting
kGameStateIdle, // Waiting for input events
kGameStateDelay, // Waiting for delay completion time
kGameStateScript, // Running a script
kGameStateScriptReset, // Resetting script interpreter into a new script
kGameStateGyroIdle, // Waiting for mouse movement to run a gyro
kGameStateGyroAnimation, // Animating a gyro
kGameStatePanLeft,
kGameStatePanRight,
kGameStateMenu,
};
struct AD2044AnimationDef {
byte roomID;
byte lookupID;
short fwdAnimationID;
short revAnimationID;
};
struct AnimationDef {
AnimationDef();
int animNum; // May be negative if reversed
uint firstFrame;
uint lastFrame; // Inclusive
Common::Rect constraintRect;
Common::String animName;
};
struct RoomDef {
Common::HashMap<Common::String, AnimationDef> animations;
Common::HashMap<Common::String, uint> vars;
Common::HashMap<Common::String, int> values;
Common::HashMap<Common::String, Common::String> texts;
Common::HashMap<Common::String, int> sounds;
Common::String name;
};
struct InteractionDef {
InteractionDef();
Common::Rect rect;
uint16 interactionID;
uint16 objectType;
};
struct MapScreenDirectionDef {
Common::Array<InteractionDef> interactions;
};
class MapLoader {
public:
virtual ~MapLoader();
virtual void setRoomNumber(uint roomNumber) = 0;
virtual const MapScreenDirectionDef *getScreenDirection(uint screen, uint direction) = 0;
virtual void unload() = 0;
protected:
static Common::SharedPtr<MapScreenDirectionDef> loadScreenDirectionDef(Common::ReadStream &stream);
};
struct ScriptEnvironmentVars {
ScriptEnvironmentVars();
uint panInteractionID;
uint clickInteractionID;
uint fpsOverride;
uint lastHighlightedItem;
uint animChangeFrameOffset;
uint animChangeNumFrames;
bool lmb;
bool lmbDrag;
bool esc;
bool exitToMenu;
bool animChangeSet;
bool isEntryScript;
bool puzzleWasSet;
};
struct SfxSound {
Common::Array<byte> soundData;
Common::SharedPtr<Common::MemoryReadStream> memoryStream;
Common::SharedPtr<Audio::SeekableAudioStream> audioStream;
Common::SharedPtr<AudioPlayer> audioPlayer;
};
struct SfxPlaylistEntry {
SfxPlaylistEntry();
uint frame;
Common::SharedPtr<SfxSound> sample;
int8 balance;
int32 volume;
bool isUpdate;
};
struct SfxPlaylist {
SfxPlaylist();
Common::Array<SfxPlaylistEntry> entries;
};
struct SfxData {
SfxData();
void reset();
void load(Common::SeekableReadStream &stream, Audio::Mixer *mixer);
typedef Common::HashMap<Common::String, Common::SharedPtr<SfxPlaylist> > PlaylistMap_t;
typedef Common::HashMap<Common::String, Common::SharedPtr<SfxSound> > SoundMap_t;
PlaylistMap_t playlists;
SoundMap_t sounds;
};
struct SoundParams3D {
SoundParams3D();
uint minRange;
uint maxRange;
// Not sure what this does. It's always shorter than the min range but after many tests, I've been
// unable to detect any level changes from altering this parameter.
uint unknownRange;
void write(Common::WriteStream *stream) const;
void read(Common::ReadStream *stream);
};
struct SoundCache {
SoundCache();
~SoundCache();
Common::SharedPtr<SoundLoopInfo> loopInfo;
Common::SharedPtr<Audio::SeekableAudioStream> stream;
Common::SharedPtr<SampleLoopAudioStream> loopingStream;
Common::SharedPtr<AudioPlayer> player;
bool isLoopActive;
};
struct SoundInstance {
SoundInstance();
~SoundInstance();
Common::String name;
Common::SharedPtr<SoundCache> cache;
uint id;
int32 rampStartVolume;
int32 rampEndVolume;
int32 rampRatePerMSec;
uint32 rampStartTime;
bool rampTerminateOnCompletion;
int32 volume;
int32 balance;
uint effectiveVolume;
int32 effectiveBalance;
bool is3D;
bool isLooping;
bool isSpeech;
bool restartWhenAudible;
bool tryToLoopWhenRestarted;
int32 x;
int32 y;
SoundParams3D params3D;
uint32 startTime;
uint32 endTime;
uint32 duration;
};
struct RandomAmbientSound {
RandomAmbientSound();
Common::String name;
int32 volume;
int32 balance;
uint frequency;
uint sceneChangesRemaining;
void write(Common::WriteStream *stream) const;
void read(Common::ReadStream *stream);
};
struct TriggeredOneShot {
TriggeredOneShot();
bool operator==(const TriggeredOneShot &other) const;
bool operator!=(const TriggeredOneShot &other) const;
uint soundID;
uint uniqueSlot;
void write(Common::WriteStream *stream) const;
void read(Common::ReadStream *stream);
};
struct ScoreSectionDef {
ScoreSectionDef();
Common::String musicFileName; // If empty, this is silent
Common::String nextSection;
int32 volumeOrDurationInSeconds;
};
struct ScoreTrackDef {
typedef Common::HashMap<Common::String, ScoreSectionDef> ScoreSectionMap_t;
ScoreSectionMap_t sections;
};
struct StartConfigDef {
StartConfigDef();
uint disc;
uint room;
uint screen;
uint direction;
};
struct StaticAnimParams {
StaticAnimParams();
uint initialDelay;
uint repeatDelay;
bool lockInteractions;
void write(Common::WriteStream *stream) const;
void read(Common::ReadStream *stream);
};
struct StaticAnimation {
StaticAnimation();
AnimationDef animDefs[2];
StaticAnimParams params;
uint32 nextStartTime;
uint currentAlternation;
};
struct FrameData {
FrameData();
uint32 frameIndex;
uint16 areaFrameIndex;
int8 roomNumber;
uint8 frameType; // 0x01 = Keyframe, 0x02 = Intra frame (not used in Schizm), 0x41 = Last frame
char areaID[4];
};
struct FrameData2 {
FrameData2();
int32 x;
int32 y;
int32 angle;
uint16 frameNumberInArea;
uint16 unknown; // Subarea or something?
};
struct AnimFrameRange {
AnimFrameRange();
uint animationNum;
uint firstFrame;
uint lastFrame; // Inclusive
};
struct InventoryItem {
InventoryItem();
Common::SharedPtr<Graphics::ManagedSurface> graphic;
Common::SharedPtr<Graphics::ManagedSurface> mask;
uint itemID;
bool highlighted;
};
struct Fraction {
Fraction();
Fraction(uint pNumerator, uint pDenominator);
uint numerator;
uint denominator;
};
enum LoadGameOutcome {
kLoadGameOutcomeSucceeded,
kLoadGameOutcomeSaveDataCorrupted,
kLoadGameOutcomeMissingVersion,
kLoadGameOutcomeInvalidVersion,
kLoadGameOutcomeSaveIsTooNew,
kLoadGameOutcomeSaveIsTooOld,
};
// State that is swapped when switching between characters in Schizm
struct SaveGameSwappableState {
struct InventoryItem {
InventoryItem();
uint itemID;
bool highlighted;
void write(Common::WriteStream *stream) const;
void read(Common::ReadStream *stream);
};
struct Sound {
Sound();
Common::String name;
uint id;
int32 volume;
int32 balance;
bool is3D;
bool isLooping;
bool tryToLoopWhenRestarted;
bool isSpeech;
int32 x;
int32 y;
SoundParams3D params3D;
void write(Common::WriteStream *stream) const;
void read(Common::ReadStream *stream, uint saveGameVersion);
};
SaveGameSwappableState();
uint roomNumber;
uint screenNumber;
uint direction;
uint disc;
bool havePendingPostSwapScreenReset;
uint loadedAnimation;
uint animDisplayingFrame;
bool haveIdleAnimationLoop;
uint idleAnimNum;
uint idleFirstFrame;
uint idleLastFrame;
int musicTrack;
Common::String scoreTrack;
Common::String scoreSection;
bool musicActive;
bool musicMuteDisabled;
int32 musicVolume;
int32 animVolume;
Common::Array<InventoryItem> inventory;
Common::Array<Sound> sounds;
Common::Array<RandomAmbientSound> randomAmbientSounds;
};
struct SaveGameSnapshot {
struct PagedInventoryItem {
PagedInventoryItem();
uint8 page;
uint8 slot;
uint8 itemID;
void write(Common::WriteStream *stream) const;
void read(Common::ReadStream *stream, uint saveGameVersion);
};
struct PlacedInventoryItem {
PlacedInventoryItem();
uint32 locationID;
uint8 itemID;
void write(Common::WriteStream *stream) const;
void read(Common::ReadStream *stream, uint saveGameVersion);
};
SaveGameSnapshot();
void write(Common::WriteStream *stream) const;
LoadGameOutcome read(Common::ReadStream *stream);
static const uint kSaveGameIdentifier = 0x53566372;
static const uint kSaveGameCurrentVersion = 10;
static const uint kSaveGameEarliestSupportedVersion = 2;
static const uint kMaxStates = 2;
static Common::String safeReadString(Common::ReadStream *stream);
static void writeString(Common::WriteStream *stream, const Common::String &str);
uint hero;
uint swapOutRoom;
uint swapOutScreen;
uint swapOutDirection;
uint8 inventoryPage;
uint8 inventoryActiveItem;
uint numStates;
Common::SharedPtr<SaveGameSwappableState> states[kMaxStates];
bool escOn;
StaticAnimParams pendingStaticAnimParams;
SoundParams3D pendingSoundParams3D;
int32 listenerX;
int32 listenerY;
int32 listenerAngle;
Common::Array<TriggeredOneShot> triggeredOneShots;
Common::HashMap<uint32, uint> sayCycles;
Common::HashMap<uint32, int32> variables;
Common::HashMap<uint, uint32> timers;
Common::Array<PagedInventoryItem> pagedItems;
Common::Array<PlacedInventoryItem> placedItems;
};
enum OSEventType {
kOSEventTypeInvalid,
kOSEventTypeMouseMove,
kOSEventTypeLButtonDown,
kOSEventTypeLButtonUp,
kOSEventTypeKeymappedEvent,
};
enum KeymappedEvent {
kKeymappedEventNone,
kKeymappedEventEscape,
kKeymappedEventHelp,
kKeymappedEventSaveGame,
kKeymappedEventLoadGame,
kKeymappedEventSoundSettings,
kKeymappedEventQuit,
kKeymappedEventPause,
kKeymappedEventMusicToggle,
kKeymappedEventSoundToggle,
kKeymappedEventMusicVolumeDown,
kKeymappedEventMusicVolumeUp,
kKeymappedEventSoundVolumeDown,
kKeymappedEventSoundVolumeUp,
kKeymappedEventSkipAnimation,
kKeymappedEventPutItem,
};
struct OSEvent {
OSEvent();
OSEventType type;
Common::Point pos;
KeymappedEvent keymappedEvent;
uint32 timestamp;
};
struct TextStyleDef {
Common::String fontName;
uint size;
uint unknown1;
uint unknown2;
uint unknown3; // Seems to always be 0 for English, other values for other languages
uint colorRGB;
uint shadowColorRGB;
uint alignment; // Modulo 10 seems to be alignment: 0 = left, 1 = center, 2 = right
uint unknown5; // Possibly drop shadow offset
};
struct UILabelDef {
Common::String lineID;
Common::String styleDefID;
uint graphicLeft;
uint graphicTop;
uint graphicWidth;
uint graphicHeight;
};
struct FontCacheItem {
FontCacheItem();
Common::String fname;
uint size;
const Graphics::Font *font;
Common::SharedPtr<Graphics::Font> keepAlive;
};
typedef Common::HashMap<Common::String, uint> ScreenNameToRoomMap_t;
typedef Common::HashMap<uint, ScreenNameToRoomMap_t> RoomToScreenNameToRoomMap_t;
struct AnimatedCursor {
struct FrameDef {
uint imageIndex;
uint delay;
};
Common::Array<FrameDef> frames;
Common::Array<Graphics::Cursor *> images;
Common::Array<Common::SharedPtr<Graphics::Cursor> > cursorKeepAlive;
Common::SharedPtr<Graphics::WinCursorGroup> cursorGroupKeepAlive;
};
class Runtime {
public:
friend class RuntimeMenuInterface;
enum CharSet {
kCharSetLatin,
kCharSetGreek,
kCharSetCyrillic,
kCharSetJapanese,
kCharSetChineseTraditional,
kCharSetChineseSimplified,
};
Runtime(OSystem *system, Audio::Mixer *mixer, MidiDriver *midiDrv, const Common::FSNode &rootFSNode, VCruiseGameID gameID, Common::Language defaultLanguage);
virtual ~Runtime();
void initSections(const Common::Rect &gameRect, const Common::Rect &menuRect, const Common::Rect &trayRect, const Common::Rect &subtitleRect, const Common::Rect &fullscreenMenuRect, const Graphics::PixelFormat &pixFmt);
void loadCursors(const char *exeName);
void setDebugMode(bool debugMode);
void setFastAnimationMode(bool fastAnimationMode);
void setPreloadSounds(bool preloadSounds);
void setLowQualityGraphicsMode(bool lowQualityGraphicsMode);
bool runFrame();
void drawFrame();
void onLButtonDown(int16 x, int16 y);
void onLButtonUp(int16 x, int16 y);
void onMouseMove(int16 x, int16 y);
void onKeymappedEvent(KeymappedEvent evt);
bool canSave(bool onCurrentScreen) const;
bool canLoad() const;
void recordSaveGameSnapshot();
void recordSounds(SaveGameSwappableState &state);
void restoreSaveGameSnapshot();
Common::SharedPtr<SaveGameSnapshot> generateNewGameSnapshot() const;
void saveGame(Common::WriteStream *stream) const;
LoadGameOutcome loadGame(Common::ReadStream *stream);
bool bootGame(bool newGame);
static void resolveCodePageForLanguage(Common::Language lang, Common::CodePage &outCodePage, CharSet &outCharSet);
void drawLabel(Graphics::ManagedSurface *surface, const Common::String &labelID, const Common::Rect &contentRect);
void getLabelDef(const Common::String &labelID, const Graphics::Font *&outFont, const Common::String *&outTextUTF8, uint32 &outColor, uint32 &outShadowColor, uint32 &outShadowOffset);
void onMidiTimer();
private:
enum IndexParseType {
kIndexParseTypeNone,
kIndexParseTypeRoom,
kIndexParseTypeRRoom, // Rectangle room (constrains animation areas)
kIndexParseTypeYRoom, // Yes room (variable/ID mappings)
kIndexParseTypeVRoom, // Value room (value/ID mappings?)
kIndexParseTypeTRoom, // Text
kIndexParseTypeCRoom, // Const
kIndexParseTypeSRoom, // Sound
kIndexParseTypeNameRoom,
};
enum AnimDecoderState {
kAnimDecoderStateStopped,
kAnimDecoderStatePlaying,
kAnimDecoderStatePaused,
};
struct IndexPrefixTypePair {
const char *prefix;
IndexParseType parseType;
};
struct RenderSection {
Common::SharedPtr<Graphics::ManagedSurface> surf;
Common::Rect rect;
Graphics::PixelFormat pixFmt;
void init(const Common::Rect &paramRect, const Graphics::PixelFormat &fmt);
};
struct Gyro {
static const uint kMaxPreviousStates = 3;
int32 currentState;
int32 requiredState;
int32 previousStates[kMaxPreviousStates];
int32 requiredPreviousStates[kMaxPreviousStates];
uint numPreviousStates;
uint numPreviousStatesRequired;
bool wrapAround;
bool requireState;
Gyro();
void reset();
void logState();
};
struct GyroState {
GyroState();
void reset();
static const uint kNumGyros = 5;
Gyro gyros[kNumGyros];
uint completeInteraction;
uint failureInteraction;
uint frameSeparation;
uint activeGyro;
uint dragMargin;
uint maxValue;
AnimationDef negAnim;
AnimationDef posAnim;
bool isVertical;
Common::Point dragBasePoint;
uint dragBaseState;
int32 dragCurrentState;
bool isWaitingForAnimation;
};
enum PanoramaCursorFlags {
kPanCursorDraggableHoriz = (1 << 0),
kPanCursorDraggableUp = (1 << 1),
kPanCursorDraggableDown = (1 << 2),
kPanCursorDirectionUp = (0 << 3),
kPanCursorDirectionLeft = (1 << 3),
kPanCursorDirectionRight = (2 << 3),
kPanCursorDirectionDown = (3 << 3),
kPanCursorMaxCount = (1 << 5),
};
enum PanoramaState {
kPanoramaStateInactive,
kPanoramaStatePanningUncertainDirection,
kPanoramaStatePanningLeft,
kPanoramaStatePanningRight,
kPanoramaStatePanningUp,
kPanoramaStatePanningDown,
};
enum InGameMenuState {
kInGameMenuStateInvisible,
kInGameMenuStateVisible,
kInGameMenuStateHoveringInactive,
kInGameMenuStateHoveringActive,
kInGameMenuStateClickingOver, // Mouse was pressed on a button and is holding on it
kInGameMenuStateClickingNotOver, // Mouse was pressed on a button and dragged off
kInGameMenuStateClickingInactive,
};
enum SoundLoopBehavior {
kSoundLoopBehaviorNo,
kSoundLoopBehaviorYes,
kSoundLoopBehaviorAuto,
};
static const uint kPanLeftInteraction = 1;
static const uint kPanDownInteraction = 2;
static const uint kPanRightInteraction = 3;
static const uint kPanUpInteraction = 4;
static const uint kPanoramaLeftFlag = 1;
static const uint kPanoramaRightFlag = 2;
static const uint kPanoramaUpFlag = 4;
static const uint kPanoramaDownFlag = 8;
static const uint kPanoramaHorizFlags = (kPanoramaLeftFlag | kPanoramaRightFlag);
static const uint kNumInventorySlots = 6;
static const uint kNumInventoryPages = 8;
typedef int32 ScriptArg_t;
typedef int32 StackInt_t;
struct StackValue {
enum StackValueType {
kNumber,
kString,
};
union ValueUnion {
StackInt_t i;
Common::String s;
ValueUnion();
explicit ValueUnion(StackInt_t iVal);
explicit ValueUnion(const Common::String &strVal);
explicit ValueUnion(Common::String &&strVal);
~ValueUnion();
};
StackValue();
StackValue(const StackValue &other);
StackValue(StackValue &&other);
explicit StackValue(StackInt_t i);
explicit StackValue(const Common::String &str);
explicit StackValue(Common::String &&str);
~StackValue();
StackValue &operator=(const StackValue &other);
StackValue &operator=(StackValue &&other);
StackValueType type;
ValueUnion value;
};
struct CallStackFrame {
CallStackFrame();
Common::SharedPtr<Script> _script;
uint _nextInstruction;
};
struct SubtitleDef {
SubtitleDef();
uint8 color[3];
uint unknownValue1;
uint durationInDeciseconds;
Common::String str;
};
struct SubtitleQueueItem {
Common::U32String str;
uint8 color[3];
uint32 startTime;
uint32 endTime;
};
bool runIdle();
bool runDelay();
bool runHorizontalPan(bool isRight);
bool runScript();
bool requireAvailableStack(uint n);
bool runWaitForAnimation();
bool runWaitForAnimationToDelay();
bool runWaitForFacing();
bool runWaitForFacingToAnim();
bool runGyroIdle();
bool runGyroAnimation();
void exitGyroIdle();
void continuePlayingAnimation(bool loop, bool useStopFrame, bool &outEndedAnimation);
void drawSectionToScreen(const RenderSection &section, const Common::Rect &rect);
void commitSectionToScreen(const RenderSection &section, const Common::Rect &rect);
void terminateScript();
void quitToMenu();
RoomScriptSet *getRoomScriptSetForCurrentRoom() const;
bool checkCompletionConditions();
void startTerminatingHorizontalPan(bool isRight);
bool popOSEvent(OSEvent &evt);
void queueOSEvent(const OSEvent &evt);
void processUniversalKeymappedEvents(KeymappedEvent evt);
void loadReahSchizmIndex();
void loadAD2044ExecutableResources();
void findWaves();
void loadConfig(const char *cfgPath);
void loadScore();
void loadDuplicateRooms();
void loadAllSchizmScreenNames();
Common::SharedPtr<SoundInstance> loadWave(const Common::String &soundName, uint soundID, const Common::ArchiveMemberPtr &archiveMemberPtr);
SoundCache *loadCache(SoundInstance &sound);
void resolveSoundByName(const Common::String &soundName, bool load, StackInt_t &outSoundID, SoundInstance *&outWave);
SoundInstance *resolveSoundByID(uint soundID);
void resolveSoundByNameOrID(const StackValue &stackValue, bool load, StackInt_t &outSoundID, SoundInstance *&outWave);
void changeToScreen(uint roomNumber, uint screenNumber);
void clearIdleAnimations();
void changeHero();
void changeToExamineItem();
void returnFromExaminingItem();
bool triggerPreIdleActions();
void returnToIdleState();
void changeToCursor(const Common::SharedPtr<AnimatedCursor> &cursor);
void refreshCursor(uint32 currentTime);
bool dischargeIdleMouseMove();
bool dischargeIdleMouseDown();
bool dischargeIdleClick();
void loadFrameData(Common::SeekableReadStream *stream);
void loadFrameData2(Common::SeekableReadStream *stream);
void loadTabData(Common::HashMap<int, AnimFrameRange> &animIDToFrameRangeMap, uint animNumber, Common::SeekableReadStream *stream);
void changeMusicTrack(int musicID);
void startScoreSection();
void setMusicMute(bool muted);
void changeAnimation(const AnimationDef &animDef, bool consumeFPSOverride);
void changeAnimation(const AnimationDef &animDef, uint initialFrame, bool consumeFPSOverride);
void changeAnimation(const AnimationDef &animDef, uint initialFrame, bool consumeFPSOverride, const Fraction &defaultFrameRate);
void applyAnimationVolume();
void setSound3DParameters(SoundInstance &sound, int32 x, int32 y, const SoundParams3D &soundParams3D);
void triggerSound(SoundLoopBehavior loopBehavior, SoundInstance &sound, int32 volume, int32 balance, bool is3D, bool isSpeech);
void triggerSoundRamp(SoundInstance &sound, uint durationMSec, int32 newVolume, bool terminateOnCompletion);
void stopSound(SoundInstance &sound);
void convertLoopingSoundToNonLooping(SoundInstance &sound);
void updateSounds(uint32 timestamp);
void updateSubtitles();
void update3DSounds();
bool computeEffectiveVolumeAndBalance(SoundInstance &snd);
void triggerAmbientSounds();
uint decibelsToLinear(int db, uint baseVolume, uint maxVolume) const;
int32 getSilentSoundVolume() const;
int32 getDefaultSoundVolume() const;
uint applyVolumeScale(int32 volume) const;
int applyBalanceScale(int32 balance) const;
void triggerWaveSubtitles(const SoundInstance &sound, const Common::String &id);
void stopSubtitles();
AnimationDef stackArgsToAnimDef(const StackInt_t *args) const;
void consumeAnimChangeAndAdjustAnim(AnimationDef &animDef);
void pushAnimDef(const AnimationDef &animDef);
void activateScript(const Common::SharedPtr<Script> &script, bool isEntryScript, const ScriptEnvironmentVars &envVars);
Common::SharedPtr<ScriptSet> compileSchizmLogicSet(const uint *roomNumbers, uint numRooms) const;
bool parseIndexDef(IndexParseType parseType, uint roomNumber, const Common::String &key, const Common::String &value);
void allocateRoomsUpTo(uint roomNumber);
void drawDebugOverlay();
Common::SharedPtr<Script> findScriptForInteraction(uint interactionID) const;
void detectPanoramaDirections();
void detectPanoramaMouseMovement(uint32 timestamp);
void panoramaActivate();
bool computeFaceDirectionAnimation(uint desiredDirection, const AnimationDef *&outAnimDef, uint &outInitialFrame, uint &outStopFrame);
void inventoryAddItem(uint item);
void inventoryRemoveItem(uint item);
void clearScreen();
void redrawTray();
void clearTray();
void redrawSubtitleSection();
void clearSubtitleSection();
void drawSubtitleText(const Common::Array<Common::U32String> &lines, const uint8 (&color)[3]);
void drawInventory(uint slot);
void drawCompass();
bool isTrayVisible() const;
void resetInventoryHighlights();
void loadInventoryFromPage();
void copyInventoryToPage();
void cheatPutItem();
static uint32 getLocationForScreen(uint roomNumber, uint screenNumber);
void updatePlacedItemCache();
void drawPlacedItemGraphic();
void clearPlacedItemGraphic();
void drawActiveItemGraphic();
void clearActiveItemGraphic();
void drawInventoryItemGraphic(uint slot);
void clearInventoryItemGraphic(uint slot);
void dropActiveItem();
void pickupPlacedItem();
void stashActiveItemToInventory(uint slot);
void pickupInventoryItem(uint slot);
void getFileNamesForItemGraphic(uint itemID, Common::String &outGraphicFileName, Common::String &outAlphaFileName) const;
Common::SharedPtr<Graphics::ManagedSurface> loadGraphic(const Common::String &graphicName, bool required);
Common::SharedPtr<Graphics::ManagedSurface> loadGraphicFromPath(const Common::Path &path, bool required);
bool loadSubtitles(Common::CodePage codePage, bool guessCodePage);
void changeToMenuPage(MenuPage *menuPage);
void checkInGameMenuHover();
void dismissInGameMenu();
void dischargeInGameMenuMouseUp();
void drawInGameMenuButton(uint element);
const Graphics::Font *resolveFont(const Common::String &textStyle, uint size);
bool resolveCircuitPuzzleInteraction(const Common::Point &relMouse, Common::Point &outCoord, bool &outIsDown, Common::Rect &outHighlightRect) const;
void clearCircuitPuzzle();
void clearCircuitHighlightRect(const Common::Rect &rect);
void drawCircuitHighlightRect(const Common::Rect &rect);
static Common::Rect padCircuitInteractionRect(const Common::Rect &rect);
static Common::SharedPtr<AnimatedCursor> winCursorGroupToAnimatedCursor(const Common::SharedPtr<Graphics::WinCursorGroup> &cursorGroup);
static Common::SharedPtr<AnimatedCursor> aniFileToAnimatedCursor(Image::AniDecoder &aniDecoder);
static Common::SharedPtr<AnimatedCursor> staticCursorToAnimatedCursor(const Common::SharedPtr<Graphics::Cursor> &cursor);
// Script things
void scriptOpNumber(ScriptArg_t arg);
void scriptOpRotate(ScriptArg_t arg);
void scriptOpAngle(ScriptArg_t arg);
void scriptOpAngleGGet(ScriptArg_t arg);
void scriptOpSpeed(ScriptArg_t arg);
void scriptOpSAnimL(ScriptArg_t arg);
void scriptOpChangeL(ScriptArg_t arg);
void scriptOpAnimR(ScriptArg_t arg);
void scriptOpAnimF(ScriptArg_t arg);
void scriptOpAnimN(ScriptArg_t arg);
void scriptOpAnimG(ScriptArg_t arg);
void scriptOpAnimS(ScriptArg_t arg);
void scriptOpAnim(ScriptArg_t arg);
void scriptOpStatic(ScriptArg_t arg);
void scriptOpVarLoad(ScriptArg_t arg);
void scriptOpVarStore(ScriptArg_t arg);
void scriptOpVarAddAndStore(ScriptArg_t arg);
void scriptOpVarGlobalLoad(ScriptArg_t arg);
void scriptOpVarGlobalStore(ScriptArg_t arg);
void scriptOpItemCheck(ScriptArg_t arg);
void scriptOpItemRemove(ScriptArg_t arg);
void scriptOpItemHighlightSet(ScriptArg_t arg);
void scriptOpItemAdd(ScriptArg_t arg);
void scriptOpItemHaveSpace(ScriptArg_t arg);
void scriptOpItemClear(ScriptArg_t arg);
void scriptOpSetCursor(ScriptArg_t arg);
void scriptOpSetRoom(ScriptArg_t arg);
void scriptOpLMB(ScriptArg_t arg);
void scriptOpLMB1(ScriptArg_t arg);
void scriptOpSoundS1(ScriptArg_t arg);
void scriptOpSoundS2(ScriptArg_t arg);
void scriptOpSoundS3(ScriptArg_t arg);
void scriptOpSoundL1(ScriptArg_t arg);
void scriptOpSoundL2(ScriptArg_t arg);
void scriptOpSoundL3(ScriptArg_t arg);
void scriptOp3DSoundS2(ScriptArg_t arg);
void scriptOp3DSoundL2(ScriptArg_t arg);
void scriptOp3DSoundL3(ScriptArg_t arg);
void scriptOpStopAL(ScriptArg_t arg);
void scriptOpRange(ScriptArg_t arg);
void scriptOpAddXSound(ScriptArg_t arg);
void scriptOpClrXSound(ScriptArg_t arg);
void scriptOpStopSndLA(ScriptArg_t arg);
void scriptOpStopSndLO(ScriptArg_t arg);
void scriptOpMusic(ScriptArg_t arg);
void scriptOpMusicVolRamp(ScriptArg_t arg);
void scriptOpParm0(ScriptArg_t arg);
void scriptOpParm1(ScriptArg_t arg);
void scriptOpParm2(ScriptArg_t arg);
void scriptOpParm3(ScriptArg_t arg);
void scriptOpParmG(ScriptArg_t arg);
void scriptOpSParmX(ScriptArg_t arg);
void scriptOpSAnimX(ScriptArg_t arg);
void scriptOpVolumeDn2(ScriptArg_t arg);
void scriptOpVolumeDn3(ScriptArg_t arg);
void scriptOpVolumeDn4(ScriptArg_t arg);
void scriptOpVolumeUp3(ScriptArg_t arg);
void scriptOpRandom(ScriptArg_t arg);
void scriptOpDrop(ScriptArg_t arg);
void scriptOpDup(ScriptArg_t arg);
void scriptOpSwap(ScriptArg_t arg);
void scriptOpSay1(ScriptArg_t arg);
void scriptOpSay2(ScriptArg_t arg);
void scriptOpSay3(ScriptArg_t arg);
void scriptOpSay3Get(ScriptArg_t arg);
void scriptOpSetTimer(ScriptArg_t arg);
void scriptOpGetTimer(ScriptArg_t arg);
void scriptOpDelay(ScriptArg_t arg);
void scriptOpLoSet(ScriptArg_t arg);
void scriptOpLoGet(ScriptArg_t arg);
void scriptOpHiSet(ScriptArg_t arg);
void scriptOpHiGet(ScriptArg_t arg);
void scriptOpNot(ScriptArg_t arg);
void scriptOpAnd(ScriptArg_t arg);
void scriptOpOr(ScriptArg_t arg);
void scriptOpAdd(ScriptArg_t arg);
void scriptOpSub(ScriptArg_t arg);
void scriptOpNegate(ScriptArg_t arg);
void scriptOpCmpEq(ScriptArg_t arg);
void scriptOpCmpLt(ScriptArg_t arg);
void scriptOpCmpGt(ScriptArg_t arg);
void scriptOpBitLoad(ScriptArg_t arg);
void scriptOpBitSet0(ScriptArg_t arg);
void scriptOpBitSet1(ScriptArg_t arg);
void scriptOpDisc1(ScriptArg_t arg);
void scriptOpDisc2(ScriptArg_t arg);
void scriptOpDisc3(ScriptArg_t arg);
void scriptOpGoto(ScriptArg_t arg);
void scriptOpEscOn(ScriptArg_t arg);
void scriptOpEscOff(ScriptArg_t arg);
void scriptOpEscGet(ScriptArg_t arg);
void scriptOpBackStart(ScriptArg_t arg);
void scriptOpSaveAs(ScriptArg_t arg);
void scriptOpSave0(ScriptArg_t arg);
void scriptOpExit(ScriptArg_t arg);
void scriptOpAllowSaves(ScriptArg_t arg);
void scriptOpAnimName(ScriptArg_t arg);
void scriptOpValueName(ScriptArg_t arg);
void scriptOpVarName(ScriptArg_t arg);
void scriptOpSoundName(ScriptArg_t arg);
void scriptOpCursorName(ScriptArg_t arg);
void scriptOpDubbing(ScriptArg_t arg);
void scriptOpCheckValue(ScriptArg_t arg);
void scriptOpJump(ScriptArg_t arg);
void scriptOpVerticalPanSet(bool *flags);
void scriptOpVerticalPanGet();
// Schizm ops
void scriptOpCallFunction(ScriptArg_t arg);
void scriptOpMusicStop(ScriptArg_t arg);
void scriptOpMusicPlayScore(ScriptArg_t arg);
void scriptOpScoreAlways(ScriptArg_t arg);
void scriptOpScoreNormal(ScriptArg_t arg);
void scriptOpSndPlay(ScriptArg_t arg);
void scriptOpSndPlayEx(ScriptArg_t arg);
void scriptOpSndPlay3D(ScriptArg_t arg);
void scriptOpSndPlaying(ScriptArg_t arg);
void scriptOpSndWait(ScriptArg_t arg);
void scriptOpSndHalt(ScriptArg_t arg);
void scriptOpSndToBack(ScriptArg_t arg);
void scriptOpSndStop(ScriptArg_t arg);
void scriptOpSndStopAll(ScriptArg_t arg);
void scriptOpSndAddRandom(ScriptArg_t arg);
void scriptOpSndClearRandom(ScriptArg_t arg);
void scriptOpVolumeAdd(ScriptArg_t arg);
void scriptOpVolumeChange(ScriptArg_t arg);
void scriptOpAnimVolume(ScriptArg_t arg);
void scriptOpAnimChange(ScriptArg_t arg);
void scriptOpScreenName(ScriptArg_t arg);
void scriptOpExtractByte(ScriptArg_t arg);
void scriptOpInsertByte(ScriptArg_t arg);
void scriptOpString(ScriptArg_t arg);
void scriptOpCmpNE(ScriptArg_t arg);
void scriptOpCmpLE(ScriptArg_t arg);
void scriptOpCmpGE(ScriptArg_t arg);
void scriptOpReturn(ScriptArg_t arg);
void scriptOpSpeech(ScriptArg_t arg);
void scriptOpSpeechEx(ScriptArg_t arg);
void scriptOpSpeechTest(ScriptArg_t arg);
void scriptOpSay(ScriptArg_t arg);
void scriptOpRandomInclusive(ScriptArg_t arg);
void scriptOpHeroOut(ScriptArg_t arg);
void scriptOpHeroGetPos(ScriptArg_t arg);
void scriptOpHeroSetPos(ScriptArg_t arg);
void scriptOpHeroGet(ScriptArg_t arg);
void scriptOpGarbage(ScriptArg_t arg);
void scriptOpGetRoom(ScriptArg_t arg);
void scriptOpBitAnd(ScriptArg_t arg);
void scriptOpBitOr(ScriptArg_t arg);
void scriptOpAngleGet(ScriptArg_t arg);
void scriptOpIsDVDVersion(ScriptArg_t arg);
void scriptOpIsCDVersion(ScriptArg_t arg);
void scriptOpDisc(ScriptArg_t arg);
void scriptOpHidePanel(ScriptArg_t arg);
void scriptOpRotateUpdate(ScriptArg_t arg);
void scriptOpMul(ScriptArg_t arg);
void scriptOpDiv(ScriptArg_t arg);
void scriptOpMod(ScriptArg_t arg);
void scriptOpGetDigit(ScriptArg_t arg);
void scriptOpPuzzleInit(ScriptArg_t arg);
void scriptOpPuzzleCanPress(ScriptArg_t arg);
void scriptOpPuzzleDoMove1(ScriptArg_t arg);
void scriptOpPuzzleDoMove2(ScriptArg_t arg);
void scriptOpPuzzleDone(ScriptArg_t arg);
void scriptOpPuzzleWhoWon(ScriptArg_t arg);
void scriptOpFn(ScriptArg_t arg);
void scriptOpItemHighlightSetTrue(ScriptArg_t arg);
// AD2044 ops
void scriptOpAnimAD2044(bool isForward);
void scriptOpAnimT(ScriptArg_t arg);
void scriptOpAnimForward(ScriptArg_t arg);
void scriptOpAnimReverse(ScriptArg_t arg);
void scriptOpAnimKForward(ScriptArg_t arg);
void scriptOpNoUpdate(ScriptArg_t arg);
void scriptOpNoClear(ScriptArg_t arg);
void scriptOpSay1_AD2044(ScriptArg_t arg);
void scriptOpSay2_AD2044(ScriptArg_t arg);
void scriptOpSay1Rnd(ScriptArg_t arg);
void scriptOpM(ScriptArg_t arg);
void scriptOpEM(ScriptArg_t arg);
void scriptOpSE(ScriptArg_t arg);
void scriptOpSDot(ScriptArg_t arg);
void scriptOpE(ScriptArg_t arg);
void scriptOpDot(ScriptArg_t arg);
void scriptOpSound(ScriptArg_t arg);
void scriptOpISound(ScriptArg_t arg);
void scriptOpUSound(ScriptArg_t arg);
void scriptOpSayCycle_AD2044(const StackInt_t *values, uint numValues);
void scriptOpSay2K(ScriptArg_t arg);
void scriptOpSay3K(ScriptArg_t arg);
void scriptOpRGet(ScriptArg_t arg);
void scriptOpRSet(ScriptArg_t arg);
void scriptOpEndRSet(ScriptArg_t arg);
void scriptOpStop(ScriptArg_t arg);
Common::Array<Common::SharedPtr<AnimatedCursor> > _cursors; // Cursors indexed as CURSOR_CUR_##
Common::Array<Common::SharedPtr<AnimatedCursor> > _cursorsShort; // Cursors indexed as CURSOR_#
InventoryItem _inventory[kNumInventorySlots];
InventoryItem _inventoryPages[kNumInventoryPages][kNumInventorySlots];
Common::HashMap<uint32, uint8> _placedItems;
uint8 _inventoryActivePage;
InventoryItem _inventoryActiveItem;
InventoryItem _inventoryPlacedItemCache;
Common::Rect _placedItemRect;
Common::SharedPtr<Graphics::ManagedSurface> _trayCompassGraphic;
Common::SharedPtr<Graphics::ManagedSurface> _trayBackgroundGraphic;
Common::SharedPtr<Graphics::ManagedSurface> _trayHighlightGraphic;
Common::SharedPtr<Graphics::ManagedSurface> _trayCornerGraphic;
Common::SharedPtr<Graphics::ManagedSurface> _backgroundGraphic;
Common::Array<Common::SharedPtr<Graphics::ManagedSurface> > _uiGraphics;
uint _panCursors[kPanCursorMaxCount];
Common::HashMap<Common::String, StackInt_t> _namedCursors;
Common::HashMap<StackInt_t, uint> _scriptCursorIDToResourceIDOverride;
OSystem *_system;
uint _roomNumber; // Room number can be changed independently of the loaded room, the screen doesn't change until a command changes it
uint _screenNumber;
uint _direction;
uint _hero;
uint _disc;
uint _swapOutRoom;
uint _swapOutScreen;
uint _swapOutDirection;
GyroState _gyros;
AnimationDef _panLeftAnimationDef;
AnimationDef _panRightAnimationDef;
bool _haveHorizPanAnimations;
bool _havePanUpFromDirection[kNumDirections];
bool _havePanDownFromDirection[kNumDirections];
StaticAnimation _idleAnimations[kNumDirections];
bool _haveIdleAnimations[kNumDirections];
bool _haveIdleStaticAnimation;
bool _keepStaticAnimationInIdle;
Common::String _idleCurrentStaticAnimation;
StaticAnimParams _pendingStaticAnimParams;
uint32 _delayCompletionTime;
AnimationDef _postFacingAnimDef;
Common::SharedPtr<CircuitPuzzle> _circuitPuzzle;
AnimationDef _circuitPuzzleBlockAnimation;
AnimationDef _circuitPuzzleConnectAnimation;
Common::HashMap<uint32, int32> _variables;
Common::HashMap<uint, uint32> _timers;
uint _panoramaDirectionFlags;
uint _loadedRoomNumber;
uint _activeScreenNumber;
bool _havePendingScreenChange;
bool _forceScreenChange;
// returnToIdleState executes any actions that must be executed upon returning to idle state from either
// a panorama or the first script that executes upon reaching a screen.
//
// Unfortunately, this was done slightly prematurely since Schizm plays idle animations during pre-idle
// delays and Reah never needs to do that, so _havePendingPreIdleActions exists to handle those actions
// during pre-idle upon arriving at a screen.
//
// Pre-idle actions are executed once upon either entering Idle OR Delay state.
bool _havePendingPreIdleActions;
bool _havePendingReturnToIdleState;
bool _havePendingPostSwapScreenReset;
bool _havePendingCompletionCheck;
GameState _gameState;
Common::SharedPtr<MenuPage> _menuPage;
Common::SharedPtr<MenuInterface> _menuInterface;
bool _havePendingPlayAmbientSounds;
uint32 _ambientSoundFinishTime;
bool _escOn;
bool _debugMode;
bool _fastAnimationMode;
bool _preloadSounds;
bool _lowQualityGraphicsMode;
VCruiseGameID _gameID;
Common::Array<Common::SharedPtr<RoomDef> > _roomDefs;
Common::Array<uint> _roomDuplicationOffsets;
RoomToScreenNameToRoomMap_t _globalRoomScreenNameToScreenIDs;
Common::SharedPtr<ScriptSet> _scriptSet;
Common::Array<AD2044AnimationDef> _ad2044AnimationDefs;
Common::Array<CallStackFrame> _scriptCallStack;
Common::Array<StackValue> _scriptStack;
ScriptEnvironmentVars _scriptEnv;
Common::SharedPtr<Common::RandomSource> _rng;
Common::SharedPtr<AudioPlayer> _musicWavePlayer;
Common::Mutex _midiPlayerMutex;
Common::SharedPtr<MidiPlayer> _musicMidiPlayer;
int _musicTrack;
int32 _musicVolume;
bool _musicActive;
bool _musicMute;
bool _musicMuteDisabled;
Common::String _scoreTrack;
Common::String _scoreSection;
uint32 _scoreSectionEndTime;
Common::HashMap<Common::String, ScoreTrackDef> _scoreDefs;
uint32 _musicVolumeRampStartTime;
int32 _musicVolumeRampStartVolume;
int32 _musicVolumeRampRatePerMSec;
int32 _musicVolumeRampEnd;
SfxData _sfxData;
Common::SharedPtr<Video::AVIDecoder> _animDecoder;
Common::SharedPtr<SfxPlaylist> _animPlaylist;
AnimDecoderState _animDecoderState;
bool _animTerminateAtStartOfFrame;
uint _animPendingDecodeFrame;
uint _animDisplayingFrame;
uint _animFirstFrame;
uint _animLastFrame;
uint _animStopFrame;
uint _animVolume;
Fraction _animFrameRateLock;
Common::Rect _animConstraintRect;
uint32 _animStartTime;
uint32 _animFramesDecoded;
uint _loadedAnimation;
bool _loadedAnimationHasSound;
bool _animPlayWhileIdle;
Common::Array<FrameData> _frameData;
Common::Array<FrameData2> _frameData2;
//uint32 _loadedArea;
// Reah/Schizm animation map
Common::Array<Common::String> _animDefNames;
Common::HashMap<Common::String, uint> _animDefNameToIndex;
// AD2044 animation map
Common::HashMap<int, AnimFrameRange> _currentRoomAnimIDToFrameRange;
Common::HashMap<int, AnimFrameRange> _examineAnimIDToFrameRange;
bool _idleLockInteractions;
bool _idleIsOnInteraction;
bool _idleHaveClickInteraction;
bool _idleHaveDragInteraction;
uint _idleInteractionID;
bool _idleIsOnOpenCircuitPuzzleLink;
Common::Rect _idleCircuitPuzzleLinkHighlightRect;
bool _idleIsCircuitPuzzleLinkDown;
Common::Point _idleCircuitPuzzleCoord;
bool _forceAllowSaves;
InGameMenuState _inGameMenuState;
uint _inGameMenuActiveElement;
bool _inGameMenuButtonActive[5];
Audio::Mixer *_mixer;
MidiDriver *_midiDrv;
Common::SharedPtr<MapLoader> _mapLoader;
RenderSection _gameSection;
RenderSection _gameDebugBackBuffer;
RenderSection _menuSection;
RenderSection _traySection;
RenderSection _fullscreenMenuSection;
RenderSection _subtitleSection;
RenderSection _placedItemBackBufferSection;
Common::Point _mousePos;
Common::Point _lmbDownPos;
uint32 _lmbDownTime;
int _lmbDragTolerance;
bool _lmbDown;
bool _lmbDragging;
bool _lmbReleaseWasClick; // If true, then the mouse didn't move at all since the LMB down
PanoramaState _panoramaState;
// The anchor point behavior is kind of weird. The way it works in Reah is that if the camera is panning left or right and the mouse is moved
// back across the anchor threshold at all, then the anchor point is reset to the mouse position. This means it can drift, because the center
// is moved by roughly the margin amount.
// Vertical panning on the other hand resets the anchor vertical coordinate every time.
Common::Point _panoramaAnchor;
Common::Array<OSEvent> _pendingEvents;
Common::HashMap<Common::String, Common::ArchiveMemberPtr> _waves;
Common::Array<Common::SharedPtr<SoundInstance> > _activeSounds;
SoundParams3D _pendingSoundParams3D;
Common::Array<TriggeredOneShot> _triggeredOneShots;
Common::HashMap<uint32, uint> _sayCycles;
Common::Array<RandomAmbientSound> _randomAmbientSounds;
int32 _listenerX;
int32 _listenerY;
int32 _listenerAngle;
Fraction _animSpeedRotation;
Fraction _animSpeedStaticAnim;
Fraction _animSpeedDefault;
static const uint kAnimDefStackArgs = 8;
static const uint kCursorArrow = 0;
static const uint kCursorWait = 29;
static const int kPanoramaPanningMarginX = 11;
static const int kPanoramaPanningMarginY = 11;
static const uint kSoundCacheSize = 16;
static const uint kExamineItemInteractionID = 0xfffffff0u;
static const uint kReturnInventorySlot0InteractionID = 0xfffffff1u;
static const uint kReturnInventorySlot1InteractionID = 0xfffffff2u;
static const uint kReturnInventorySlot2InteractionID = 0xfffffff3u;
static const uint kReturnInventorySlot3InteractionID = 0xfffffff4u;
static const uint kReturnInventorySlot4InteractionID = 0xfffffff5u;
static const uint kReturnInventorySlot5InteractionID = 0xfffffff6u;
static const uint kPickupInventorySlot0InteractionID = 0xfffffff7u;
static const uint kPickupInventorySlot1InteractionID = 0xfffffff8u;
static const uint kPickupInventorySlot2InteractionID = 0xfffffff9u;
static const uint kPickupInventorySlot3InteractionID = 0xfffffffau;
static const uint kPickupInventorySlot4InteractionID = 0xfffffffbu;
static const uint kPickupInventorySlot5InteractionID = 0xfffffffcu;
static const uint kObjectPickupInteractionID = 0xfffffffdu;
static const uint kObjectDropInteractionID = 0xfffffffeu;
static const uint kHeroChangeInteractionID = 0xffffffffu;
Common::Pair<Common::String, Common::SharedPtr<SoundCache> > _soundCache[kSoundCacheSize];
uint _soundCacheIndex;
Common::SharedPtr<SaveGameSnapshot> _mostRecentValidSaveState; // Always valid
Common::SharedPtr<SaveGameSnapshot> _mostRecentlyRecordedSaveState; // Might be invalid, becomes valid if the player returns to idle
Common::SharedPtr<SaveGameSwappableState> _altState;
bool _isInGame;
const Graphics::Font *_subtitleFont;
Common::SharedPtr<Graphics::Font> _subtitleFontKeepalive;
uint _defaultLanguageIndex;
uint _languageIndex;
Common::Language _language;
CharSet _charSet;
bool _isCDVariant;
StartConfigDef _startConfigs[kNumStartConfigs];
Common::Language _defaultLanguage;
typedef Common::HashMap<uint, SubtitleDef> FrameToSubtitleMap_t;
typedef Common::HashMap<uint, FrameToSubtitleMap_t> AnimSubtitleMap_t;
typedef Common::HashMap<Common::String, SubtitleDef> WaveSubtitleMap_t;
AnimSubtitleMap_t _animSubtitles;
Common::HashMap<Common::String, SubtitleDef> _waveSubtitles;
Common::Array<SubtitleQueueItem> _subtitleQueue;
bool _isDisplayingSubtitles;
bool _isSubtitleSourceAnimation;
Common::HashMap<Common::String, Common::String> _locStrings;
Common::HashMap<Common::String, TextStyleDef> _locTextStyles;
Common::HashMap<Common::String, UILabelDef> _locUILabels;
Common::Array<Common::SharedPtr<FontCacheItem> > _fontCache;
AnimatedCursor *_currentAnimatedCursor;
Graphics::Cursor *_currentCursor;
uint32 _cursorTimeBase;
uint32 _cursorCycleLength;
int32 _dbToVolume[49];
// AD2044 tooltips
Common::String _tooltipText;
Common::String _subtitleText;
Common::SharedPtr<AD2044Graphics> _ad2044Graphics;
Common::Array<Common::String> _ad2044ItemNames;
};
} // End of namespace VCruise
#endif