From 1cf5c7f7c91559962ddd8c43af7bf4ce05deebc3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Sep 2016 00:01:25 -0400 Subject: XEEN: More of Darkside endgame sequence --- engines/xeen/dialogs_options.cpp | 4 +- engines/xeen/dialogs_party.cpp | 12 +- engines/xeen/events.h | 1 + engines/xeen/interface.cpp | 8 +- engines/xeen/screen.h | 4 +- engines/xeen/worldofxeen/cutscenes.cpp | 6 +- engines/xeen/worldofxeen/cutscenes.h | 9 + engines/xeen/worldofxeen/darkside_cutscenes.cpp | 372 ++++++++++++++++++++---- engines/xeen/xeen.cpp | 4 +- 9 files changed, 350 insertions(+), 70 deletions(-) diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp index 88ee6d33d3..886c73d1b7 100644 --- a/engines/xeen/dialogs_options.cpp +++ b/engines/xeen/dialogs_options.cpp @@ -186,7 +186,7 @@ void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) { title2 = "start.icn"; Screen &screen = *_vm->_screen; - screen.fadeOut(4); + screen.fadeOut(); screen.loadPalette("dark.pal"); _vm->_events->clearEvents(); } @@ -197,7 +197,7 @@ void WorldOptionsMenu::setBackground(bool doFade) { screen.saveBackground(); if (doFade) - screen.fadeIn(4); + screen.fadeIn(); } void WorldOptionsMenu::openWindow() { diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 88e0b17547..ced778f714 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -86,10 +86,10 @@ void PartyDialog::execute() { if (modeFlag) { screen._windows[0].update(); events.setCursor(0); - screen.fadeIn(4); + screen.fadeIn(); } else { if (_vm->getGameID() == GType_DarkSide) { - screen.fadeOut(4); + screen.fadeOut(); screen._windows[0].update(); } @@ -97,7 +97,7 @@ void PartyDialog::execute() { events.setCursor(0); if (_vm->getGameID() == GType_DarkSide) { - screen.fadeIn(4); + screen.fadeIn(); } } @@ -200,14 +200,14 @@ void PartyDialog::execute() { if (_charList.size() == XEEN_TOTAL_CHARACTERS) { ErrorScroll::show(_vm, YOUR_ROSTER_IS_FULL); } else { - screen.fadeOut(4); + screen.fadeOut(); w.close(); createChar(); party.copyPartyToRoster(); _vm->_saves->writeCharFile(); - screen.fadeOut(4); + screen.fadeOut(); modeFlag = true; breakFlag = true; } @@ -498,7 +498,7 @@ void PartyDialog::createChar() { // Draw the dice drawDice(dice); if (!hasFadedIn) { - screen.fadeIn(4); + screen.fadeIn(); hasFadedIn = true; } diff --git a/engines/xeen/events.h b/engines/xeen/events.h index f8fafca176..36ef939004 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -105,6 +105,7 @@ public: uint32 timeElapsed3() const { return _frameCounter - _gameCounters[3]; } uint32 timeElapsed4() const { return _frameCounter - _gameCounters[4]; } uint32 timeElapsed5() const { return _frameCounter - _gameCounters[5]; } + uint32 getTicks() { return _frameCounter; } bool wait(uint numFrames, bool interruptable = true); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 2516c1b851..6c09b05b60 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1077,12 +1077,12 @@ void Interface::rest() { if (_vm->getRandomNumber(1, 20) == 1) { // Show dream screen.saveBackground(); - screen.fadeOut(4); + screen.fadeOut(); events.hideCursor(); screen.loadBackground("scene1.raw"); screen._windows[0].update(); - screen.fadeIn(4); + screen.fadeIn(); events.updateGameCounter(); while (!_vm->shouldQuit() && events.timeElapsed() < 7) @@ -1100,12 +1100,12 @@ void Interface::rest() { while (!_vm->shouldQuit() && events.timeElapsed() < 7) events.pollEventsAndWait(); - screen.fadeOut(4); + screen.fadeOut(); events.setCursor(0); screen.restoreBackground(); screen._windows[0].update(); - screen.fadeIn(4); + screen.fadeIn(); } party.resetTemps(); diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 8a17d6218d..3f27b33166 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -178,9 +178,9 @@ public: void draw(void *data = nullptr); - void fadeIn(int step); + void fadeIn(int step = 4); - void fadeOut(int step); + void fadeOut(int step = 4); void saveBackground(int slot = 1); diff --git a/engines/xeen/worldofxeen/cutscenes.cpp b/engines/xeen/worldofxeen/cutscenes.cpp index 20b4158c32..701adb6833 100644 --- a/engines/xeen/worldofxeen/cutscenes.cpp +++ b/engines/xeen/worldofxeen/cutscenes.cpp @@ -35,7 +35,7 @@ void Cutscenes::showSubtitles(uint windowIndex) { Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; - if (sound._soundOn) { + if (sound._soundOn || _vm->shouldQuit()) { // Sound is on, so subtitles aren't needed resetSubtitles(); } else { @@ -96,5 +96,9 @@ uint Cutscenes::timeElapsed() { return _vm->_events->timeElapsed1(); } +uint Cutscenes::getSpeakingFrame(uint minFrame, uint maxFrame) { + uint interval = g_system->getMillis() / 100; + return minFrame + interval % (maxFrame + 1 - minFrame); +} } // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/cutscenes.h b/engines/xeen/worldofxeen/cutscenes.h index 895094d3dd..1443ba6ea8 100644 --- a/engines/xeen/worldofxeen/cutscenes.h +++ b/engines/xeen/worldofxeen/cutscenes.h @@ -28,6 +28,10 @@ namespace Xeen { +#define WAIT(time) events.updateGameCounter(); \ + if (events.wait(time)) \ + return false + class XeenEngine; class Cutscenes { @@ -72,6 +76,11 @@ protected: * Returns the number of ticks since the last recordTime */ uint timeElapsed(); + + /** + * Get a speaking frame from a range + */ + uint getSpeakingFrame(uint minFrame, uint maxFrame); }; } // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/xeen/worldofxeen/darkside_cutscenes.cpp index 99f634671a..6c6dc68686 100644 --- a/engines/xeen/worldofxeen/darkside_cutscenes.cpp +++ b/engines/xeen/worldofxeen/darkside_cutscenes.cpp @@ -51,7 +51,7 @@ bool DarkSideCutscenes::showDarkSideTitle() { // Draw the screen and fade it in screen.horizMerge(0); screen.draw(); - screen.fadeIn(4); + screen.fadeIn(); sound.setMusicVolume(0x5f); sound.playFX(1); @@ -60,7 +60,6 @@ bool DarkSideCutscenes::showDarkSideTitle() { int nwcIndex = 0, nwcFrame = 0; for (int idx = 0; idx < 55 && !_vm->shouldQuit(); ++idx) { // Render the next frame - events.updateGameCounter(); screen.vertMerge(0); nwc[nwcIndex].draw(screen, nwcFrame); screen.draw(); @@ -81,13 +80,11 @@ bool DarkSideCutscenes::showDarkSideTitle() { ++nwcFrame; } - if (events.wait(2)) - return false; + WAIT(2); } // Loop for dragon using flyspray for (int idx = 0; idx < 42 && !_vm->shouldQuit(); ++idx) { - events.updateGameCounter(); screen.vertMerge(SCREEN_HEIGHT); nwc[3].draw(screen, idx); screen.draw(); @@ -112,25 +109,22 @@ bool DarkSideCutscenes::showDarkSideTitle() { break; } - if (events.wait(2)) - return false; + WAIT(2); } if (_vm->shouldQuit()) return false; // Pause for a bit - if (events.wait(10)) - return false; + WAIT(10); sound.setMusicVolume(95); screen.fadeOut(8); screen.loadBackground("jvc.raw"); screen.draw(); - screen.fadeIn(4); + screen.fadeIn(); - events.updateGameCounter(); - events.wait(60); + WAIT(60); return true; } @@ -177,7 +171,6 @@ bool DarkSideCutscenes::showDarkSideIntro() { bool fadeFlag = true; for (int yCtr = SCREEN_HEIGHT; yCtr > 0; ) { - events.updateGameCounter(); screen.vertMerge(yp); sprites[0].draw(screen, 0); @@ -197,11 +190,10 @@ bool DarkSideCutscenes::showDarkSideIntro() { yCtr -= timeExpired; yp = MIN((uint)(yp + timeExpired), (uint)200); - if (events.wait(1)) - return false; + WAIT(1); if (fadeFlag) { - screen.fadeIn(4); + screen.fadeIn(); fadeFlag = false; } } @@ -211,21 +203,17 @@ bool DarkSideCutscenes::showDarkSideIntro() { screen.draw(); screen.freePages(); - events.updateGameCounter(); - if (events.wait(30)) - return false; + WAIT(30); // Zoom into the Pharoah's base closeup view for (int idx = 14; idx >= 0; --idx) { - events.updateGameCounter(); sprites[1].draw(screen, 0, Common::Point(XLIST1[idx], YLIST1[idx])); sprites[1].draw(screen, 1, Common::Point(XLIST2[idx], YLIST1[idx])); screen.draw(); if (idx == 2) sound.setMusicVolume(48); - if (events.wait(2)) - return false; + WAIT(2); } return true; @@ -236,34 +224,31 @@ bool DarkSideCutscenes::showDarkSideEnding() { Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; - sound.playSong("dngon3.m"); + //sound.playSong("dngon3.m"); screen.loadBackground("scene1.raw"); screen.loadPalette("endgame.pal"); screen.update(); +/* + screen.fadeIn(); + WAIT(30); - screen.fadeIn(4); - events.updateGameCounter(); - if (events.wait(30)) - return false; - - screen.fadeOut(4); + screen.fadeOut(); screen.loadBackground("scene2-b.raw"); screen.update(); screen.saveBackground(); SpriteResource faceEnd("face.end"); - events.updateGameCounter(); screen.restoreBackground(); faceEnd.draw(screen, 0, Common::Point(29, 76), SPRFLAG_4000); screen.update(); - screen.fadeIn(4); - if (events.wait(1, false)) - return false; + screen.fadeIn(); + WAIT(1); _subtitles.load("special.bin"); recordTime(); resetSubtitles(); + _subtitleLineNum = 21; // Alamar stands up for (int idx = 74; idx > 20; idx -= 2) { @@ -272,20 +257,17 @@ bool DarkSideCutscenes::showDarkSideEnding() { else if (idx == 22) sound.stopSong(); - events.updateGameCounter(); screen.restoreBackground(); faceEnd.draw(screen, 0, Common::Point(29, idx), SPRFLAG_4000); screen.update(); - if (events.wait(2)) - return false; + WAIT(2); } faceEnd.clear(); // Alamar says "Come to me" sound.playSound("come2.voc"); - if (!subtitlesWait(27)) - return false; + WAIT(27); // Show the entire throne room screen.loadBackground("mainback.raw"); @@ -294,25 +276,20 @@ bool DarkSideCutscenes::showDarkSideEnding() { screen.saveBackground(); screen.update(); - events.updateGameCounter(); - if (events.wait(30)) - return false; + WAIT(30); // Silhouette of door opening sound.playSound("door.voc"); for (int idx = 0; idx < 6; ++idx) { - events.updateGameCounter(); screen.restoreBackground(); sc03b.draw(screen, idx, Common::Point(72, 125)); screen.update(); - if (events.wait(4)) - return false; + WAIT(4); } // Silhouette of playing entering for (int idx = 0; idx < 19; ++idx) { - events.updateGameCounter(); screen.restoreBackground(); sc03c.draw(screen, idx, Common::Point(72, 125)); screen.update(); @@ -322,8 +299,7 @@ bool DarkSideCutscenes::showDarkSideEnding() { if (idx == 7 || idx == 16) sound.playFX(8); - if (events.wait(4)) - return false; + WAIT(4); } sc03a.clear(); @@ -341,7 +317,6 @@ bool DarkSideCutscenes::showDarkSideEnding() { screen.horizMerge(); int yp = 101, ctr = 0, frameNum = 0; for (int xp = 0; xp < 320; xp += 2) { - events.updateGameCounter(); screen.horizMerge(xp); disk.draw(screen, frameNum, Common::Point(xp / 2, yp)); @@ -351,8 +326,7 @@ bool DarkSideCutscenes::showDarkSideEnding() { if (!(xp % 22)) sound.playSound(whoosh); - if (events.wait(1)) - return false; + WAIT(1); if (++ctr % 2) frameNum = (frameNum + 1) % 10; @@ -362,8 +336,9 @@ bool DarkSideCutscenes::showDarkSideEnding() { else if (xp > 150) ++yp; } - if (events.wait(10)) - return false; + + whoosh.close(); + WAIT(10); // Play landing thud sound.playSound("thud.voc"); @@ -372,8 +347,299 @@ bool DarkSideCutscenes::showDarkSideEnding() { events.pollEventsAndWait(); } + // Fade over to box opening background + events.updateGameCounter(); + screen.freePages(); + screen.fadeOut(); + screen.loadBackground("sc050001.raw"); + screen.update(); + screen.saveBackground(); + screen.fadeIn(); + events.updateGameCounter(); + + // Box opening + SpriteResource diskOpen[5] = { + SpriteResource("diska.end"), SpriteResource("diskb.end"), + SpriteResource("diskc.end"), SpriteResource("diskd.end"), + SpriteResource("diske.end") + }; + File click("click.voc"); + + for (int idx = 0; idx < 34; ++idx) { + screen.restoreBackground(); + diskOpen[idx / 8].draw(screen, idx % 8, Common::Point(28, 11)); + + WAIT(3); + if (idx == 0 || idx == 2 || idx == 4 || idx == 6) + sound.playSound(click); + else if (idx == 18) + sound.playSound("explosio.voc"); + else if (idx == 9 || idx == 10 || idx == 11 || idx == 12) + sound.playFX(30); + else if (idx == 13) + sound.playFX(14); + } + click.close(); + for (int idx = 0; idx < 5; ++idx) + diskOpen[idx].clear(); + + SpriteResource sc06[2] = { + SpriteResource("sc06a.end"), SpriteResource("sc06b.end") + }; + screen.loadBackground("mainback.raw"); + screen.saveBackground(); + sc06[0].draw(screen, 0); + screen.update(); + sound.playSound("alien2.voc"); + + // Zoomed out throneroom view of beam coming out of box + for (int idx = 0; idx < 20; ++idx) { + if (idx == 6 || idx == 8 || idx == 9 || idx == 10 + || idx == 13 || idx == 15 || idx == 16) + sound.playFX(3); + + screen.restoreBackground(); + sc06[idx / 10].draw(screen, idx % 10); + screen.update(); + + WAIT(3); + } + + screen.fadeOut(); + sc06[0].clear(); + sc06[1].clear(); + + // Corak appearing + SpriteResource sc07[8] = { + SpriteResource("sc07a.end"), SpriteResource("sc07b.end"), + SpriteResource("sc07c.end"), SpriteResource("sc07d.end"), + SpriteResource("sc07e.end"), SpriteResource("sc07f.end"), + SpriteResource("sc07g.end"), SpriteResource("sc07h.end") + }; + + screen.loadBackground("sc070001.raw"); + screen.saveBackground(); + screen.update(); + screen.fadeIn(); + WAIT(2); + + resetSubtitles(); + _subtitleLineNum = 22; + recordTime(); + + for (int idx = 0; idx < 45; ++idx) { + screen.restoreBackground(); + sc07[idx / 6].draw(screen, idx % 6, Common::Point(61, 12)); + + if (_subtitleSize == 0) + screen.update(); + else + showSubtitles(); + + WAIT(2); + if (idx == 40) + _subtitleSize = 1; + else if (idx == 1 || idx == 19) + // Wind storm + sound.playSound("windstor.voc"); + } + + for (int idx = 0; idx < 8; ++idx) + sc07[idx].clear(); + + // Corak?! + sound.playSound("corak2.voc"); + subtitlesWait(30); + + // Yep, that's my name, don't wear it out + SpriteResource sc08("sc08.end"); + resetSubtitles(); + recordTime(); + _subtitleLineNum = 23; + _subtitleSize = 1; + sound.playFX(0); + + for (int idx = 0; idx < 15; ++idx) { + if (idx == 2) + sound.playSound("yes1.voc"); + + // Animate Corak speaking + sc08.draw(screen, sound.isPlaying() ? getSpeakingFrame(0, 2) : 0); + showSubtitles(); + WAIT(3); + } + + do { + sc08.draw(screen, 0); + showSubtitles(); + } while (_subtitleSize); + + sc08.clear(); + + // Nowhere to run to + SpriteResource sc09("sc09.end"); + + screen.loadBackground("sc090001.raw"); + screen.saveBackground(); + screen.update(); + + resetSubtitles(); + recordTime(); + _subtitleLineNum = 24; + _subtitleSize = 1; + + for (int idx = 0; idx < 15; ++idx) { + if (idx == 2) + sound.playSound("nowre1.voc"); + + screen.restoreBackground(); + sc09.draw(screen, getSpeakingFrame(0, 8)); + showSubtitles(); + WAIT(3); + } + + do { + screen.restoreBackground(); + showSubtitles(); + } while (_subtitleSize); + sc09.clear(); + + // Nor do you! + SpriteResource sc10("sc10.end"); + resetSubtitles(); + recordTime(); + _subtitleLineNum = 25; + _subtitleSize = 1; + + for (int idx = 0; idx < 15; ++idx) { + if (idx == 3) + sound.playSound("nordo2.voc"); + + screen.restoreBackground(); + sc09.draw(screen, getSpeakingFrame(0, 1)); + showSubtitles(); + WAIT(3); + } + + do { + screen.restoreBackground(); + showSubtitles(); + } while (_subtitleSize); + sc10.clear(); + */_subtitles.load("special.bin"); + + // Closeup of side of Alamar's helmet + SpriteResource sc11("sc11.end"); + sound.setMusicVolume(95); + sound.playSong("dngon2.m"); + screen.fadeOut(); + screen.loadBackground("blank.raw"); + screen.saveBackground(); + + for (int idx = 0; idx < 15; ++idx) { + screen.restoreBackground(); + sc11.draw(screen, idx, Common::Point(100, 44)); + + if (idx == 0) + screen.fadeIn(); + WAIT(3); + + if (idx == 3) + sound.playSound("click.voc"); + else if (idx == 5) + sound.playSound("airmon.voc"); + } + + screen.fadeOut(); + + // Helmet raises, we see the face appear + for (int idx = 80; idx > 20; idx -= 2) { + screen.restoreBackground(); + sc11.draw(screen, 15, Common::Point(60, 80)); + sc11.draw(screen, 16, Common::Point(61, idx)); + sc11.draw(screen, 17); + screen.update(); + + if (idx == 80) + screen.fadeIn(); + + WAIT(3); + } + + // Sheltem is revealed + sc11.clear(); + screen.fadeOut(); + screen.loadBackground("scene12.raw"); + screen.update(); + screen.fadeIn(); + WAIT(30); + screen.fadeOut(); + + // I'm ready for you this time + SpriteResource sc13("sc13.end"); + resetSubtitles(); + recordTime(); + _subtitleLineNum = 26; + _subtitleSize = 1; + sound.setMusicVolume(48); + + for (int idx = 0; idx < 16; ++idx) { + if (idx == 1) + sound.playSound("ready2.voc"); + + sc13.draw(screen, getSpeakingFrame(0, 3)); + showSubtitles(); + + if (idx == 0) + screen.fadeIn(); + WAIT(3); + } + + do { + sc13.draw(screen, 0); + showSubtitles(); + events.pollEventsAndWait(); + } while (_subtitleSize); + + sc13.clear(); + + // This fight will be your last + SpriteResource sc14("sc14.end"); + resetSubtitles(); + recordTime(); + _subtitleLineNum = 27; + _subtitleSize = 1; + screen.fadeOut(); + screen.loadBackground("blank.raw"); + screen.saveBackground(); + + sc14.draw(screen, 0, Common::Point(37, 37)); + screen.update(); + screen.fadeIn(); + + for (int waveNum = 0; waveNum < 3; ++waveNum) { + for (int idx = 0; idx < 10; ++idx) { + if (waveNum == 0 && idx == 3) + sound.playSound("fight2.voc"); + + screen.restoreBackground(); + sc14.draw(screen, idx, Common::Point(37, 37)); + showSubtitles(); + WAIT(3); + } + } + + while (_subtitleSize) { + showSubtitles(); + events.pollEventsAndWait(); + showSubtitles(); + } + sc14.clear(); + + // Fighting start + - // TODO + // TODO events.wait(5000); freeSubtitles(); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 76eb1b6910..bc18ec09c9 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -304,7 +304,7 @@ void XeenEngine::play() { _interface->startup(); if (_mode == MODE_0) { -// _screen->fadeOut(4); +// _screen->fadeOut(); } _screen->_windows[0].update(); @@ -315,7 +315,7 @@ void XeenEngine::play() { _combat->_moveMonsters = true; if (_mode == MODE_0) { _mode = MODE_1; - _screen->fadeIn(4); + _screen->fadeIn(); } _combat->_moveMonsters = true; -- cgit v1.2.3