/* 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. * * $URL$ * $Id$ * */ // Scene management module private header file #ifndef SAGA_SCENE_H #define SAGA_SCENE_H #include "saga/font.h" #include "saga/actor.h" #include "saga/interface.h" #include "saga/puzzle.h" #include "saga/events.h" namespace Saga { //#define SCENE_DEBUG // for scene debugging #define SCENE_DOORS_MAX 16 #define NO_CHAPTER_CHANGE -2 // Scenes #define ITE_SCENE_INV -1 #define ITE_SCENE_PUZZLE 26 #define ITE_SCENE_LODGE 21 #define ITE_SCENE_ENDCREDIT1 295 #define ITE_SCENE_OVERMAP 226 // Default scenes #define ITE_DEFAULT_SCENE 32 #define IHNM_DEFAULT_SCENE 151 #define ITEDEMO_DEFAULT_SCENE 68 #define IHNMDEMO_DEFAULT_SCENE 144 class ObjectMap; enum SceneFlags { kSceneFlagISO = 1, kSceneFlagShowCursor = 2 }; // FTA2 possible endings enum FTA2Endings { kFta2BadEndingLaw = 0, kFta2BadEndingChaos = 1, kFta2GoodEnding1 = 2, kFta2GoodEnding2 = 3, kFta2BadEndingDeath = 4 }; struct BGInfo { Rect bounds; byte *buffer; }; typedef int (SceneProc) (int, void *); enum SCENE_PROC_PARAMS { SCENE_BEGIN = 0, SCENE_END }; // Resource type numbers enum SAGAResourceTypes { SAGA_UNKNOWN, SAGA_ACTOR, SAGA_OBJECT, SAGA_BG_IMAGE, SAGA_BG_MASK, SAGA_STRINGS, SAGA_OBJECT_MAP, SAGA_ACTION_MAP, SAGA_ISO_IMAGES, SAGA_ISO_MAP, SAGA_ISO_PLATFORMS, SAGA_ISO_METATILES, SAGA_ENTRY, SAGA_ANIM, SAGA_ISO_MULTI, SAGA_PAL_ANIM, SAGA_FACES, SAGA_PALETTE }; #define SAGA_RESLIST_ENTRY_LEN 4 struct SceneResourceData { uint32 resourceId; int resourceType; byte *buffer; size_t size; bool invalid; }; #define SAGA_SCENE_DESC_LEN 16 struct SceneDescription { int16 flags; int16 resourceListResourceId; int16 endSlope; int16 beginSlope; uint16 scriptModuleNumber; uint16 sceneScriptEntrypointNumber; uint16 startScriptEntrypointNumber; int16 musicResourceId; SceneResourceData *resourceList; size_t resourceListCount; }; struct SceneEntry { Location location; uint16 facing; }; class SceneEntryList : public Common::Array { }; struct SceneImage { bool loaded; int w; int h; int p; ByteArray buffer; byte *res_buf; size_t res_len; PalEntry pal[256]; SceneImage() : loaded(false), w(0), h(0), p(0) { memset(pal, 0, sizeof(pal)); } }; enum SceneTransitionType { kTransitionNoFade, kTransitionFade }; enum SceneLoadFlags { kLoadByResourceId, kLoadBySceneNumber, kLoadByDescription }; struct LoadSceneParams { int32 sceneDescriptor; SceneLoadFlags loadFlag; SceneDescription* sceneDescription; SceneProc *sceneProc; bool sceneSkipTarget; SceneTransitionType transitionType; int actorsEntrance; int chapter; }; typedef Common::List SceneQueueList; ///// IHNM-specific stuff #define IHNM_PALFADE_TIME 1000 #define IHNM_INTRO_FRAMETIME 80 #define IHNM_DGLOGO_TIME 8000 #define IHNM_TITLE_TIME_GM 28750 #define IHNM_TITLE_TIME_FM 19500 ///// ITE-specific stuff #define ITE_INTRO_FRAMETIME 90 #define INTRO_CAPTION_Y 170 #define INTRO_DE_CAPTION_Y 160 #define INTRO_IT_CAPTION_Y 160 #define VOICE_PAD 50 #define VOICE_LETTERLEN 90 #define PALETTE_FADE_DURATION 1000 #define DISSOLVE_DURATION 3000 #define LOGO_DISSOLVE_DURATION 1000 #define CREDIT_DURATION1 4000 struct IntroDialogue { uint32 i_voice_rn; const char *i_str; }; struct IntroCredit { Common::Language lang; int game; int type; const char *string; }; class Scene { public: Scene(SagaEngine *vm); ~Scene(); // Console functions void cmdActionMapInfo(); void cmdObjectMapInfo(); void cmdSceneChange(int argc, const char **argv); void startScene(); void creditsScene(); void nextScene(); void skipScene(); void endScene(); void restoreScene(); void queueScene(LoadSceneParams *sceneQueue) { _sceneQueue.push_back(*sceneQueue); } void draw(); int getFlags() const { return _sceneDescription.flags; } int getScriptModuleNumber() const { return _sceneDescription.scriptModuleNumber; } bool isInIntro() { return !_inGame; } const Rect& getSceneClip() const { return _sceneClip; } void getBGMaskInfo(int &width, int &height, byte *&buffer); int isBGMaskPresent() { return _bgMask.loaded; } int getBGMaskType(const Point &testPoint) { uint offset; if (!_bgMask.loaded) { return 0; } offset = testPoint.x + testPoint.y * _bgMask.w; #ifdef SCENE_DEBUG if (offset >= _bgMask.buf_len) { error("Scene::getBGMaskType offset 0x%X exceed bufferLength 0x%X", offset, (int)_bgMask.buf_len); } #endif return (_bgMask.buffer[offset] >> 4) & 0x0f; } bool validBGMaskPoint(const Point &testPoint) { #ifdef SCENE_DEBUG if (!_bgMask.loaded) { error("Scene::validBGMaskPoint _bgMask not loaded"); } #endif return !((testPoint.x < 0) || (testPoint.x >= _bgMask.w) || (testPoint.y < 0) || (testPoint.y >= _bgMask.h)); } bool canWalk(const Point &testPoint); bool offscreenPath(Point &testPoint); void setDoorState(int doorNumber, int doorState) { #ifdef SCENE_DEBUG if ((doorNumber < 0) || (doorNumber >= SCENE_DOORS_MAX)) error("Scene::setDoorState wrong doorNumber"); #endif _sceneDoors[doorNumber] = doorState; } int getDoorState(int doorNumber) { #ifdef SCENE_DEBUG if ((doorNumber < 0) || (doorNumber >= SCENE_DOORS_MAX)) error("Scene::getDoorState wrong doorNumber"); #endif return _sceneDoors[doorNumber]; } void initDoorsState(); void getBGInfo(BGInfo &bgInfo); void getBGPal(PalEntry *&pal) { pal = (PalEntry *)_bg.pal; } void getSlopes(int &beginSlope, int &endSlope); void clearSceneQueue() { _sceneQueue.clear(); } void changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionType transitionType, int chapter = NO_CHAPTER_CHANGE); bool isSceneLoaded() const { return _sceneLoaded; } uint16 getSceneResourceId(int sceneNumber) { #ifdef SCENE_DEBUG if ((sceneNumber < 0) || (sceneNumber >= _sceneCount)) { error("getSceneResourceId: wrong sceneNumber %i", sceneNumber); } #endif return _sceneLUT[sceneNumber]; } int currentProtag() const { return _currentProtag; } void setProtag(int pr) { _currentProtag = pr; } int currentSceneNumber() const { return _sceneNumber; } int currentChapterNumber() const { return _chapterNumber; } void setChapterNumber(int ch) { _chapterNumber = ch; } int getOutsetSceneNumber() const { return _outsetSceneNumber; } int currentSceneResourceId() const { return _sceneResourceId; } int getCurrentMusicTrack() const { return _currentMusicTrack; } void setCurrentMusicTrack(int tr) { _currentMusicTrack = tr; } int getCurrentMusicRepeat() const { return _currentMusicRepeat; } void setCurrentMusicRepeat(int rp) { _currentMusicRepeat = rp; } bool haveChapterPointsChanged() const { return _chapterPointsChanged; } void setChapterPointsChanged(bool cp) { _chapterPointsChanged = cp; } void cutawaySkip() { _vm->_framesEsc = _vm->_scene->isInIntro() ? 2 : 1; } void drawTextList(); int getHeight(bool speech = false) const { if (_vm->getGameId() == GID_IHNM && _vm->_scene->currentChapterNumber() == 8 && !speech) return _vm->getDisplayInfo().height; else return _vm->getDisplayInfo().sceneHeight; } void clearPlacard(); void showPsychicProfile(const char *text); void clearPsychicProfile(); void showIHNMDemoSpecialScreen(); bool isNonInteractiveIHNMDemoPart() { return _vm->isIHNMDemo() && (_sceneNumber >= 144 && _sceneNumber <= 149); } bool isITEPuzzleScene() { return _vm->getGameId() == GID_ITE && _vm->_puzzle->isActive(); } private: void loadScene(LoadSceneParams &loadSceneParams); void loadSceneDescriptor(uint32 resourceId); void loadSceneResourceList(uint32 resourceId); void loadSceneEntryList(const byte* resourcePointer, size_t resourceLength); void processSceneResources(); void getResourceTypes(SAGAResourceTypes *&types, int &typesCount); SagaEngine *_vm; ResourceContext *_sceneContext; Common::Array _sceneLUT; SceneQueueList _sceneQueue; bool _sceneLoaded; int _currentProtag; int _sceneNumber; int _chapterNumber; int _outsetSceneNumber; int _sceneResourceId; int _currentMusicTrack; int _currentMusicRepeat; bool _chapterPointsChanged; bool _inGame; bool _loadDescription; SceneDescription _sceneDescription; size_t _resourceListCount; SceneResourceData *_resourceList; SceneProc *_sceneProc; SceneImage _bg; SceneImage _bgMask; Common::Rect _sceneClip; int _sceneDoors[SCENE_DOORS_MAX]; public: ObjectMap *_actionMap; ObjectMap *_objectMap; SceneEntryList _entryList; StringsTable _sceneStrings; TextList _textList; private: int ITEStartProc(); int IHNMStartProc(); int IHNMCreditsProc(); int DinoStartProc(); int FTA2StartProc(); int FTA2EndProc(FTA2Endings whichEnding); void playMovie(const char *filename); void IHNMLoadCutaways(); bool checkKey(); bool playTitle(int title, int time, int mode = kPanelVideo); bool playLoopingTitle(int title, int seconds); public: static int SC_IHNMIntroMovieProc1(int param, void *refCon); static int SC_IHNMIntroMovieProc2(int param, void *refCon); static int SC_IHNMIntroMovieProc3(int param, void *refCon); static int SC_IHNMCreditsMovieProc(int param, void *refCon); private: int IHNMIntroMovieProc1(int param); int IHNMIntroMovieProc2(int param); int IHNMIntroMovieProc3(int param); int IHNMCreditsMovieProc(int param); public: static int SC_ITEIntroAnimProc(int param, void *refCon); static int SC_ITEIntroCave1Proc(int param, void *refCon); static int SC_ITEIntroCave2Proc(int param, void *refCon); static int SC_ITEIntroCave3Proc(int param, void *refCon); static int SC_ITEIntroCave4Proc(int param, void *refCon); static int SC_ITEIntroValleyProc(int param, void *refCon); static int SC_ITEIntroTreeHouseProc(int param, void *refCon); static int SC_ITEIntroFairePathProc(int param, void *refCon); static int SC_ITEIntroFaireTentProc(int param, void *refCon); private: EventColumns *ITEQueueDialogue(EventColumns *eventColumns, int n_dialogues, const IntroDialogue dialogue[]); EventColumns *ITEQueueCredits(int delta_time, int duration, int n_credits, const IntroCredit credits[]); int ITEIntroAnimProc(int param); int ITEIntroCave1Proc(int param); int ITEIntroCave2Proc(int param); int ITEIntroCave3Proc(int param); int ITEIntroCave4Proc(int param); int ITEIntroValleyProc(int param); int ITEIntroTreeHouseProc(int param); int ITEIntroFairePathProc(int param); int ITEIntroFaireTentProc(int param); }; } // End of namespace Saga #endif