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

211 lines
7.4 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/gamestate.h"
#include "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/biochips/arthurchip.h"
#include "pegasus/neighborhood/norad/constants.h"
#include "pegasus/neighborhood/norad/norad.h"
#include "pegasus/neighborhood/norad/subplatform.h"
#include "pegasus/neighborhood/norad/alpha/noradalpha.h"
namespace Pegasus {
// As usual, times here are in seconds.
static const TimeValue kNormalSplashStart = 0;
static const TimeValue kNormalSplashStop = 5;
static const TimeValue kPrepSubStart = 5;
static const TimeValue kPrepSubStop = 15;
static const TimeValue kPrepIncompleteStart = 15;
static const TimeValue kPrepIncompleteStop = 19;
static const TimeValue kDamagedStart = 19;
static const TimeValue kDamagedStop = 28;
static const NotificationFlags kNormalSplashFinished = 1;
static const NotificationFlags kPrepSubFinished = kNormalSplashFinished << 1;
static const NotificationFlags kPrepIncompleteFinished = kPrepSubFinished << 1;
static const NotificationFlags kDamagedFinished = kPrepIncompleteFinished << 1;
static const NotificationFlags kPlatformNotificationFlags = kNormalSplashFinished |
kPrepSubFinished |
kPrepIncompleteFinished |
kDamagedFinished;
static const uint16 kSubPreppedBit = (1 << 0);
static const uint16 kWaitingForPlayerBit = (1 << 1);
SubPlatform::SubPlatform(Neighborhood *handler) : GameInteraction(kNoradSubPlatformInteractionID, handler),
_platformMovie(kPlatformMonitorID), _platformNotification(kNoradSubPlatformNotificationID, g_vm) {
_neighborhoodNotification = handler->getNeighborhoodNotification();
}
void SubPlatform::openInteraction() {
_stateBits = 0;
// TODO: These next two lines seem unused?
if (GameState.getNoradSubPrepState() == kSubPrepped)
_stateBits |= kSubPreppedBit;
_stateBits |= kWaitingForPlayerBit;
_platformMovie.initFromMovieFile("Images/Norad Alpha/Platform Monitor Movie");
_platformMovie.setVolume(g_vm->getSoundFXLevel());
_platformMovie.moveElementTo(kNoradPlatformLeft, kNoradPlatformTop);
_platformScale = _platformMovie.getScale();
_platformMovie.setDisplayOrder(kPlatformOrder);
_platformMovie.startDisplaying();
_platformCallBack.setNotification(&_platformNotification);
_platformCallBack.initCallBack(&_platformMovie, kCallBackAtExtremes);
_platformNotification.notifyMe(this, kPlatformNotificationFlags, kPlatformNotificationFlags);
}
void SubPlatform::initInteraction() {
_neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
}
void SubPlatform::closeInteraction() {
_platformNotification.cancelNotification(this);
_platformCallBack.releaseCallBack();
_neighborhoodNotification->cancelNotification(this);
}
void SubPlatform::setSoundFXLevel(const uint16 fxLevel) {
_platformMovie.setVolume(fxLevel);
}
void SubPlatform::receiveNotification(Notification *notification, const NotificationFlags flags) {
FaderMoveSpec loop1Spec, loop2Spec;
ExtraTable::Entry entry;
Norad *owner = (Norad *)getOwner();
if (notification == &_platformNotification) {
switch (flags) {
case kNormalSplashFinished:
_platformMovie.stop();
switch (GameState.getNoradSubPrepState()) {
case kSubNotPrepped:
_platformMovie.setSegment(kPrepIncompleteStart * _platformScale, kPrepIncompleteStop * _platformScale);
_platformMovie.setTime(kPrepIncompleteStart * _platformScale);
_platformCallBack.setCallBackFlag(kPrepIncompleteFinished);
_platformCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
_platformMovie.start();
break;
case kSubPrepped:
_platformMovie.setSegment(kPrepSubStart * _platformScale, kPrepSubStop * _platformScale);
_platformMovie.setTime(kPrepSubStart * _platformScale);
_platformCallBack.setCallBackFlag(kPrepSubFinished);
_platformCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
owner->startExtraSequence(kNorad19PrepSub, 0, kFilterNoInput);
_platformMovie.start();
break;
case kSubDamaged:
// Shouldn't happen.
default:
break;
}
break;
case kPrepSubFinished:
_platformMovie.stop();
_platformMovie.stopDisplaying();
owner->getExtraEntry(kNorad19ExitToSub, entry);
loop1Spec.makeTwoKnotFaderSpec(kNoradAlphaMovieScale, 0, kNoradWarningVolume,
entry.movieEnd - entry.movieStart, 0);
loop1Spec.insertFaderKnot(4560, kNoradWarningVolume);
loop1Spec.insertFaderKnot(5080, 0);
loop2Spec.makeTwoKnotFaderSpec(kNoradAlphaMovieScale, 0, kNoradSuckWindVolume,
entry.movieEnd - entry.movieStart, 0);
loop1Spec.insertFaderKnot(4560, kNoradSuckWindVolume);
loop1Spec.insertFaderKnot(5080, 0);
owner->startExtraSequence(kNorad19ExitToSub, kExtraCompletedFlag, kFilterNoInput);
if (g_arthurChip)
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA07", kArthurNoradEnteredSub);
owner->startLoop1Fader(loop1Spec);
owner->startLoop2Fader(loop2Spec);
break;
case kPrepIncompleteFinished:
((NoradAlpha *)owner)->setSubPrepFailed(true);
g_AIArea->checkMiddleArea();
// Fall through...
case kDamagedFinished:
_platformMovie.stop();
_platformMovie.hide();
_stateBits |= kWaitingForPlayerBit;
allowInput(true);
break;
default:
break;
}
} else if (notification == _neighborhoodNotification && !g_vm->isDVD()) {
allowInput(true);
g_vm->jumpToNewEnvironment(kNoradSubChaseID, kNoRoomID, kNoDirection);
GameState.setScoringEnteredSub(true);
}
}
void SubPlatform::activateHotspots() {
if (_stateBits & kWaitingForPlayerBit)
g_allHotspots.activateOneHotspot(kNorad19ActivateMonitorSpotID);
GameInteraction::activateHotspots();
}
void SubPlatform::clickInHotspot(const Input &input, const Hotspot *spot) {
if (spot->getObjectID() == kNorad19ActivateMonitorSpotID) {
if (GameState.getNoradSubPrepState() == kSubDamaged) {
_platformMovie.setSegment(kDamagedStart * _platformScale, kDamagedStop * _platformScale);
_platformMovie.setTime(kDamagedStart * _platformScale);
_platformCallBack.setCallBackFlag(kDamagedFinished);
} else {
_platformMovie.setSegment(kNormalSplashStart * _platformScale, kNormalSplashStop * _platformScale);
_platformMovie.setTime(kNormalSplashStart * _platformScale);
_platformCallBack.setCallBackFlag(kNormalSplashFinished);
}
_platformCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
_platformMovie.show();
_platformMovie.start();
_platformMovie.redrawMovieWorld();
_stateBits &= ~kWaitingForPlayerBit;
allowInput(false);
} else {
GameInteraction::clickInHotspot(input, spot);
}
}
} // End of namespace Pegasus