Files
scummvm-cursorfix/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp
2026-02-02 04:50:13 +01:00

392 lines
11 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.
*
* Additional copyright for this file:
* Copyright (C) 1995-1997 Presto Studios, Inc.
*
* 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/>.
*
*/
#include "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/neighborhood/caldoria/caldoria.h"
#include "pegasus/neighborhood/caldoria/caldoria4dsystem.h"
namespace Pegasus {
enum {
kSwitchableSlop = 3 * kCaldoriaFrameDuration,
// Two seconds - some slop
kSwitchableDuration = kCaldoriaMovieScale * 2 - kSwitchableSlop,
// Twelve frames + some slop
kNonswitchableDuration = kCaldoriaFrameDuration * 12 + kSwitchableSlop,
kSwitchable1Start = 0,
kSwitchable1Stop = kSwitchable1Start + kSwitchableDuration,
kSwitchable2Start = kSwitchable1Stop + kNonswitchableDuration,
kSwitchable2Stop = kSwitchable2Start + kSwitchableDuration,
kSwitchable3Start = kSwitchable2Stop + kNonswitchableDuration,
kSwitchable3Stop = kSwitchable3Start + kSwitchableDuration,
kVidPhoneDoneFlag = 1,
kRockMusicLoopIn = 0,
kRockMusicLoopOut = 2088,
kOrchestralMusicLoopIn = 2088,
kOrchestralMusicLoopOut = 4985,
kRhythmsMusicLoopIn = 4985,
kRhythmsMusicLoopOut = 6824,
kAcousticMusicLoopIn = 6824,
kAcousticMusicLoopOut = 9387
};
enum {
k4DVideoMenu,
k4DAudioMenu,
k4DShuttingDown,
// These constants are the exact frame numbers of the sprite movie.
k4DRockChoice = 0,
k4DOrchestralChoice,
k4DRhythmsChoice,
k4DAcousticChoice,
k4DIslandChoice,
k4DDesertChoice,
k4DMountainChoice,
k4DFirstVideoChoice = k4DIslandChoice
};
static const ExtraID s_transitionExtras0[3][3] = {
{ 0xffffffff, k4DIsland0ToDesert0, k4DIsland0ToMountain0 },
{ k4DDesert0ToIsland0, 0xffffffff, k4DDesert0ToMountain0 },
{ k4DMountain0ToIsland0, k4DMountain0ToDesert0, 0xffffffff }
};
static const ExtraID s_transitionExtras1[3][3] = {
{ 0xffffffff, k4DIsland1ToDesert0, k4DIsland1ToMountain0 },
{ k4DDesert1ToIsland0, 0xffffffff, k4DDesert1ToMountain0 },
{ k4DMountain1ToIsland0, k4DMountain1ToDesert0, 0xffffffff }
};
static const ExtraID s_transitionExtras2[3][3] = {
{ 0xffffffff, k4DIsland2ToDesert0, k4DIsland2ToMountain0 },
{ k4DDesert2ToIsland0, 0xffffffff, k4DDesert2ToMountain0 },
{ k4DMountain2ToIsland0, k4DMountain2ToDesert0, 0xffffffff }
};
static const ExtraID s_shutDownExtras[3][3] = {
{ 0xffffffff, k4DIsland1ToIsland0, k4DIsland2ToIsland0 },
{ k4DDesert0ToIsland0, k4DDesert1ToIsland0, k4DDesert2ToIsland0 },
{ k4DMountain0ToIsland0, k4DMountain1ToIsland0, k4DMountain2ToIsland0 }
};
Caldoria4DSystem::Caldoria4DSystem(Neighborhood *owner) : GameInteraction(kCaldoria4DInteractionID, owner),
_4DSpritesMovie(kCaldoria4DSpritesID) {
_4DSpritesScale = 0;
_whichMenu = k4DVideoMenu;
_videoChoice = k4DIslandChoice;
_audioChoice = k4DRockChoice;
_neighborhoodNotification = nullptr;
_loopStart = 0;
_clickedHotspotID = kNoHotSpotID;
g_AIArea->lockAIOut();
}
Caldoria4DSystem::~Caldoria4DSystem() {
g_AIArea->unlockAI();
}
void Caldoria4DSystem::openInteraction() {
_whichMenu = k4DVideoMenu;
_videoChoice = k4DIslandChoice;
_audioChoice = k4DRockChoice;
_clickedHotspotID = kNoHotSpotID;
_4DSpritesMovie.initFromMovieFile("Images/Caldoria/4D Sprites", true);
_4DSpritesMovie.moveElementTo(kCaldoria4DSpritesLeft, kCaldoria4DSpritesTop);
_4DSpritesMovie.setDisplayOrder(k4DSpritesOrder);
_4DSpritesMovie.startDisplaying();
_4DSpritesMovie.show();
_4DSpritesScale = _4DSpritesMovie.getScale();
_neighborhoodNotification = _owner->getNeighborhoodNotification();
_neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
startIdling();
}
void Caldoria4DSystem::loopExtra(const ExtraID extraID) {
ExtraTable::Entry extraEntry;
_owner->getExtraEntry(extraID, extraEntry);
_loopStart = extraEntry.movieStart;
_owner->loopExtraSequence(extraID);
}
void Caldoria4DSystem::useIdleTime() {
if (_whichMenu == k4DShuttingDown) {
TimeValue movieTime = _owner->getNavMovie()->getTime() - _loopStart;
ExtraID extraID;
if (movieTime < kSwitchable1Stop)
extraID = s_shutDownExtras[_videoChoice - k4DFirstVideoChoice][0];
else if (movieTime >= kSwitchable2Start && movieTime < kSwitchable2Stop)
extraID = s_shutDownExtras[_videoChoice - k4DFirstVideoChoice][1];
else if (movieTime >= kSwitchable3Start && movieTime < kSwitchable3Stop)
extraID = s_shutDownExtras[_videoChoice - k4DFirstVideoChoice][2];
else
extraID = 0xffffffff;
if (extraID != 0xffffffff) {
setSpritesMovie();
_loopStart = 0;
_owner->startExtraSequence(extraID, kExtraCompletedFlag, kFilterNoInput);
}
} else if (_clickedHotspotID != kNoHotSpotID) {
TimeValue movieTime = _owner->getNavMovie()->getTime() - _loopStart;
ExtraID extraID;
if (movieTime < kSwitchable1Stop) {
extraID = s_transitionExtras0[_videoChoice - k4DFirstVideoChoice][_clickedHotspotID - kCa4DChoice1SpotID];
_clickedHotspotID = kNoHotSpotID;
} else if (movieTime >= kSwitchable2Start && movieTime < kSwitchable2Stop) {
extraID = s_transitionExtras1[_videoChoice - k4DFirstVideoChoice][_clickedHotspotID - kCa4DChoice1SpotID];
_clickedHotspotID = kNoHotSpotID;
} else if (movieTime >= kSwitchable3Start && movieTime < kSwitchable3Stop) {
extraID = s_transitionExtras2[_videoChoice - k4DFirstVideoChoice][_clickedHotspotID - kCa4DChoice1SpotID];
_clickedHotspotID = kNoHotSpotID;
} else
extraID = 0xffffffff;
if (extraID != 0xffffffff) {
switch (extraID) {
case k4DDesert0ToIsland0:
case k4DMountain0ToIsland0:
case k4DDesert1ToIsland0:
case k4DMountain1ToIsland0:
case k4DDesert2ToIsland0:
case k4DMountain2ToIsland0:
_videoChoice = k4DIslandChoice;
break;
case k4DIsland0ToDesert0:
case k4DMountain0ToDesert0:
case k4DIsland1ToDesert0:
case k4DMountain1ToDesert0:
case k4DIsland2ToDesert0:
case k4DMountain2ToDesert0:
_videoChoice = k4DDesertChoice;
break;
case k4DDesert0ToMountain0:
case k4DIsland0ToMountain0:
case k4DIsland1ToMountain0:
case k4DDesert1ToMountain0:
case k4DIsland2ToMountain0:
case k4DDesert2ToMountain0:
_videoChoice = k4DMountainChoice;
break;
default:
break;
}
setSpritesMovie();
_loopStart = 0;
_owner->startExtraSequence(extraID, kExtraCompletedFlag, kFilterNoInput);
}
}
}
void Caldoria4DSystem::initInteraction() {
setSpritesMovie();
playSound("Rock");
_owner->playSpotSoundSync(kCaldoria4DInstructionsIn, kCaldoria4DInstructionsOut);
loopExtra(k4DIslandLoop);
}
void Caldoria4DSystem::closeInteraction() {
stopIdling();
_neighborhoodNotification->cancelNotification(this);
_4DSpritesMovie.releaseMovie();
_owner->loadAmbientLoops();
}
void Caldoria4DSystem::setSpritesMovie() {
if (_whichMenu == k4DShuttingDown)
_4DSpritesMovie.setTime(_4DSpritesScale * k4DIslandChoice);
else if (_whichMenu == k4DVideoMenu)
_4DSpritesMovie.setTime(_4DSpritesScale * _videoChoice);
else if (_whichMenu == k4DAudioMenu)
_4DSpritesMovie.setTime(_4DSpritesScale * _audioChoice);
_4DSpritesMovie.redrawMovieWorld();
}
void Caldoria4DSystem::handleInput(const Input &input, const Hotspot *cursorSpot) {
if (input.downButtonAnyDown())
return;
if (input.anyDirectionInput())
shutDown4DSystem();
else
GameInteraction::handleInput(input, cursorSpot);
}
void Caldoria4DSystem::activateHotspots() {
GameInteraction::activateHotspots();
g_allHotspots.activateOneHotspot(kCa4DChoice4SpotID);
}
void Caldoria4DSystem::clickInHotspot(const Input &input, const Hotspot *spot) {
switch (spot->getObjectID()) {
case kCa4DVisualSpotID:
if (_whichMenu == k4DAudioMenu) {
_whichMenu = k4DVideoMenu;
setSpritesMovie();
}
break;
case kCa4DAudioSpotID:
if (_whichMenu == k4DVideoMenu) {
_whichMenu = k4DAudioMenu;
setSpritesMovie();
}
break;
case kCa4DChoice1SpotID:
if (_whichMenu == k4DVideoMenu)
makeIslandChoice();
else if (_whichMenu == k4DAudioMenu)
makeRockChoice();
break;
case kCa4DChoice2SpotID:
if (_whichMenu == k4DVideoMenu)
makeDesertChoice();
else if (_whichMenu == k4DAudioMenu)
makeOrchestralChoice();
break;
case kCa4DChoice3SpotID:
if (_whichMenu == k4DVideoMenu)
makeMountainChoice();
else if (_whichMenu == k4DAudioMenu)
makeRhythmsChoice();
break;
case kCa4DChoice4SpotID:
if (_whichMenu == k4DAudioMenu)
makeAcousticChoice();
else
_owner->playSpotSoundSync(kCaldoria4DBlankChoiceIn, kCaldoria4DBlankChoiceOut);
break;
default:
GameInteraction::clickInHotspot(input, spot);
}
}
void Caldoria4DSystem::receiveNotification(Notification *, const NotificationFlags) {
if (_whichMenu == k4DShuttingDown) {
_owner->requestDeleteCurrentInteraction();
} else {
uint32 extraID;
switch (_videoChoice) {
case k4DIslandChoice:
extraID = k4DIslandLoop;
break;
case k4DDesertChoice:
extraID = k4DDesertLoop;
break;
case k4DMountainChoice:
extraID = k4DMountainLoop;
break;
default:
extraID = 0xffffffff;
break;
}
if (extraID != 0xffffffff)
loopExtra(extraID);
}
}
void Caldoria4DSystem::makeIslandChoice() {
if (_videoChoice != k4DIslandChoice && _clickedHotspotID == kNoHotSpotID)
_clickedHotspotID = kCa4DChoice1SpotID;
}
void Caldoria4DSystem::makeDesertChoice() {
if (_videoChoice != k4DDesertChoice && _clickedHotspotID == kNoHotSpotID)
_clickedHotspotID = kCa4DChoice2SpotID;
}
void Caldoria4DSystem::makeMountainChoice() {
if (_videoChoice != k4DMountainChoice && _clickedHotspotID == kNoHotSpotID)
_clickedHotspotID = kCa4DChoice3SpotID;
}
void Caldoria4DSystem::makeRockChoice() {
if (_audioChoice != k4DRockChoice) {
_audioChoice = k4DRockChoice;
setSpritesMovie();
playSound("Rock");
}
}
void Caldoria4DSystem::makeOrchestralChoice() {
if (_audioChoice != k4DOrchestralChoice) {
_audioChoice = k4DOrchestralChoice;
setSpritesMovie();
playSound("Orchestral");
}
}
void Caldoria4DSystem::makeRhythmsChoice() {
if (_audioChoice != k4DRhythmsChoice) {
_audioChoice = k4DRhythmsChoice;
setSpritesMovie();
playSound("Rhythms");
}
}
void Caldoria4DSystem::makeAcousticChoice() {
if (_audioChoice != k4DAcousticChoice) {
_audioChoice = k4DAcousticChoice;
setSpritesMovie();
playSound("Acoustic");
}
}
void Caldoria4DSystem::shutDown4DSystem() {
_whichMenu = k4DShuttingDown;
}
void Caldoria4DSystem::playSound(const Common::String &baseFileName) {
Common::String fileName = "Sounds/Caldoria/" + baseFileName;
// Updated DVD files
if (g_vm->isDVD())
fileName += ".44K";
_owner->loadLoopSound1(Common::Path(fileName + ".aiff"));
}
} // End of namespace Pegasus