/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "common/scummsys.h" #include "xeen/worldofxeen/worldofxeen_menu.h" #include "xeen/worldofxeen/worldofxeen.h" #include "xeen/dialogs/credits_screen.h" #include "xeen/dialogs/dialogs_difficulty.h" #include "xeen/resources.h" namespace Xeen { namespace WorldOfXeen { void MainMenuContainer::show() { MainMenuContainer *menu; switch (g_vm->getGameID()) { case GType_Clouds: menu = new CloudsMainMenuContainer(); break; case GType_DarkSide: menu = new DarkSideMainMenuContainer(); break; case GType_WorldOfXeen: if (g_vm->getIsCD()) menu = new WorldOfXeenCDMainMenuContainer(); else menu = new WorldOfXeenMainMenuContainer(); break; default: error("Invalid game"); } menu->execute(); delete menu; } MainMenuContainer::MainMenuContainer(const char *spritesName1, const char *spritesName2, const char *spritesName3) : _animateCtr(0), _dialog(nullptr) { g_vm->_files->setGameCc(g_vm->getGameID() == GType_Clouds ? 0 : 1); _backgroundSprites.resize(1 + (spritesName2 ? 1 : 0) + (spritesName3 ? 1 : 0)); _backgroundSprites[0].load(spritesName1); if (spritesName2) _backgroundSprites[1].load(spritesName2); if (spritesName3) _backgroundSprites[2].load(spritesName3); _frameCount = 0; for (uint idx = 0; idx < _backgroundSprites.size(); ++idx) _frameCount += _backgroundSprites[idx].size(); } MainMenuContainer::~MainMenuContainer() { delete _dialog; g_vm->_windows->closeAll(); g_vm->_sound->stopAllAudio(); g_vm->_events->clearEvents(); } void MainMenuContainer::draw() { g_vm->_screen->restoreBackground(); _animateCtr = (_animateCtr + 1) % _frameCount; // Draw the next background frame uint frameNum = _animateCtr; for (uint idx = 0; idx < _backgroundSprites.size(); ++idx) { if (frameNum < _backgroundSprites[idx].size()) { _backgroundSprites[idx].draw(0, frameNum); return; } else { frameNum -= _backgroundSprites[idx].size(); } } } void MainMenuContainer::execute() { EventsManager &events = *g_vm->_events; Screen &screen = *g_vm->_screen; bool showFlag = false; // Show the cursor events.clearEvents(); events.setCursor(0); events.showCursor(); screen.doScroll(true, false); while (!g_vm->shouldExit() && g_vm->_gameMode == GMODE_NONE) { // Draw the menu draw(); if (_dialog) _dialog->draw(); // Fade/scroll in screen if first frame showing screen if (!showFlag) { display(); screen.doScroll(false, true); showFlag = true; } // Check for events events.updateGameCounter(); if (events.wait(4, true)) { if (_dialog) { // There's a dialog active, so let it handle the event _dialog->handleEvents(); // If dialog was removed as a result of the event, flag screen for re-showing, // such as returning to main menu from the Credits screen if (!_dialog) showFlag = false; } else { // No active dialog. If Escape pressed, exit game entirely. Otherwise, // open up the main menu dialog PendingEvent pe; if (events.getEvent(pe) && pe._keyState.keycode == Common::KEYCODE_ESCAPE) g_vm->_gameMode = GMODE_QUIT; events.clearEvents(); showMenuDialog(); } } } } /*------------------------------------------------------------------------*/ CloudsMainMenuContainer::CloudsMainMenuContainer() : MainMenuContainer("intro.vga") { } void CloudsMainMenuContainer::display() { FileManager &files = *g_vm->_files; Screen &screen = *g_vm->_screen; Sound &sound = *g_vm->_sound; sound._musicSide = 0; files.setGameCc(0); screen.loadPalette("mm4.pal"); screen.loadBackground("intro.raw"); screen.saveBackground(); if (!sound.isMusicPlaying()) sound.playSong("inn.m"); } void CloudsMainMenuContainer::showMenuDialog() { setOwner(new CloudsMenuDialog(this)); } /*------------------------------------------------------------------------*/ DarkSideMainMenuContainer::DarkSideMainMenuContainer() : MainMenuContainer("title2a.int") { Screen &screen = *g_vm->_screen; Sound &sound = *g_vm->_sound; screen.loadPalette("dark.pal"); screen.fadeIn(0x81); sound._musicSide = 1; sound.playSong("newbrigh.m"); _background.load("title2.int"); } void DarkSideMainMenuContainer::display() { FileManager &files = *g_vm->_files; Screen &screen = *g_vm->_screen; Sound &sound = *g_vm->_sound; _background.draw(0, 0, Common::Point(0, 0)); _background.draw(0, 1, Common::Point(160, 0)); sound._musicSide = 1; files.setGameCc(1); screen.loadPalette("dark.pal"); screen.saveBackground(); if (!sound.isMusicPlaying()) sound.playSong("newbrigh.m"); } void DarkSideMainMenuContainer::showMenuDialog() { setOwner(new DarkSideMenuDialog(this)); } /*------------------------------------------------------------------------*/ WorldOfXeenMainMenuContainer::WorldOfXeenMainMenuContainer() : MainMenuContainer("world.int") { } void WorldOfXeenMainMenuContainer::display() { FileManager &files = *g_vm->_files; Screen &screen = *g_vm->_screen; Sound &sound = *g_vm->_sound; sound._musicSide = 1; files.setGameCc(1); screen.loadPalette("dark.pal"); screen.loadBackground("world.raw"); screen.saveBackground(); if (!sound.isMusicPlaying()) sound.playSong("newbrigh.m"); } void WorldOfXeenMainMenuContainer::showMenuDialog() { setOwner(new WorldMenuDialog(this)); } /*------------------------------------------------------------------------*/ WorldOfXeenCDMainMenuContainer::WorldOfXeenCDMainMenuContainer() : MainMenuContainer("world0.int", "world1.int", "world2.int") { } void WorldOfXeenCDMainMenuContainer::display() { FileManager &files = *g_vm->_files; Screen &screen = *g_vm->_screen; Sound &sound = *g_vm->_sound; sound._musicSide = 1; files.setGameCc(1); screen.loadPalette("dark.pal"); screen.loadBackground("world.raw"); screen.saveBackground(); if (!sound.isMusicPlaying()) sound.playSong("newbrigh.m"); } void WorldOfXeenCDMainMenuContainer::showMenuDialog() { setOwner(new WorldMenuDialog(this)); } /*------------------------------------------------------------------------*/ bool MainMenuDialog::handleEvents() { FileManager &files = *g_vm->_files; checkEvents(g_vm); int difficulty; switch (_buttonValue) { case Common::KEYCODE_s: // Start new game difficulty = DifficultyDialog::show(g_vm); if (difficulty == -1) return true; // Load a new game state and set the difficulty g_vm->_saves->newGame(); g_vm->_party->_difficulty = (Difficulty)difficulty; g_vm->_gameMode = GMODE_PLAY_GAME; break; case Common::KEYCODE_l: { // Load existing game int ccNum = files._ccNum; g_vm->_saves->newGame(); if (!g_vm->_saves->loadGame()) { files.setGameCc(ccNum); return true; } g_vm->_gameMode = GMODE_PLAY_GAME; break; } case Common::KEYCODE_c: case Common::KEYCODE_v: // Show credits CreditsScreen::show(g_vm); break; case Common::KEYCODE_ESCAPE: // Exit dialog (returning to just the animated background) break; default: return false; } // If this point is reached, delete the dialog itself, which will return the main menu // to it's default "No dialog showing" state delete this; return true; } /*------------------------------------------------------------------------*/ CloudsMenuDialog::CloudsMenuDialog(MainMenuContainer *owner) : MainMenuDialog(owner) { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; w.setBounds(Common::Rect(72, 25, 248, g_vm->_gameWon[0] ? 175 : 150)); w.open(); loadButtons(); } CloudsMenuDialog::~CloudsMenuDialog() { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; w.close(); } void CloudsMenuDialog::loadButtons() { _buttonSprites.load("start.icn"); addButton(Common::Rect(93, 53, 227, 73), Common::KEYCODE_s, &_buttonSprites); addButton(Common::Rect(93, 78, 227, 98), Common::KEYCODE_l, &_buttonSprites); addButton(Common::Rect(93, 103, 227, 123), Common::KEYCODE_c, &_buttonSprites); if (g_vm->_gameWon[0]) addButton(Common::Rect(93, 128, 227, 148), Common::KEYCODE_e, &_buttonSprites); } void CloudsMenuDialog::draw() { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; w.frame(); w.writeString(Common::String::format(Res.OPTIONS_MENU, Res.GAME_NAMES[0], g_vm->_gameWon[0] ? 117 : 92, 1992)); drawButtons(&w); } bool CloudsMenuDialog::handleEvents() { if (MainMenuDialog::handleEvents()) return true; switch (_buttonValue) { case Common::KEYCODE_e: if (g_vm->_gameWon[0]) { // Close the window delete this; // Show clouds ending WOX_VM._sound->stopAllAudio(); WOX_VM.showCloudsEnding(g_vm->_finalScore); return true; } break; default: break; } return false; } /*------------------------------------------------------------------------*/ DarkSideMenuDialog::DarkSideMenuDialog(MainMenuContainer *owner) : MainMenuDialog(owner), _firstDraw(true) { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; w.setBounds(Common::Rect(72, 25, 248, 150)); w.open(); loadButtons(); } DarkSideMenuDialog::~DarkSideMenuDialog() { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; w.close(); } void DarkSideMenuDialog::loadButtons() { addButton(Common::Rect(124, 87, 177, 97), Common::KEYCODE_s); addButton(Common::Rect(126, 98, 173, 108), Common::KEYCODE_l); addButton(Common::Rect(91, 110, 209, 120), Common::KEYCODE_c); addButton(Common::Rect(85, 121, 216, 131), Common::KEYCODE_o); } void DarkSideMenuDialog::draw() { Screen &screen = *g_vm->_screen; EventsManager &events = *g_vm->_events; Sound &sound = *g_vm->_sound; Windows &windows = *g_vm->_windows; if (!_firstDraw) return; SpriteResource kludgeSprites("kludge.int"); SpriteResource title2Sprites[8] = { SpriteResource("title2b.int"), SpriteResource("title2c.int"), SpriteResource("title2d.int"), SpriteResource("title2e.int"), SpriteResource("title2f.int"), SpriteResource("title2g.int"), SpriteResource("title2h.int"), SpriteResource("title2i.int"), }; screen.loadBackground("title2b.raw"); kludgeSprites.draw(0, 0, Common::Point(85, 86)); screen.saveBackground(); sound.playSound("elect.voc"); for (int i = 0; i < 30 && !g_vm->shouldExit(); ++i) { events.updateGameCounter(); screen.restoreBackground(); title2Sprites[i / 4].draw(0, i % 4); windows[0].update(); if (i == 19) sound.stopSound(); if (events.wait(2)) break; } events.clearEvents(); sound.stopSound(); screen.restoreBackground(); windows[0].update(); _firstDraw = false; } bool DarkSideMenuDialog::handleEvents() { if (MainMenuDialog::handleEvents()) return true; switch (_buttonValue) { case Common::KEYCODE_o: { // Show other options dialog // Remove this dialog MainMenuContainer *owner = _owner; delete this; // Set the new options dialog owner->setOwner(new OtherOptionsDialog(owner)); return true; } default: break; } return false; } /*------------------------------------------------------------------------*/ WorldMenuDialog::WorldMenuDialog(MainMenuContainer *owner) : MainMenuDialog(owner) { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; w.setBounds(Common::Rect(72, 25, 248, 175)); w.open(); loadButtons(); } WorldMenuDialog::~WorldMenuDialog() { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; w.close(); } void WorldMenuDialog::loadButtons() { _buttonSprites.load("start.icn"); addButton(Common::Rect(93, 53, 227, 73), Common::KEYCODE_s, &_buttonSprites); addButton(Common::Rect(93, 78, 227, 98), Common::KEYCODE_l, &_buttonSprites); addButton(Common::Rect(93, 103, 227, 123), Common::KEYCODE_c, &_buttonSprites); addButton(Common::Rect(93, 128, 227, 148), Common::KEYCODE_o, &_buttonSprites); } void WorldMenuDialog::draw() { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; w.frame(); w.writeString(Common::String::format(Res.OPTIONS_MENU, Res.GAME_NAMES[2], 117, 1993)); drawButtons(&w); } bool WorldMenuDialog::handleEvents() { if (MainMenuDialog::handleEvents()) return true; switch (_buttonValue) { case Common::KEYCODE_o: { // Show other options dialog // Remove this dialog MainMenuContainer *owner = _owner; delete this; // Set the new options dialog owner->setOwner(new OtherOptionsDialog(owner)); return true; } default: break; } return false; } /*------------------------------------------------------------------------*/ OtherOptionsDialog::OtherOptionsDialog(MainMenuContainer *owner) : MenuContainerDialog(owner) { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; int height = (g_vm->getGameID() == GType_WorldOfXeen ? 25 : 0) + (g_vm->getGameID() == GType_WorldOfXeen && g_vm->_gameWon[0] ? 25 : 0) + (g_vm->_gameWon[1] ? 25 : 0) + (g_vm->_gameWon[2] ? 25 : 0) + 75; w.setBounds(Common::Rect(72, 25, 248, 25 + height)); w.open(); loadButtons(); } OtherOptionsDialog::~OtherOptionsDialog() { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; w.close(); } void OtherOptionsDialog::loadButtons() { _buttonSprites.load("special.icn"); Common::Rect r(93, 53, 227, 73); // View Darkside Intro addButton(r, Common::KEYCODE_d, &_buttonSprites); r.translate(0, 25); // View Clouds Intro if (g_vm->getGameID() == GType_WorldOfXeen) { addButton(r, Common::KEYCODE_c, &_buttonSprites); r.translate(0, 25); } else { addButton(Common::Rect(), Common::KEYCODE_INVALID); } // View Darkside End if (g_vm->_gameWon[1]) { addButton(r, Common::KEYCODE_e, &_buttonSprites); r.translate(0, 25); } else { addButton(Common::Rect(), Common::KEYCODE_INVALID); } // View Clouds End if (g_vm->_gameWon[0]) { addButton(r, Common::KEYCODE_v, &_buttonSprites); r.translate(0, 25); } else { addButton(Common::Rect(), Common::KEYCODE_INVALID); } // View World End if (g_vm->_gameWon[2]) { addButton(r, Common::KEYCODE_w, &_buttonSprites); } else { addButton(Common::Rect(), Common::KEYCODE_INVALID); } } void OtherOptionsDialog::draw() { Windows &windows = *g_vm->_windows; Window &w = windows[GAME_WINDOW]; w.frame(); w.writeString(Common::String::format(Res.OPTIONS_MENU, Res.GAME_NAMES[g_vm->getGameID() == GType_WorldOfXeen ? 2 : 1], w.getBounds().height() - 33, 1993)); drawButtons(&w); } bool OtherOptionsDialog::handleEvents() { Sound &sound = *g_vm->_sound; checkEvents(g_vm); switch (_buttonValue) { case Common::KEYCODE_d: delete this; sound.stopAllAudio(); WOX_VM.showDarkSideIntro(false); break; case Common::KEYCODE_c: if (g_vm->getGameID() == GType_WorldOfXeen) { delete this; sound.stopAllAudio(); WOX_VM.showCloudsIntro(); } break; case Common::KEYCODE_e: if (g_vm->_gameWon[1]) { delete this; sound.stopAllAudio(); WOX_VM.showDarkSideEnding(g_vm->_finalScore); } break; case Common::KEYCODE_v: if (g_vm->_gameWon[0]) { delete this; sound.stopAllAudio(); WOX_VM.showCloudsEnding(g_vm->_finalScore); } break; case Common::KEYCODE_w: if (g_vm->_gameWon[2]) { delete this; sound.stopAllAudio(); WOX_VM.showWorldOfXeenEnding(NON_GOOBER, g_vm->_finalScore); } break; case Common::KEYCODE_ESCAPE: // Exit dialog delete this; break; default: return false; } return true; } } // End of namespace WorldOfXeen } // End of namespace Xeen