From 3d1a43bc5486de8d65b72a5385719e370f159298 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 30 Jan 2010 23:03:07 +0000 Subject: Worked on separating scene logic into separate classes for M4 and MADS svn-id: r47728 --- engines/m4/console.cpp | 24 +- engines/m4/dialogs.cpp | 2 +- engines/m4/globals.cpp | 26 ++- engines/m4/globals.h | 32 ++- engines/m4/gui.cpp | 3 +- engines/m4/hotspot.cpp | 4 +- engines/m4/m4.cpp | 25 +- engines/m4/m4.h | 8 +- engines/m4/scene.cpp | 613 ++++++++++++++++++++++++++----------------------- engines/m4/scene.h | 101 +++++--- 10 files changed, 487 insertions(+), 351 deletions(-) diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp index b4cdaaf86c..84106148cc 100644 --- a/engines/m4/console.cpp +++ b/engines/m4/console.cpp @@ -311,12 +311,12 @@ bool MadsConsole::cmdObject(int argc, const char **argv) { DebugPrintf("Usage: object ['list' | '#objnum' | 'add #objnum']\n"); } else if (!strcmp(argv[1], "list")) { // List of objects - for (uint objStart = 0; objStart < _vm->_globals->getObjectsSize(); objStart += 5) { + for (uint objStart = 0; objStart < _vm->globals()->getObjectsSize(); objStart += 5) { DebugPrintf("%2d - ", objStart); - for (uint objId = objStart; objId < MIN(_vm->_globals->getObjectsSize(), objStart + 5); ++objId) { + for (uint objId = objStart; objId < MIN(_vm->globals()->getObjectsSize(), objStart + 5); ++objId) { if (objId != objStart) DebugPrintf(", "); - uint16 descId = _vm->_globals->getObject(objId)->descId; - DebugPrintf("%s", _vm->_globals->getVocab(descId)); + uint16 descId = _vm->globals()->getObject(objId)->descId; + DebugPrintf("%s", _vm->globals()->getVocab(descId)); } DebugPrintf("\n"); @@ -327,12 +327,12 @@ bool MadsConsole::cmdObject(int argc, const char **argv) { // Add the specified object to the player's inventory int objNum = strToInt(argv[2]); - if ((objNum < 0) || (objNum >= (int)_vm->_globals->getObjectsSize())) + if ((objNum < 0) || (objNum >= (int)_vm->globals()->getObjectsSize())) DebugPrintf("Invalid object specified\n"); else if (_vm->isM4()) DebugPrintf("Not implemented for M4 games\n"); else { - _vm->_scene->getMadsInterface()->addObjectToInventory(objNum); + _vm->_scene->getInterface()->addObjectToInventory(objNum); return false; } @@ -340,19 +340,19 @@ bool MadsConsole::cmdObject(int argc, const char **argv) { // Print the details of a specific object int objNum = strToInt(argv[1]); - if ((objNum < 0) || (objNum >= (int)_vm->_globals->getObjectsSize())) + if ((objNum < 0) || (objNum >= (int)_vm->globals()->getObjectsSize())) DebugPrintf("Invalid object specified\n"); else { - const MadsObject *obj = _vm->_globals->getObject(objNum); + const MadsObject *obj = _vm->globals()->getObject(objNum); - DebugPrintf("Object #%d (%s) room=%d article=%d/%s vocabs=%d", objNum, _vm->_globals->getVocab(obj->descId), + DebugPrintf("Object #%d (%s) room=%d article=%d/%s vocabs=%d", objNum, _vm->globals()->getVocab(obj->descId), obj->roomNumber, (int)obj->article, englishMADSArticleList[obj->article], obj->vocabCount); if (obj->vocabCount > 0) { DebugPrintf(" - "); for (int i = 0; i < obj->vocabCount; ++i) { if (i != 0) DebugPrintf(", "); - DebugPrintf("%s (%d)/%d", _vm->_globals->getVocab(obj->vocabList[i].vocabId), + DebugPrintf("%s (%d)/%d", _vm->globals()->getVocab(obj->vocabList[i].vocabId), obj->vocabList[i].vocabId, obj->vocabList[i].unk); } } @@ -371,13 +371,13 @@ bool MadsConsole::cmdMessage(int argc, const char **argv) { else { int messageIdx = strToInt(argv[1]); if ((argc == 3) && !strcmp(argv[2], "id")) - messageIdx = _vm->_globals->messageIndexOf(messageIdx); + messageIdx = _vm->globals()->messageIndexOf(messageIdx); if (messageIdx == -1) DebugPrintf("Unknown message"); else { - const char *msg = _vm->_globals->loadMessage(messageIdx); + const char *msg = _vm->globals()->loadMessage(messageIdx); Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); _vm->_viewManager->addView(dlg); diff --git a/engines/m4/dialogs.cpp b/engines/m4/dialogs.cpp index 0919039fbc..3af94af262 100644 --- a/engines/m4/dialogs.cpp +++ b/engines/m4/dialogs.cpp @@ -191,7 +191,7 @@ void Dialog::addBarLine() { */ void Dialog::getVocab(int vocabId, char **line) { assert(vocabId > 0); - const char *vocabStr = _madsVm->_globals->getVocab(vocabId); + const char *vocabStr = _madsVm->globals()->getVocab(vocabId); strcpy(*line, vocabStr); if (_commandCase) diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp index d110b67d93..06bbcec9c1 100644 --- a/engines/m4/globals.cpp +++ b/engines/m4/globals.cpp @@ -265,9 +265,19 @@ void Kernel::unpauseEngines() { // TODO: A proper implementation of game unpausing } -//-------------------------------------------------------------------------- +/*--------------------------------------------------------------------------*/ + +Globals::Globals(MadsM4Engine *vm): _vm(vm) { +} + +bool Globals::isInterfaceVisible() { + return _vm->_interfaceView->isVisible(); +} + +/*--------------------------------------------------------------------------*/ -MadsGlobals::MadsGlobals(MadsM4Engine *vm): _vm(vm) { +MadsGlobals::MadsGlobals(MadsEngine *vm): Globals(vm) { + _vm = vm; } MadsGlobals::~MadsGlobals() { @@ -284,10 +294,6 @@ MadsGlobals::~MadsGlobals() { _madsMessages.clear(); } -bool MadsGlobals::isInterfaceVisible() { - return _vm->_interfaceView->isVisible(); -} - void MadsGlobals::loadMadsVocab() { Common::SeekableReadStream *vocabS = _vm->res()->get("vocab.dat"); int curPos = 0; @@ -402,7 +408,13 @@ const char *MadsGlobals::loadMessage(uint index) { return (char*)buffer; } -//-------------------------------------------------------------------------- +/*--------------------------------------------------------------------------*/ + +M4Globals::M4Globals(M4Engine *vm): Globals(vm) { + _vm = vm; +} + +/*--------------------------------------------------------------------------*/ Player::Player(MadsM4Engine *vm) : _vm(vm) { commandsAllowed = true; diff --git a/engines/m4/globals.h b/engines/m4/globals.h index 7e78d2d3a3..9b26e12070 100644 --- a/engines/m4/globals.h +++ b/engines/m4/globals.h @@ -36,6 +36,8 @@ namespace M4 { class MadsM4Engine; +class M4Engine; +class MadsEngine; class ScriptInterpreter; class ScriptFunction; @@ -183,7 +185,28 @@ public: typedef Common::Array > MadsObjectArray; -class MadsGlobals { +class Globals { +private: + MadsM4Engine *_vm; +public: + Globals(MadsM4Engine *vm); + virtual ~Globals() {}; + + bool isInterfaceVisible(); + +}; + +class M4Globals: public Globals { +private: + M4Engine *_vm; +public: + M4Globals(M4Engine *vm); + virtual ~M4Globals() {}; + + bool invSuppressClickSound; +}; + +class MadsGlobals: public Globals { private: struct MessageItem { uint32 id; @@ -192,18 +215,15 @@ private: uint16 compSize; }; - MadsM4Engine *_vm; + MadsEngine *_vm; Common::Array _madsVocab; Common::Array _madsQuotes; Common::Array _madsMessages; MadsObjectArray _madsObjects; public: - MadsGlobals(MadsM4Engine *vm); + MadsGlobals(MadsEngine *vm); ~MadsGlobals(); - bool isInterfaceVisible(); - // M4 variables - bool invSuppressClickSound; // MADS variables bool easyMouse; bool invObjectsStill; diff --git a/engines/m4/gui.cpp b/engines/m4/gui.cpp index abdf0c8e53..8f949de9c5 100644 --- a/engines/m4/gui.cpp +++ b/engines/m4/gui.cpp @@ -1191,7 +1191,8 @@ bool GUIButton::onEvent(M4EventType eventType, int32 param, int x, int y, GUIObj _buttonState = BUTTON_PRESSED; } - _madsVm->_globals->invSuppressClickSound = false; + if (_vm->isM4()) + _m4Vm->globals()->invSuppressClickSound = false; } else { // Button isn't pressed if (_tracking) diff --git a/engines/m4/hotspot.cpp b/engines/m4/hotspot.cpp index af5b6b7574..9849cc7416 100644 --- a/engines/m4/hotspot.cpp +++ b/engines/m4/hotspot.cpp @@ -274,10 +274,10 @@ void HotSpotList::loadHotSpots(Common::SeekableReadStream* hotspotStream, int ho currentHotSpot->setVerb(""); if (currentHotSpot->getVocabID() > 0) - currentHotSpot->setVocab(_madsVm->_globals->getVocab(currentHotSpot->getVocabID())); + currentHotSpot->setVocab(_madsVm->globals()->getVocab(currentHotSpot->getVocabID())); if (currentHotSpot->getVerbID() > 0) - currentHotSpot->setVerb(_madsVm->_globals->getVocab(currentHotSpot->getVerbID())); + currentHotSpot->setVerb(_madsVm->globals()->getVocab(currentHotSpot->getVerbID())); } } } diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index 090921da83..fef646325c 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -118,6 +118,7 @@ MadsM4Engine::MadsM4Engine(OSystem *syst, const M4GameDescription *gameDesc) : Common::addDebugChannel(kDebugConversations, "conversations", "Conversations debugging"); _resourceManager = NULL; + _globals = NULL; } @@ -174,7 +175,6 @@ Common::Error MadsM4Engine::run() { _actor = NULL; } _rails = new Rails(); // needs to be initialized before _scene - _scene = new Scene(this); _dialogs = new Dialogs(); _viewManager = new ViewManager(this); _inventory = new Inventory(this); @@ -298,10 +298,13 @@ void MadsM4Engine::dumpFile(const char* filename, bool uncompress) { M4Engine::M4Engine(OSystem *syst, const M4GameDescription *gameDesc): MadsM4Engine(syst, gameDesc) { // FIXME _m4Vm = this; + + _globals = new M4Globals(this); } M4Engine::~M4Engine() { delete _resourceManager; + delete _globals; } Common::Error M4Engine::run() { @@ -314,7 +317,7 @@ Common::Error M4Engine::run() { // Set up needed common functionality MadsM4Engine::run(); - + _scene = new M4Scene(this); _script->open("m4.dat"); #ifdef SCRIPT_TEST @@ -506,22 +509,24 @@ Common::Error MadsEngine::run() { // Set up needed common functionality MadsM4Engine::run(); + _scene = new MadsScene(this); _palette->setMadsSystemPalette(); _mouse->init("cursor.ss", NULL); _mouse->setCursorNum(0); // Load MADS data files - _globals->loadMadsVocab(); // vocab.dat - _globals->loadMadsQuotes(); // quotes.dat - _globals->loadMadsMessagesInfo(); // messages.dat - _globals->loadMadsObjects(); + MadsGlobals *globals = (MadsGlobals *)_globals; + globals->loadMadsVocab(); // vocab.dat + globals->loadMadsQuotes(); // quotes.dat + globals->loadMadsMessagesInfo(); // messages.dat + globals->loadMadsObjects(); // Setup globals - _madsVm->_globals->easyMouse = true; - _madsVm->_globals->invObjectsStill = false; - _madsVm->_globals->textWindowStill = false; - _madsVm->_globals->storyMode = 0; + globals->easyMouse = true; + globals->invObjectsStill = false; + globals->textWindowStill = false; + globals->storyMode = 0; // Test code to dump all messages to the console //for (int i = 0; i < _globals->getMessagesSize(); i++) diff --git a/engines/m4/m4.h b/engines/m4/m4.h index e8a73debe6..29f3acce34 100644 --- a/engines/m4/m4.h +++ b/engines/m4/m4.h @@ -175,6 +175,8 @@ public: // ResourceManager *_resourceManager; + Globals *_globals; + SaveLoad *_saveLoad; ViewManager *_viewManager; Palette *_palette; @@ -206,7 +208,8 @@ public: virtual Common::Error run(); - MadsGlobals *_globals; + MadsGlobals *globals() { return (MadsGlobals *)_globals; }; + MadsScene *scene() { return (MadsScene *)_scene; }; }; class M4Engine: public MadsM4Engine { @@ -215,6 +218,9 @@ public: virtual ~M4Engine(); virtual Common::Error run(); + + M4Globals *globals() { return (M4Globals *)_globals; }; + M4Scene *scene() { return (M4Scene *)_scene; }; }; // FIXME: remove globals diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp index 0d3e63b781..ca4ba732ee 100644 --- a/engines/m4/scene.cpp +++ b/engines/m4/scene.cpp @@ -52,14 +52,12 @@ Scene::Scene(MadsM4Engine *vm): View(vm, Common::Rect(0, 0, vm->_screen->width() _sceneResources.props = new HotSpotList(); _backgroundSurface = new M4Surface(); _codeSurface = new M4Surface(); - _madsInterfaceSurface = new MadsInterfaceView(vm); - _sceneSprites = NULL; _palData = NULL; _interfacePal = NULL; + _interfaceSurface = NULL; _inverseColorTable = NULL; strcpy(_statusText, ""); _vm->_rails->setCodeSurface(_codeSurface); - _currentAction = kVerbNone; } Scene::~Scene() { @@ -73,7 +71,6 @@ Scene::~Scene() { delete _backgroundSurface; delete _codeSurface; - delete _sceneSprites; // _vm->_palette->deleteAllRanges(); @@ -85,17 +82,6 @@ Scene::~Scene() { void Scene::loadScene(int sceneNumber) { _currentScene = sceneNumber; - // Close the menu if it's active - if (!_vm->isM4()) { - View *mainMenu = _vm->_viewManager->getView(VIEWID_MAINMENU); - if (mainMenu != NULL) { - _vm->_viewManager->deleteView(mainMenu); - } - } - - // TODO: Check if we were loading a game - - // Load scene background and set palette if (_palData) { _vm->_palette->deleteRange(_palData); @@ -106,79 +92,10 @@ void Scene::loadScene(int sceneNumber) { _vm->_palette->deleteRange(_interfacePal); delete _interfacePal; } +} - if (_vm->isM4()) { - _backgroundSurface->loadBackground(sceneNumber); - _palData = NULL; - } else { - // Set system palette entries - _vm->_palette->blockRange(0, 7); - RGB8 sysColors[3] = { {0x1f<<2, 0x2d<<2, 0x31<<2, 0}, {0x24<<2, 0x37<<2, 0x3a<<2, 0}, - {0x00<<2, 0x10<<2, 0x16<<2, 0}}; - _vm->_palette->setPalette(&sysColors[0], 4, 3); - - _backgroundSurface->loadBackground(sceneNumber, &_palData); - _vm->_palette->addRange(_palData); - _backgroundSurface->translate(_palData); - - if (sceneNumber < 900) { - /*_backgroundSurface->fillRect(Common::Rect(0, MADS_SURFACE_HEIGHT, - _backgroundSurface->width(), _backgroundSurface->height()), - _vm->_palette->BLACK);*/ - // TODO: interface palette - _madsInterfaceSurface->madsloadInterface(0, &_interfacePal); - _vm->_palette->addRange(_interfacePal); - _madsInterfaceSurface->translate(_interfacePal); - _backgroundSurface->copyFrom(_madsInterfaceSurface, Common::Rect(0, 0, 320, 44), 0, 200 - 44); - - _madsInterfaceSurface->initialise(); - } - } - - if (_vm->getGameType() == GType_Burger && - sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) - _vm->_interfaceView->setStatusText(""); - - // Load scene def file (*.CHK) - if (_vm->isM4()) { - loadSceneResources(sceneNumber); - loadSceneInverseColorTable(sceneNumber); - } else { - // Don't load other screen resources for system screens - if (sceneNumber >= 900) - return; - - loadSceneHotSpotsMads(sceneNumber); - } - - // TODO: set walker scaling - // TODO: destroy woodscript buffer - - // Load scene walk path file (*.COD/*.WW?) - loadSceneCodes(sceneNumber); - - // Load inverse color table file (*.IPL) - loadSceneInverseColorTable(sceneNumber); - - if (_vm->isM4()) { - - if (_vm->getGameType() != GType_Burger) { - // Load scene sprites file (*.SSB) - loadSceneSprites(sceneNumber); - - // Load scene sprite codes file (*.SSC) - loadSceneSpriteCodes(sceneNumber); - } - - - if (sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) { - _vm->_interfaceView->show(); - showSprites(); - } - } - - // Purge resources - _vm->res()->purge(); +void Scene::show() { + _vm->_viewManager->addView(this); } void Scene::loadSceneResources(int sceneNumber) { @@ -248,27 +165,6 @@ void Scene::loadSceneHotSpotsMads(int sceneNumber) { delete hotspotStream; } -void Scene::loadSceneCodes(int sceneNumber, int index) { - char filename[kM4MaxFilenameSize]; - Common::SeekableReadStream *sceneS; - - if (_vm->isM4()) { - sprintf(filename, "%i.cod", sceneNumber); - sceneS = _vm->res()->openFile(filename); - _codeSurface->loadCodesM4(sceneS); - _vm->res()->toss(filename); - } else if (_vm->getGameType() == GType_Phantom || _vm->getGameType() == GType_DragonSphere) { - sprintf(filename, "rm%i.ww%i", sceneNumber, index); - MadsPack walkData(filename, _vm); - sceneS = walkData.getItemStream(0); - _codeSurface->loadCodesMads(sceneS); - _vm->res()->toss(filename); - } else if (_vm->getGameType() == GType_RexNebular) { - // TODO - return; - } -} - void Scene::loadSceneInverseColorTable(int sceneNumber) { char filename[kM4MaxFilenameSize]; Common::SeekableReadStream *iplS; @@ -287,18 +183,6 @@ void Scene::loadSceneInverseColorTable(int sceneNumber) { } - -void Scene::loadSceneSprites(int sceneNumber) { - char filename[kM4MaxFilenameSize]; - sprintf(filename, "%i.ssb", sceneNumber); - - Common::SeekableReadStream *sceneS = _vm->res()->get(filename); - _sceneSprites = new SpriteAsset(_vm, sceneS, sceneS->size(), filename); - _vm->res()->toss(filename); - - printf("Scene has %d sprites, each one having %d colors\n", _sceneSprites->getCount(), _sceneSprites->getColorCount()); -} - void Scene::loadSceneSpriteCodes(int sceneNumber) { char filename[kM4MaxFilenameSize]; sprintf(filename, "%i.ssc", sceneNumber); @@ -349,60 +233,6 @@ void Scene::showSprites() { // TODO } -void Scene::checkHotspotAtMousePos(int x, int y) { - if (_vm->getGameType() == GType_Riddle) - return; - - // TODO: loads of things to do here, only the mouse cursor and the status - // text is changed for now - - // Only scene hotspots are checked for now, not parallax/props, as the - // latter ones are not used by Orion Burger - HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y); - if (currentHotSpot != NULL && currentHotSpot->getActive()) { - if (_vm->_mouse->getCursorNum() != CURSOR_LOOK && - _vm->_mouse->getCursorNum() != CURSOR_TAKE && - _vm->_mouse->getCursorNum() != CURSOR_USE && - _vm->_interfaceView->_inventory.getSelectedIndex() == -1) { - _vm->_mouse->setCursorNum(currentHotSpot->getCursor()); - } - _vm->_interfaceView->setStatusText(currentHotSpot->getPrep()); - } else { - if (_vm->_mouse->getCursorNum() != CURSOR_LOOK && - _vm->_mouse->getCursorNum() != CURSOR_TAKE && - _vm->_mouse->getCursorNum() != CURSOR_USE && - _vm->_interfaceView->_inventory.getSelectedIndex() == -1) { - _vm->_mouse->setCursorNum(0); - } else { - - } - } -} - -void Scene::checkHotspotAtMousePosMads(int x, int y) { - HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y); - if (currentHotSpot != NULL) { - _vm->_mouse->setCursorNum(currentHotSpot->getCursor()); - - // This is the "easy" interface, which updates the status text when the mouse is moved - // TODO: toggle this code for easy/normal interface mode - char statusText[50]; - int verbId = _currentAction; - if (verbId == kVerbNone) - verbId = currentHotSpot->getVerbID(); - if (verbId == kVerbNone) - verbId = kVerbWalkTo; - - sprintf(statusText, "%s %s\n", _madsVm->_globals->getVocab(verbId), currentHotSpot->getVocab()); - - statusText[0] = toupper(statusText[0]); // capitalize first letter - setMADSStatusText(statusText); - } else { - _vm->_mouse->setCursorNum(0); - setMADSStatusText(""); - } -} - // Test function, shows all scene hotspots void Scene::showHotSpots() { int i = 0; @@ -450,11 +280,6 @@ void Scene::playIntro() { } -void Scene::show() { - _vm->_viewManager->addView(this); - _vm->_viewManager->addView(_madsInterfaceSurface); -} - void Scene::update() { // TODO: Needs a proper implementation // NOTE: Don't copy the background when in M4 mode or WoodScript anims won't be shown @@ -473,7 +298,7 @@ void Scene::update() { _vm->_font->writeString(this, _statusText, (width() - _vm->_font->getWidth(_statusText)) / 2, 142, 0); } - _madsInterfaceSurface->copyTo(this, 0, this->height() - _madsInterfaceSurface->height()); + _interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height()); } } @@ -492,76 +317,13 @@ bool Scene::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &cap switch (eventType) { case MEVENT_LEFT_CLICK: - { - if (_vm->getGameType() == GType_Burger) { - // Place a Wilbur sprite with the correct facing - HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y); - if (currentHotSpot != NULL && currentHotSpot->getActive()) { - update(); - _vm->_actor->setWalkerDirection(currentHotSpot->getFacing()); - /* - int posX = currentHotSpot->getFeetX(); - int posY = currentHotSpot->getFeetY() - - scaleValue(_vm->_actor->getWalkerHeight(), _vm->_actor->getWalkerScaling(), 0); - //_vm->_actor->placeWalkerSpriteAt(0, posX, posY); - */ - - // Player said.... (for scene scripts) - printf("Player said: %s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab()); - - // FIXME: This should be moved somewhere else, and is incomplete - if (_vm->_interfaceView->_inventory.getSelectedIndex() == -1) { - if (_vm->_mouse->getVerb() == NULL) { - strcpy(_vm->_player->verb, currentHotSpot->getVerb()); - } else { - strcpy(_vm->_player->verb, _vm->_mouse->getVerb()); - } - } else { - strcpy(_vm->_player->verb, _vm->_interfaceView->_inventory.getSelectedObjectName()); - } - strcpy(_vm->_player->noun, currentHotSpot->getVocab()); - strcpy(_vm->_player->object, ""); - _vm->_player->commandReady = true; - - printf("## Player said: %s %s\n", _vm->_player->verb, _vm->_player->noun); - - } - } - - if (!_vm->isM4()) { - HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y); - if (currentHotSpot != NULL) { - char statusText[50]; - if (currentHotSpot->getVerbID() != 0) { - sprintf(statusText, "%s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab()); - } else { - sprintf(statusText, "%s %s\n", _madsVm->_globals->getVocab(kVerbWalkTo), currentHotSpot->getVocab()); - } - - statusText[0] = toupper(statusText[0]); // capitalize first letter - setMADSStatusText(statusText); - } - } - } + leftClick(x, y); break; case MEVENT_RIGHT_CLICK: - if (_vm->getGameType() == GType_Burger) { - nextCommonCursor(); - _vm->_interfaceView->_inventory.clearSelected(); - } else { - // ***DEBUG*** - sample dialog display - int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a); - const char *msg = _madsVm->_globals->loadMessage(idx); - Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); - _vm->_viewManager->addView(dlg); - _vm->_viewManager->moveToFront(dlg); - } + rightClick(x, y); break; case MEVENT_MOVE: - if (_vm->isM4()) - checkHotspotAtMousePos(x, y); - else - checkHotspotAtMousePosMads(x, y); + checkHotspotAtMousePos(x, y); break; default: return false; @@ -570,29 +332,6 @@ bool Scene::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &cap return true; } -void Scene::nextCommonCursor() { - int cursorIndex = _vm->_mouse->getCursorNum(); - - switch (cursorIndex) { - case CURSOR_ARROW: - cursorIndex = CURSOR_LOOK; - break; - case CURSOR_LOOK: - cursorIndex = CURSOR_TAKE; - break; - case CURSOR_TAKE: - cursorIndex = CURSOR_USE; - break; - case CURSOR_USE: - cursorIndex = CURSOR_ARROW; - break; - default: - cursorIndex = CURSOR_ARROW; - } - - _vm->_mouse->setCursorNum(cursorIndex); -} - enum boxSprites { topLeft = 0, topRight = 1, @@ -691,7 +430,313 @@ void Scene::showMADSV2TextBox(char *text, int x, int y, char *faceName) { boxSprites->getFrame(bottomRight)->copyTo(_backgroundSurface, curX, curY + 1); } -void Scene::setAction(int action, int objectId) { +/*--------------------------------------------------------------------------*/ + +M4Scene::M4Scene(M4Engine *vm): Scene(vm) { + _vm = vm; + _sceneSprites = NULL; +} + +M4Scene::~M4Scene() { + delete _sceneSprites; +} + +void M4Scene::loadSceneSprites(int sceneNumber) { + char filename[kM4MaxFilenameSize]; + sprintf(filename, "%i.ssb", sceneNumber); + + Common::SeekableReadStream *sceneS = _vm->res()->get(filename); + _sceneSprites = new SpriteAsset(_vm, sceneS, sceneS->size(), filename); + _vm->res()->toss(filename); + + printf("Scene has %d sprites, each one having %d colors\n", _sceneSprites->getCount(), _sceneSprites->getColorCount()); +} + +void M4Scene::loadScene(int sceneNumber) { + Scene::loadScene(sceneNumber); + + _backgroundSurface->loadBackground(sceneNumber); + _palData = NULL; + + if (_vm->getGameType() == GType_Burger && + sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) + _vm->_interfaceView->setStatusText(""); + + // Load scene def file (*.CHK) + loadSceneResources(sceneNumber); + loadSceneInverseColorTable(sceneNumber); + + // TODO: set walker scaling + // TODO: destroy woodscript buffer + + // Load scene walk path file (*.COD/*.WW?) + loadSceneCodes(sceneNumber); + + // Load inverse color table file (*.IPL) + loadSceneInverseColorTable(sceneNumber); + + if (_vm->getGameType() != GType_Burger) { + // Load scene sprites file (*.SSB) + loadSceneSprites(sceneNumber); + + // Load scene sprite codes file (*.SSC) + loadSceneSpriteCodes(sceneNumber); + } + + + if (sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) { + _vm->_interfaceView->show(); + showSprites(); + } + + // Purge resources + _vm->res()->purge(); +} + +void M4Scene::loadSceneCodes(int sceneNumber, int index) { + char filename[kM4MaxFilenameSize]; + Common::SeekableReadStream *sceneS; + + sprintf(filename, "%i.cod", sceneNumber); + sceneS = _vm->res()->openFile(filename); + _codeSurface->loadCodesM4(sceneS); + _vm->res()->toss(filename); +} + +void M4Scene::checkHotspotAtMousePos(int x, int y) { + if (_vm->getGameType() == GType_Riddle) + return; + + // TODO: loads of things to do here, only the mouse cursor and the status + // text is changed for now + + // Only scene hotspots are checked for now, not parallax/props, as the + // latter ones are not used by Orion Burger + HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y); + if (currentHotSpot != NULL && currentHotSpot->getActive()) { + if (_vm->_mouse->getCursorNum() != CURSOR_LOOK && + _vm->_mouse->getCursorNum() != CURSOR_TAKE && + _vm->_mouse->getCursorNum() != CURSOR_USE && + _vm->_interfaceView->_inventory.getSelectedIndex() == -1) { + _vm->_mouse->setCursorNum(currentHotSpot->getCursor()); + } + _vm->_interfaceView->setStatusText(currentHotSpot->getPrep()); + } else { + if (_vm->_mouse->getCursorNum() != CURSOR_LOOK && + _vm->_mouse->getCursorNum() != CURSOR_TAKE && + _vm->_mouse->getCursorNum() != CURSOR_USE && + _vm->_interfaceView->_inventory.getSelectedIndex() == -1) { + _vm->_mouse->setCursorNum(0); + } else { + + } + } +} + +void M4Scene::leftClick(int x, int y) { + if (_vm->getGameType() == GType_Burger) { + // Place a Wilbur sprite with the correct facing + HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y); + if (currentHotSpot != NULL && currentHotSpot->getActive()) { + update(); + _vm->_actor->setWalkerDirection(currentHotSpot->getFacing()); + /* + int posX = currentHotSpot->getFeetX(); + int posY = currentHotSpot->getFeetY() - + scaleValue(_vm->_actor->getWalkerHeight(), _vm->_actor->getWalkerScaling(), 0); + //_vm->_actor->placeWalkerSpriteAt(0, posX, posY); + */ + + // Player said.... (for scene scripts) + printf("Player said: %s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab()); + + // FIXME: This should be moved somewhere else, and is incomplete + if (_vm->_interfaceView->_inventory.getSelectedIndex() == -1) { + if (_vm->_mouse->getVerb() == NULL) { + strcpy(_vm->_player->verb, currentHotSpot->getVerb()); + } else { + strcpy(_vm->_player->verb, _vm->_mouse->getVerb()); + } + } else { + strcpy(_vm->_player->verb, _vm->_interfaceView->_inventory.getSelectedObjectName()); + } + strcpy(_vm->_player->noun, currentHotSpot->getVocab()); + strcpy(_vm->_player->object, ""); + _vm->_player->commandReady = true; + + printf("## Player said: %s %s\n", _vm->_player->verb, _vm->_player->noun); + + } + } +} + +void M4Scene::rightClick(int x, int y) { + if (_vm->getGameType() == GType_Burger) { + nextCommonCursor(); + _vm->_interfaceView->_inventory.clearSelected(); + } +} + +void M4Scene::setAction(int action, int objectId) { +} + +void M4Scene::nextCommonCursor() { + int cursorIndex = _vm->_mouse->getCursorNum(); + + switch (cursorIndex) { + case CURSOR_ARROW: + cursorIndex = CURSOR_LOOK; + break; + case CURSOR_LOOK: + cursorIndex = CURSOR_TAKE; + break; + case CURSOR_TAKE: + cursorIndex = CURSOR_USE; + break; + case CURSOR_USE: + cursorIndex = CURSOR_ARROW; + break; + default: + cursorIndex = CURSOR_ARROW; + } + + _vm->_mouse->setCursorNum(cursorIndex); +} + +/*--------------------------------------------------------------------------*/ + +MadsScene::MadsScene(MadsEngine *vm): Scene(vm) { + _vm = vm; + + _interfaceSurface = new MadsInterfaceView(vm); + _currentAction = kVerbNone; +} + +void MadsScene::loadScene(int sceneNumber) { + // Close the menu if it's active + View *mainMenu = _vm->_viewManager->getView(VIEWID_MAINMENU); + if (mainMenu != NULL) { + _vm->_viewManager->deleteView(mainMenu); + } + + // Handle common scene setting + Scene::loadScene(sceneNumber); + + + // TODO: Check if we were loading a game + + + // Set system palette entries + _vm->_palette->blockRange(0, 7); + RGB8 sysColors[3] = { {0x1f<<2, 0x2d<<2, 0x31<<2, 0}, {0x24<<2, 0x37<<2, 0x3a<<2, 0}, + {0x00<<2, 0x10<<2, 0x16<<2, 0}}; + _vm->_palette->setPalette(&sysColors[0], 4, 3); + + _backgroundSurface->loadBackground(sceneNumber, &_palData); + _vm->_palette->addRange(_palData); + _backgroundSurface->translate(_palData); + + if (sceneNumber < 900) { + /*_backgroundSurface->fillRect(Common::Rect(0, MADS_SURFACE_HEIGHT, + _backgroundSurface->width(), _backgroundSurface->height()), + _vm->_palette->BLACK);*/ + // TODO: interface palette + _interfaceSurface->madsloadInterface(0, &_interfacePal); + _vm->_palette->addRange(_interfacePal); + _interfaceSurface->translate(_interfacePal); + _backgroundSurface->copyFrom(_interfaceSurface, Common::Rect(0, 0, 320, 44), 0, 200 - 44); + + _interfaceSurface->initialise(); + } + + // Don't load other screen resources for system screens + if (sceneNumber >= 900) + return; + + loadSceneHotSpotsMads(sceneNumber); + + // TODO: set walker scaling + // TODO: destroy woodscript buffer + + // Load scene walk path file (*.COD/*.WW?) + loadSceneCodes(sceneNumber); + + // Load inverse color table file (*.IPL) + loadSceneInverseColorTable(sceneNumber); + + // Purge resources + _vm->res()->purge(); +} + +void MadsScene::show() { + Scene::show(); + _vm->_viewManager->addView(_interfaceSurface); +} + +void MadsScene::loadSceneCodes(int sceneNumber, int index) { + char filename[kM4MaxFilenameSize]; + Common::SeekableReadStream *sceneS; + + if (_vm->getGameType() == GType_Phantom || _vm->getGameType() == GType_DragonSphere) { + sprintf(filename, "rm%i.ww%i", sceneNumber, index); + MadsPack walkData(filename, _vm); + sceneS = walkData.getItemStream(0); + _codeSurface->loadCodesMads(sceneS); + _vm->res()->toss(filename); + } else if (_vm->getGameType() == GType_RexNebular) { + // TODO + } +} + +void MadsScene::checkHotspotAtMousePos(int x, int y) { + HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y); + if (currentHotSpot != NULL) { + _vm->_mouse->setCursorNum(currentHotSpot->getCursor()); + + // This is the "easy" interface, which updates the status text when the mouse is moved + // TODO: toggle this code for easy/normal interface mode + char statusText[50]; + int verbId = _currentAction; + if (verbId == kVerbNone) + verbId = currentHotSpot->getVerbID(); + if (verbId == kVerbNone) + verbId = kVerbWalkTo; + + sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(verbId), currentHotSpot->getVocab()); + + statusText[0] = toupper(statusText[0]); // capitalize first letter + setMADSStatusText(statusText); + } else { + _vm->_mouse->setCursorNum(0); + setMADSStatusText(""); + } +} + +void MadsScene::leftClick(int x, int y) { + HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y); + if (currentHotSpot != NULL) { + char statusText[50]; + if (currentHotSpot->getVerbID() != 0) { + sprintf(statusText, "%s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab()); + } else { + sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(kVerbWalkTo), currentHotSpot->getVocab()); + } + + statusText[0] = toupper(statusText[0]); // capitalize first letter + setMADSStatusText(statusText); + } +} + +void MadsScene::rightClick(int x, int y) { + // ***DEBUG*** - sample dialog display + int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a); + const char *msg = _madsVm->globals()->loadMessage(idx); + Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); + _vm->_viewManager->addView(dlg); + _vm->_viewManager->moveToFront(dlg); +} + +void MadsScene::setAction(int action, int objectId) { VALIDATE_MADS; char statusText[50]; @@ -699,12 +744,12 @@ void Scene::setAction(int action, int objectId) { // a second object can be selected, as in 'use gun to shoot person', with requires a target // Set up the new action - strcpy(statusText, _madsVm->_globals->getVocab(action)); + strcpy(statusText, _madsVm->globals()->getVocab(action)); statusText[0] = toupper(statusText[0]); // capitalize first letter if (objectId != -1) { - MadsObject *obj = _madsVm->_globals->getObject(objectId); - sprintf(statusText + strlen(statusText), " %s", _madsVm->_globals->getVocab(obj->descId)); + MadsObject *obj = _madsVm->globals()->getObject(objectId); + sprintf(statusText + strlen(statusText), " %s", _madsVm->globals()->getVocab(obj->descId)); } else { _currentAction = action; } @@ -712,14 +757,13 @@ void Scene::setAction(int action, int objectId) { setMADSStatusText(statusText); } - /*-------------------------------------------------------------------------- * MadsInterfaceView handles the user interface section at the bottom of * game screens in MADS games *-------------------------------------------------------------------------- */ -MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): View(vm, Common::Rect(0, MADS_SURFACE_HEIGHT, +MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): InterfaceView(vm, Common::Rect(0, MADS_SURFACE_HEIGHT, vm->_screen->width(), vm->_screen->height())) { _screenType = VIEWID_INTERFACE; _highlightedElement = -1; @@ -772,8 +816,8 @@ void MadsInterfaceView::initialise() { // Build up the inventory list _inventoryList.clear(); - for (uint i = 0; i < _madsVm->_globals->getObjectsSize(); ++i) { - MadsObject *obj = _madsVm->_globals->getObject(i); + for (uint i = 0; i < _madsVm->globals()->getObjectsSize(); ++i) { + MadsObject *obj = _madsVm->globals()->getObject(i); if (obj->roomNumber == PLAYER_INVENTORY) _inventoryList.push_back(i); } @@ -823,7 +867,7 @@ void MadsInterfaceView::setSelectedObject(int objectNumber) { void MadsInterfaceView::addObjectToInventory(int objectNumber) { if (_inventoryList.indexOf(objectNumber) == -1) { - _madsVm->_globals->getObject(objectNumber)->roomNumber = PLAYER_INVENTORY; + _madsVm->globals()->getObject(objectNumber)->roomNumber = PLAYER_INVENTORY; _inventoryList.push_back(objectNumber); } @@ -847,7 +891,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { ((actionIndex == 0) ? ITEM_SELECTED : ITEM_NORMAL)); // Get the verb action and capitalise it - const char *verbStr = _madsVm->_globals->getVocab(kVerbLook + actionIndex); + const char *verbStr = _madsVm->globals()->getVocab(kVerbLook + actionIndex); strcpy(buffer, verbStr); if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; @@ -875,7 +919,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { if ((_topIndex + i) >= _inventoryList.size()) break; - const char *descStr = _madsVm->_globals->getVocab(_madsVm->_globals->getObject( + const char *descStr = _madsVm->globals()->getVocab(_madsVm->globals()->getObject( _inventoryList[_topIndex + i])->descId); strcpy(buffer, descStr); if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; @@ -898,21 +942,21 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED); spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, 0); - if (!_madsVm->_globals->invObjectsStill && !dialogVisible) { + if (!_madsVm->globals()->invObjectsStill && !dialogVisible) { // If objetcs are to animated, move to the next frame if (++_objectFrameNumber >= (_objectSprites->getCount() * INV_ANIM_FRAME_SPEED)) _objectFrameNumber = 0; } // List the vocab actions for the currently selected object - MadsObject *obj = _madsVm->_globals->getObject(_selectedObject); + MadsObject *obj = _madsVm->globals()->getObject(_selectedObject); int yIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1); for (int i = 0; i < obj->vocabCount; ++i) { const Common::Rect r(_screenObjects[VOCAB_START + i]); // Get the vocab description and capitalise it - const char *descStr = _madsVm->_globals->getVocab(obj->vocabList[i].vocabId); + const char *descStr = _madsVm->globals()->getVocab(obj->vocabList[i].vocabId); strcpy(buffer, descStr); if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; @@ -958,7 +1002,7 @@ bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int _vm->_scene->setAction(kVerbLook + (_highlightedElement - ACTIONS_START)); } else if ((_highlightedElement >= VOCAB_START) && (_highlightedElement < (VOCAB_START + 5))) { // A vocab action was selected - MadsObject *obj = _madsVm->_globals->getObject(_selectedObject); + MadsObject *obj = _madsVm->globals()->getObject(_selectedObject); int vocabIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1); if (vocabIndex >= 0) _vm->_scene->setAction(obj->vocabList[vocabIndex].vocabId, _selectedObject); @@ -1050,5 +1094,4 @@ bool MadsInterfaceView::handleKeypress(int32 keycode) { return false; } - } // End of namespace M4 diff --git a/engines/m4/scene.h b/engines/m4/scene.h index 5f1269c973..c5abcbe201 100644 --- a/engines/m4/scene.h +++ b/engines/m4/scene.h @@ -75,57 +75,96 @@ struct SceneResources { int32 railNodeCount; // # of rails }; -class MadsInterfaceView; +class M4Engine; +class MadsEngine; +class InterfaceView; class Scene: public View { +private: + byte *_inverseColorTable; + HotSpotList _sceneHotspots; + char _statusText[100]; +protected: + int _currentScene; + InterfaceView *_interfaceSurface; + M4Surface *_backgroundSurface; + M4Surface *_codeSurface; + RGBList *_palData; + RGBList *_interfacePal; + SceneResources _sceneResources; public: Scene(MadsM4Engine *vm); - ~Scene(); + virtual ~Scene(); + + // Methods that differ between engines + virtual void loadScene(int sceneNumber); + virtual void loadSceneCodes(int sceneNumber, int index = 0) = 0; + virtual void show(); + virtual void checkHotspotAtMousePos(int x, int y) = 0; + virtual void leftClick(int x, int y) = 0; + virtual void rightClick(int x, int y) = 0; + virtual void setAction(int action, int objectId = -1) = 0; // TODO: perhaps move playIntro() someplace else? void playIntro(); - void show(); - void loadScene(int sceneNumber); void loadSceneResources(int sceneNumber); void loadSceneHotSpotsMads(int sceneNumber); - void loadSceneCodes(int sceneNumber, int index = 0); void loadSceneInverseColorTable(int sceneNumber); - void loadSceneSprites(int sceneNumber); void loadSceneSpriteCodes(int sceneNumber); void showSprites(); - void checkHotspotAtMousePos(int x, int y); - void checkHotspotAtMousePosMads(int x, int y); void showHotSpots(); void showCodes(); int getCurrentScene() { return _currentScene; } - SceneResources getSceneResources() { return _sceneResources; } M4Surface *getBackgroundSurface() const { return _backgroundSurface; } byte *getInverseColorTable() const { return _inverseColorTable; } - MadsInterfaceView *getMadsInterface() { return _madsInterfaceSurface; } - void setAction(int action, int objectId = -1); void update(); void setMADSStatusText(const char *text) { strcpy(_statusText, text); } void showMADSV2TextBox(char *text, int x, int y, char *faceName); + InterfaceView *getInterface() { return _interfaceSurface; } + SceneResources getSceneResources() { return _sceneResources; } void onRefresh(RectList *rects, M4Surface *destSurface); bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); +}; +class M4Scene: public Scene { private: - int _currentScene; - M4Surface *_backgroundSurface; - M4Surface *_codeSurface; - MadsInterfaceView *_madsInterfaceSurface; - byte *_inverseColorTable; - RGBList *_palData; - RGBList *_interfacePal; - SceneResources _sceneResources; - HotSpotList _sceneHotspots; + M4Engine *_vm; SpriteAsset *_sceneSprites; SpriteAsset *_walkerSprite; - int _currentAction; - char _statusText[100]; + void loadSceneSprites(int sceneNumber); void nextCommonCursor(); +public: + M4Scene(M4Engine *vm); + virtual ~M4Scene(); + + // Methods that differ between engines + virtual void loadScene(int sceneNumber); + virtual void loadSceneCodes(int sceneNumber, int index = 0); + virtual void checkHotspotAtMousePos(int x, int y); + virtual void leftClick(int x, int y); + virtual void rightClick(int x, int y); + virtual void setAction(int action, int objectId = -1); +}; + +class MadsScene: public Scene { +private: + MadsEngine *_vm; + + int _currentAction; +public: + MadsScene(MadsEngine *vm); + virtual ~MadsScene() {}; + + // Methods that differ between engines + virtual void loadScene(int sceneNumber); + virtual void loadSceneCodes(int sceneNumber, int index = 0); + virtual void show(); + virtual void checkHotspotAtMousePos(int x, int y); + virtual void leftClick(int x, int y); + virtual void rightClick(int x, int y); + virtual void setAction(int action, int objectId = -1); }; enum InterfaceFontMode {ITEM_NORMAL, ITEM_HIGHLIGHTED, ITEM_SELECTED}; @@ -143,7 +182,17 @@ public: } }; -class MadsInterfaceView: public View { +class InterfaceView: public View { +public: + InterfaceView(MadsM4Engine *vm, const Common::Rect &bounds): View(vm, bounds) {}; + ~InterfaceView() {}; + + virtual void initialise() {}; + virtual void setSelectedObject(int objectNumber) {}; + virtual void addObjectToInventory(int objectNumber) {}; +}; + +class MadsInterfaceView: public InterfaceView { private: IntegerList _inventoryList; RectList _screenObjects; @@ -165,9 +214,9 @@ public: MadsInterfaceView(MadsM4Engine *vm); ~MadsInterfaceView(); - void initialise(); - void setSelectedObject(int objectNumber); - void addObjectToInventory(int objectNumber); + virtual void initialise(); + virtual void setSelectedObject(int objectNumber); + virtual void addObjectToInventory(int objectNumber); void onRefresh(RectList *rects, M4Surface *destSurface); bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); -- cgit v1.2.3