Initial commit
This commit is contained in:
224
engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp
Normal file
224
engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp
Normal file
@@ -0,0 +1,224 @@
|
||||
/* 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/items/biochips/arthurchip.h"
|
||||
#include "pegasus/neighborhood/norad/constants.h"
|
||||
#include "pegasus/neighborhood/norad/norad.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/ecrmonitor.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
static const NotificationFlags kECRSection1FinishedFlag = 1;
|
||||
static const NotificationFlags kECRPanFinishedFlag = kECRSection1FinishedFlag << 1;
|
||||
static const NotificationFlags kECRSection2FinishedFlag = kECRPanFinishedFlag << 1;
|
||||
static const NotificationFlags kECRNotificationFlags = kECRSection1FinishedFlag |
|
||||
kECRPanFinishedFlag |
|
||||
kECRSection2FinishedFlag;
|
||||
|
||||
static const TimeValue kSection1Start = 0;
|
||||
static const TimeValue kSection1Stop = 25;
|
||||
static const TimeValue kPanStart = 0;
|
||||
static const TimeValue kPanStop = 20;
|
||||
static const TimeValue kSection2Start = 26;
|
||||
static const TimeValue kSection2Stop = 1000;
|
||||
|
||||
// Seems to be a good value for a 20 second pan.
|
||||
enum {
|
||||
kPanPixelsPerFrame = 8
|
||||
};
|
||||
|
||||
// Interesting times are in seconds.
|
||||
static const TimeValue s_ECRInterestingTimes[] = {
|
||||
0, 1, 2, 10, 25, 26, 56, 64, 72, 80, 88, 94, 102, 108, 116, 999
|
||||
};
|
||||
|
||||
// Index into s_ECRInterestingTimes of interesting time before security pan.
|
||||
static const int kBeforePanTime = 3;
|
||||
|
||||
// Index into s_ECRInterestingTimes of interesting time after security pan.
|
||||
static const int kAfterPanTime = 5;
|
||||
|
||||
NoradAlphaECRMonitor::NoradAlphaECRMonitor(Neighborhood *nextHandler) : GameInteraction(kNoradECRMonitorInteractionID, nextHandler),
|
||||
_ecrSlideShowNotification(kNoradECRNotificationID, g_vm), _ecrMovie(kECRSlideShowMovieID),
|
||||
_ecrPan(kECRPanID) {
|
||||
}
|
||||
|
||||
void NoradAlphaECRMonitor::receiveNotification(Notification *, const NotificationFlags flags) {
|
||||
if (flags & kECRSection1FinishedFlag)
|
||||
ecrSection1Finished();
|
||||
else if (flags & kECRPanFinishedFlag)
|
||||
ecrPanFinished();
|
||||
else if (flags & kECRSection2FinishedFlag)
|
||||
ecrSection2Finished();
|
||||
}
|
||||
|
||||
int NoradAlphaECRMonitor::findCurrentInterestingTime() {
|
||||
TimeValue time = _ecrMovie.getTime();
|
||||
TimeScale scale = _ecrMovie.getScale();
|
||||
|
||||
for (int i = ARRAYSIZE(s_ECRInterestingTimes) - 1; i >= 0; i--)
|
||||
if (time >= s_ECRInterestingTimes[i] * scale)
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NoradAlphaECRMonitor::skipToNextInterestingTime() {
|
||||
if (_ecrMovie.isRunning()) {
|
||||
int interestingTime = findCurrentInterestingTime();
|
||||
_ecrMovie.setTime(s_ECRInterestingTimes[interestingTime + 1] * _ecrMovie.getScale());
|
||||
_ecrMovie.redrawMovieWorld();
|
||||
} else if (_ecrPan.isRunning()) {
|
||||
_ecrPanCallBack.cancelCallBack();
|
||||
ecrPanFinished();
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlphaECRMonitor::skipToPreviousInterestingTime() {
|
||||
if (_ecrPan.isRunning()) {
|
||||
_ecrPan.stop();
|
||||
_ecrPan.stopDisplaying();
|
||||
_ecrPanCallBack.cancelCallBack();
|
||||
|
||||
_ecrMovieCallBack.setCallBackFlag(kECRSection1FinishedFlag);
|
||||
_ecrMovieCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
|
||||
TimeScale scale = _ecrMovie.getScale();
|
||||
_ecrMovie.setSegment(kSection1Start * scale, kSection1Stop * scale + 1);
|
||||
_ecrMovie.setTime(s_ECRInterestingTimes[kBeforePanTime] * scale);
|
||||
_ecrMovie.start();
|
||||
} else {
|
||||
int interestingTime = findCurrentInterestingTime();
|
||||
|
||||
if (interestingTime == kAfterPanTime) {
|
||||
_ecrMovieCallBack.cancelCallBack();
|
||||
TimeScale scale = _ecrMovie.getScale();
|
||||
_ecrMovie.setSegment(kSection1Start * scale, kSection1Stop * scale + 1);
|
||||
_ecrMovie.setTime(kSection1Stop * scale);
|
||||
ecrSection1Finished();
|
||||
} else if (interestingTime == 0) {
|
||||
_ecrMovie.setTime(kSection1Start * _ecrMovie.getScale());
|
||||
_ecrMovie.redrawMovieWorld();
|
||||
} else {
|
||||
_ecrMovie.setTime(s_ECRInterestingTimes[interestingTime - 1] * _ecrMovie.getScale());
|
||||
_ecrMovie.redrawMovieWorld();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlphaECRMonitor::handleInput(const Input &input, const Hotspot *cursorSpot) {
|
||||
if (isInteracting()) {
|
||||
if (input.rightButtonDown())
|
||||
skipToNextInterestingTime();
|
||||
else if (input.leftButtonDown())
|
||||
skipToPreviousInterestingTime();
|
||||
else
|
||||
InputHandler::handleInput(input, cursorSpot);
|
||||
} else {
|
||||
InputHandler::handleInput(input, cursorSpot);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlphaECRMonitor::ecrSection1Finished() {
|
||||
_ecrMovie.stop();
|
||||
_ecrPanCallBack.setNotification(&_ecrSlideShowNotification);
|
||||
_ecrPanCallBack.initCallBack(&_ecrPan, kCallBackAtExtremes);
|
||||
_ecrPanCallBack.setCallBackFlag(kECRPanFinishedFlag);
|
||||
_ecrSlideShowNotification.notifyMe(this, kECRNotificationFlags, kECRNotificationFlags);
|
||||
_ecrPanCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
_ecrPan.startDisplaying();
|
||||
_ecrPan.show();
|
||||
|
||||
TimeScale scale = _ecrPan.getScale();
|
||||
_ecrPan.setSegment(kPanStart * scale, kPanStop * scale);
|
||||
_ecrPan.setTime(0);
|
||||
_ecrPan.start();
|
||||
}
|
||||
|
||||
void NoradAlphaECRMonitor::ecrPanFinished() {
|
||||
_ecrPan.stop();
|
||||
_ecrPan.stopDisplaying();
|
||||
_ecrMovieCallBack.setCallBackFlag(kECRSection2FinishedFlag);
|
||||
_ecrMovieCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
|
||||
TimeScale scale = _ecrMovie.getScale();
|
||||
_ecrMovie.setSegment(kSection2Start * scale, kSection2Stop * scale);
|
||||
_ecrMovie.start();
|
||||
}
|
||||
|
||||
void NoradAlphaECRMonitor::ecrSection2Finished() {
|
||||
_ecrMovie.stop();
|
||||
_ecrMovie.stopDisplaying();
|
||||
}
|
||||
|
||||
void NoradAlphaECRMonitor::openInteraction() {
|
||||
// Initialize the security pan.
|
||||
_ecrPan.initFromMovieFile("Images/Norad Alpha/Security Pan.pano");
|
||||
_ecrPan.initMaskFromPICTFile("Images/Norad Alpha/Security Pan Mask");
|
||||
_ecrPan.setBounds(Common::Rect(kECRPanLeft, kECRPanTop, kECRPanRight, kECRPanBottom));
|
||||
_ecrPan.setDisplayOrder(kECRPanOrder);
|
||||
_ecrPan.setScale(15); // 15 fps.
|
||||
|
||||
// Begin the lame ECR slide show.
|
||||
// clone2727: I didn't say it :P
|
||||
_ecrMovie.initFromMovieFile("Images/Norad Alpha/ECR Monitor Movie");
|
||||
|
||||
_ecrMovieCallBack.setNotification(&_ecrSlideShowNotification);
|
||||
_ecrMovieCallBack.initCallBack(&_ecrMovie, kCallBackAtExtremes);
|
||||
_ecrMovieCallBack.setCallBackFlag(kECRSection1FinishedFlag);
|
||||
|
||||
_ecrSlideShowNotification.notifyMe(this, kECRNotificationFlags, kECRNotificationFlags);
|
||||
_ecrMovieCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
|
||||
_ecrMovie.moveElementTo(kECRSlideShowLeft, kECRSlideShowTop);
|
||||
_ecrMovie.setDisplayOrder(kECRMonitorOrder);
|
||||
_ecrMovie.startDisplaying();
|
||||
_ecrMovie.show();
|
||||
_ecrMovie.redrawMovieWorld();
|
||||
|
||||
TimeScale scale = _ecrMovie.getScale();
|
||||
_ecrMovie.setSegment(kSection1Start * scale, kSection1Stop * scale + 1);
|
||||
|
||||
_ecrMovie.start();
|
||||
}
|
||||
|
||||
void NoradAlphaECRMonitor::closeInteraction() {
|
||||
_ecrMovieCallBack.releaseCallBack();
|
||||
_ecrMovie.stop();
|
||||
_ecrMovie.stopDisplaying();
|
||||
_ecrMovie.releaseMovie();
|
||||
_ecrMovieCallBack.releaseCallBack();
|
||||
|
||||
_ecrPanCallBack.releaseCallBack();
|
||||
_ecrPan.stop();
|
||||
_ecrPan.stopDisplaying();
|
||||
_ecrPan.releasePanorama();
|
||||
_ecrPanCallBack.releaseCallBack();
|
||||
|
||||
if (g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBB33", kArthurNoradAtSecurityMonitor);
|
||||
}
|
||||
|
||||
} // End of namespace Pegasus
|
||||
64
engines/pegasus/neighborhood/norad/alpha/ecrmonitor.h
Normal file
64
engines/pegasus/neighborhood/norad/alpha/ecrmonitor.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_ecrMONITOR_H
|
||||
#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_ecrMONITOR_H
|
||||
|
||||
#include "pegasus/interaction.h"
|
||||
#include "pegasus/notification.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/panoramascroll.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
class NoradAlphaECRMonitor : public GameInteraction, public NotificationReceiver {
|
||||
public:
|
||||
NoradAlphaECRMonitor(Neighborhood *);
|
||||
~NoradAlphaECRMonitor() override {}
|
||||
|
||||
void handleInput(const Input &, const Hotspot *) override;
|
||||
|
||||
protected:
|
||||
void openInteraction() override;
|
||||
void closeInteraction() override;
|
||||
|
||||
void receiveNotification(Notification *, const NotificationFlags) override;
|
||||
|
||||
void ecrSection1Finished();
|
||||
void ecrPanFinished();
|
||||
void ecrSection2Finished();
|
||||
|
||||
int findCurrentInterestingTime();
|
||||
void skipToNextInterestingTime();
|
||||
void skipToPreviousInterestingTime();
|
||||
|
||||
Notification _ecrSlideShowNotification;
|
||||
Movie _ecrMovie;
|
||||
NotificationCallBack _ecrMovieCallBack;
|
||||
PanoramaScroll _ecrPan;
|
||||
NotificationCallBack _ecrPanCallBack;
|
||||
};
|
||||
|
||||
} // End of namespace Pegasus
|
||||
|
||||
#endif
|
||||
459
engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp
Normal file
459
engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp
Normal file
@@ -0,0 +1,459 @@
|
||||
/* 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/items/biochips/arthurchip.h"
|
||||
#include "pegasus/items/inventory/airmask.h"
|
||||
#include "pegasus/neighborhood/norad/constants.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/fillingstation.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/noradalpha.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
static const NotificationFlags kFSPowerUpFinishedFlag = 1;
|
||||
static const NotificationFlags kFSSplashFinishedFlag = kFSPowerUpFinishedFlag << 1;
|
||||
static const NotificationFlags kFSIntakeWarningFinishedFlag = kFSSplashFinishedFlag << 1;
|
||||
static const NotificationFlags kFSIntakeHiliteFinishedFlag = kFSIntakeWarningFinishedFlag << 1;
|
||||
static const NotificationFlags kFSDispenseHiliteFinishedFlag = kFSIntakeHiliteFinishedFlag << 1;
|
||||
static const NotificationFlags kFSArHiliteFinishedFlag = kFSDispenseHiliteFinishedFlag << 1;
|
||||
static const NotificationFlags kFSCO2HiliteFinishedFlag = kFSArHiliteFinishedFlag << 1;
|
||||
static const NotificationFlags kFSHeHiliteFinishedFlag = kFSCO2HiliteFinishedFlag << 1;
|
||||
static const NotificationFlags kFSOHiliteFinishedFlag = kFSHeHiliteFinishedFlag << 1;
|
||||
static const NotificationFlags kFSNHiliteFinishedFlag = kFSOHiliteFinishedFlag << 1;
|
||||
|
||||
static const NotificationFlags kFSNotificationFlags = kFSPowerUpFinishedFlag |
|
||||
kFSSplashFinishedFlag |
|
||||
kFSIntakeWarningFinishedFlag |
|
||||
kFSIntakeHiliteFinishedFlag |
|
||||
kFSDispenseHiliteFinishedFlag |
|
||||
kFSArHiliteFinishedFlag |
|
||||
kFSCO2HiliteFinishedFlag |
|
||||
kFSHeHiliteFinishedFlag |
|
||||
kFSOHiliteFinishedFlag |
|
||||
kFSNHiliteFinishedFlag;
|
||||
|
||||
static const int16 kNoState = 0;
|
||||
static const int16 kMainMenu = 1;
|
||||
static const int16 kWaitingForAttach = 2;
|
||||
static const int16 kDispenseMenu = 3;
|
||||
static const int16 kWaitingForDispense = 4;
|
||||
|
||||
// Dummy itemIDs
|
||||
static const ItemID kCO2Item = 10000;
|
||||
static const ItemID kHeItem = 10001;
|
||||
|
||||
// Interactive points.
|
||||
enum {
|
||||
kFSPowerUpStartStart = 0,
|
||||
kFSPowerUpStartStop = 600,
|
||||
kFSSplashStart = 600,
|
||||
kFSSplashStop = 7800,
|
||||
kFSSplashIntakeStart = 7800,
|
||||
kFSSplashIntakeStop = 18600,
|
||||
|
||||
kFSMainMenu = 18600,
|
||||
kFSIntakeHiliteStart = 19200,
|
||||
kFSIntakeHiliteStop = 19800,
|
||||
kFSDispenseHiliteStart = 19800,
|
||||
kFSDispenseHiliteStop = 20400,
|
||||
|
||||
kFSDispenseMenu = 20400,
|
||||
|
||||
kFSArHiliteStart = 21000,
|
||||
kFSArHiliteStop = 21600,
|
||||
kFSArAttach = 21600,
|
||||
kFSArFilledStart = 22200,
|
||||
kFSArFilledStop = 25200,
|
||||
kFSArIncompatibleStart = 25200,
|
||||
kFSArIncompatibleStop = 30000,
|
||||
|
||||
kFSCO2HiliteStart = 30000,
|
||||
kFSCO2HiliteStop = 30600,
|
||||
kFSCO2Attach = 30600,
|
||||
kFSCO2FilledStart = 31200,
|
||||
kFSCO2FilledStop = 34200,
|
||||
kFSCO2IncompatibleStart = 34200,
|
||||
kFSCO2IncompatibleStop = 39000,
|
||||
|
||||
kFSHeHiliteStart = 39000,
|
||||
kFSHeHiliteStop = 39600,
|
||||
kFSHeAttach = 39600,
|
||||
kFSHeFilledStart = 40200,
|
||||
kFSHeFilledStop = 43200,
|
||||
kFSHeIncompatibleStart = 43200,
|
||||
kFSHeIncompatibleStop = 48000,
|
||||
|
||||
kFSOHiliteStart = 48000,
|
||||
kFSOHiliteStop = 48600,
|
||||
kFSOAttach = 48600,
|
||||
kFSOFilledStart = 49200,
|
||||
kFSOFilledStop = 52200,
|
||||
kFSOIncompatibleStart = 52200,
|
||||
kFSOIncompatibleStop = 57000,
|
||||
|
||||
kFSNHiliteStart = 57000,
|
||||
kFSNHiliteStop = 57600,
|
||||
kFSNAttach = 57600,
|
||||
kFSNFilledStart = 58200,
|
||||
kFSNFilledStop = 61200,
|
||||
kFSNIncompatibleStart = 61200,
|
||||
kFSNIncompatibleStop = 66000,
|
||||
|
||||
kFSIntakeMenu = 66000,
|
||||
kFSIntakeInProgressStart = 66600,
|
||||
kFSIntakeInProgressStop = 69600
|
||||
};
|
||||
|
||||
NoradAlphaFillingStation::NoradAlphaFillingStation(Neighborhood *owner) : GameInteraction(kNoradFillingStationInteractionID, owner),
|
||||
_rightSideMovie(kN01RightSideID), _rightSideNotification(kNoradFillingStationNotificationID, g_vm) {
|
||||
_state = kNoState;
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::openInteraction() {
|
||||
_rightSideMovie.initFromMovieFile("Images/Norad Alpha/N01W Right Side");
|
||||
_rightSideMovie.moveElementTo(kNoradAlpha01RightSideLeft, kNoradAlpha01RightSideTop);
|
||||
_rightSideMovie.setDisplayOrder(kN01RightSideOrder);
|
||||
_rightSideMovie.startDisplaying();
|
||||
_rightSideCallBack.setNotification(&_rightSideNotification);
|
||||
_rightSideCallBack.initCallBack(&_rightSideMovie, kCallBackAtExtremes);
|
||||
_rightSideCallBack.setCallBackFlag(kFSPowerUpFinishedFlag);
|
||||
_rightSideNotification.notifyMe(this, kFSNotificationFlags, kFSNotificationFlags);
|
||||
_rightSideCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
_rightSideMovie.show();
|
||||
_rightSideMovie.redrawMovieWorld();
|
||||
_rightSideMovie.setSegment(kFSPowerUpStartStart, kFSPowerUpStartStop);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::initInteraction() {
|
||||
allowInput(false);
|
||||
|
||||
_rightSideMovie.setRate(2);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::closeInteraction() {
|
||||
_rightSideMovie.stop();
|
||||
_rightSideMovie.stopDisplaying();
|
||||
_rightSideMovie.releaseMovie();
|
||||
_rightSideCallBack.releaseCallBack();
|
||||
((NoradAlpha *)getOwner())->turnOffFillingStation();
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::setStaticState(TimeValue time, int16 state) {
|
||||
_rightSideMovie.stop();
|
||||
_rightSideMovie.setSegment(0, _rightSideMovie.getDuration());
|
||||
_rightSideMovie.setTime(time);
|
||||
_rightSideMovie.redrawMovieWorld();
|
||||
_state = state;
|
||||
allowInput(true);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::setSegmentState(TimeValue start, TimeValue stop, NotificationFlags flag, int16 state) {
|
||||
_rightSideMovie.stop();
|
||||
_rightSideMovie.setSegment(start, stop);
|
||||
_rightSideMovie.setTime(start);
|
||||
_rightSideCallBack.setCallBackFlag(flag);
|
||||
_rightSideCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
_state = state;
|
||||
allowInput(false);
|
||||
_rightSideMovie.setRate(2);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::powerUpFinished() {
|
||||
((NoradAlpha *)getOwner())->turnOnFillingStation();
|
||||
setSegmentState(kFSSplashStart, kFSSplashStop, kFSSplashFinishedFlag, kNoState);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::splashFinished() {
|
||||
if (GameState.getNoradGassed())
|
||||
setSegmentState(kFSSplashIntakeStart, kFSSplashIntakeStop, kFSIntakeWarningFinishedFlag, kNoState);
|
||||
else
|
||||
intakeWarningFinished();
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::intakeWarningFinished() {
|
||||
setStaticState(kFSMainMenu, kMainMenu);
|
||||
if (g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA29", kArthurNoradSawIntakeWarning);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::showIntakeInProgress(uint16 numSeconds) {
|
||||
if (numSeconds == 0) {
|
||||
setSegmentState(kFSIntakeInProgressStart, kFSIntakeInProgressStop, kFSIntakeWarningFinishedFlag, kNoState);
|
||||
Item *item = ((NoradAlpha *)getOwner())->getFillingItem();
|
||||
|
||||
if (item->getObjectID() == kGasCanister) {
|
||||
GameState.setNoradGassed(true);
|
||||
((NoradAlpha *)getOwner())->checkAirMask();
|
||||
getOwner()->restoreStriding(kNorad03, kEast, kAltNoradAlphaNormal);
|
||||
}
|
||||
} else {
|
||||
setSegmentState(kFSIntakeInProgressStart, kFSIntakeInProgressStart + _rightSideMovie.getScale() * numSeconds,
|
||||
kFSIntakeWarningFinishedFlag, kNoState);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::intakeHighlightFinished() {
|
||||
_rightSideMovie.stop();
|
||||
|
||||
if (GameState.getNoradGassed()) {
|
||||
showIntakeInProgress(2);
|
||||
} else {
|
||||
Item *item = ((NoradAlpha *)getOwner())->getFillingItem();
|
||||
if (item)
|
||||
showIntakeInProgress(0);
|
||||
else
|
||||
setStaticState(kFSIntakeMenu, kWaitingForAttach);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::dispenseHighlightFinished() {
|
||||
setStaticState(kFSDispenseMenu, kDispenseMenu);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::dispenseGas() {
|
||||
Item *item = ((NoradAlpha *)getOwner())->getFillingItem();
|
||||
|
||||
if (item) {
|
||||
if (item->getObjectID() != _dispenseItemID)
|
||||
switch (_dispenseItemID) {
|
||||
case kArgonCanister:
|
||||
setSegmentState(kFSArIncompatibleStart, kFSArIncompatibleStop,
|
||||
kFSIntakeWarningFinishedFlag, kNoState);
|
||||
break;
|
||||
case kCO2Item:
|
||||
setSegmentState(kFSCO2IncompatibleStart, kFSCO2IncompatibleStop,
|
||||
kFSIntakeWarningFinishedFlag, kNoState);
|
||||
break;
|
||||
case kHeItem:
|
||||
setSegmentState(kFSHeIncompatibleStart, kFSHeIncompatibleStop,
|
||||
kFSIntakeWarningFinishedFlag, kNoState);
|
||||
break;
|
||||
case kAirMask:
|
||||
setSegmentState(kFSOIncompatibleStart, kFSOIncompatibleStop,
|
||||
kFSIntakeWarningFinishedFlag, kNoState);
|
||||
break;
|
||||
case kNitrogenCanister:
|
||||
setSegmentState(kFSNIncompatibleStart, kFSNIncompatibleStop,
|
||||
kFSIntakeWarningFinishedFlag, kNoState);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (_dispenseItemID == kArgonCanister) {
|
||||
setSegmentState(kFSArFilledStart, kFSArFilledStop, kFSIntakeWarningFinishedFlag, kNoState);
|
||||
item->setItemState(kArgonFull);
|
||||
GameState.setScoringFilledArgonCanister(true);
|
||||
} else if (_dispenseItemID == kAirMask) {
|
||||
setSegmentState(kFSOFilledStart, kFSOFilledStop, kFSIntakeWarningFinishedFlag, kNoState);
|
||||
((AirMask *)item)->refillAirMask();
|
||||
GameState.setScoringFilledOxygenCanister(true);
|
||||
} else if (_dispenseItemID == kNitrogenCanister) {
|
||||
setSegmentState(kFSNFilledStart, kFSNFilledStop, kFSIntakeWarningFinishedFlag, kNoState);
|
||||
item->setItemState(kNitrogenFull);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (_dispenseItemID) {
|
||||
case kArgonCanister:
|
||||
setStaticState(kFSArAttach, kWaitingForDispense);
|
||||
break;
|
||||
case kCO2Item:
|
||||
setStaticState(kFSCO2Attach, kWaitingForDispense);
|
||||
break;
|
||||
case kHeItem:
|
||||
setStaticState(kFSHeAttach, kWaitingForDispense);
|
||||
break;
|
||||
case kAirMask:
|
||||
setStaticState(kFSOAttach, kWaitingForDispense);
|
||||
break;
|
||||
case kNitrogenCanister:
|
||||
setStaticState(kFSNAttach, kWaitingForDispense);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::ArHighlightFinished() {
|
||||
_dispenseItemID = kArgonCanister;
|
||||
dispenseGas();
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::CO2HighlightFinished() {
|
||||
_dispenseItemID = kCO2Item;
|
||||
dispenseGas();
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::HeHighlightFinished() {
|
||||
_dispenseItemID = kHeItem;
|
||||
dispenseGas();
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::OHighlightFinished() {
|
||||
_dispenseItemID = kAirMask;
|
||||
dispenseGas();
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::NHighlightFinished() {
|
||||
_dispenseItemID = kNitrogenCanister;
|
||||
dispenseGas();
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::receiveNotification(Notification *, const NotificationFlags flags) {
|
||||
switch (flags) {
|
||||
case kFSPowerUpFinishedFlag:
|
||||
powerUpFinished();
|
||||
break;
|
||||
case kFSSplashFinishedFlag:
|
||||
splashFinished();
|
||||
break;
|
||||
case kFSIntakeWarningFinishedFlag:
|
||||
intakeWarningFinished();
|
||||
break;
|
||||
case kFSIntakeHiliteFinishedFlag:
|
||||
intakeHighlightFinished();
|
||||
break;
|
||||
case kFSDispenseHiliteFinishedFlag:
|
||||
dispenseHighlightFinished();
|
||||
break;
|
||||
case kFSArHiliteFinishedFlag:
|
||||
ArHighlightFinished();
|
||||
break;
|
||||
case kFSCO2HiliteFinishedFlag:
|
||||
CO2HighlightFinished();
|
||||
break;
|
||||
case kFSHeHiliteFinishedFlag:
|
||||
HeHighlightFinished();
|
||||
break;
|
||||
case kFSOHiliteFinishedFlag:
|
||||
OHighlightFinished();
|
||||
break;
|
||||
case kFSNHiliteFinishedFlag:
|
||||
NHighlightFinished();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::handleInput(const Input &input, const Hotspot *cursorSpot) {
|
||||
InputHandler::handleInput(input, cursorSpot);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::clickInIntake() {
|
||||
setSegmentState(kFSIntakeHiliteStart, kFSIntakeHiliteStop, kFSIntakeHiliteFinishedFlag, kNoState);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::clickInDispense() {
|
||||
setSegmentState(kFSDispenseHiliteStart, kFSDispenseHiliteStop, kFSDispenseHiliteFinishedFlag, kNoState);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::clickInAr() {
|
||||
setSegmentState(kFSArHiliteStart, kFSArHiliteStop, kFSArHiliteFinishedFlag, kNoState);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::clickInCO2() {
|
||||
setSegmentState(kFSCO2HiliteStart, kFSCO2HiliteStop, kFSCO2HiliteFinishedFlag, kNoState);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::clickInHe() {
|
||||
setSegmentState(kFSHeHiliteStart, kFSHeHiliteStop, kFSHeHiliteFinishedFlag, kNoState);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::clickInO() {
|
||||
setSegmentState(kFSOHiliteStart, kFSOHiliteStop, kFSOHiliteFinishedFlag, kNoState);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::clickInN() {
|
||||
setSegmentState(kFSNHiliteStart, kFSNHiliteStop, kFSNHiliteFinishedFlag, kNoState);
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::clickInHotspot(const Input &input, const Hotspot *spot) {
|
||||
GameInteraction::clickInHotspot(input, spot);
|
||||
|
||||
switch (spot->getObjectID()) {
|
||||
case kNorad01IntakeSpotID:
|
||||
clickInIntake();
|
||||
break;
|
||||
case kNorad01DispenseSpotID:
|
||||
clickInDispense();
|
||||
break;
|
||||
case kNorad01ArSpotID:
|
||||
clickInAr();
|
||||
break;
|
||||
case kNorad01CO2SpotID:
|
||||
clickInCO2();
|
||||
break;
|
||||
case kNorad01HeSpotID:
|
||||
clickInHe();
|
||||
break;
|
||||
case kNorad01OSpotID:
|
||||
clickInO();
|
||||
break;
|
||||
case kNorad01NSpotID:
|
||||
clickInN();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::activateHotspots() {
|
||||
GameInteraction::activateHotspots();
|
||||
|
||||
switch (_state) {
|
||||
case kMainMenu:
|
||||
g_allHotspots.activateOneHotspot(kNorad01IntakeSpotID);
|
||||
g_allHotspots.activateOneHotspot(kNorad01DispenseSpotID);
|
||||
break;
|
||||
case kDispenseMenu:
|
||||
g_allHotspots.activateOneHotspot(kNorad01ArSpotID);
|
||||
g_allHotspots.activateOneHotspot(kNorad01CO2SpotID);
|
||||
g_allHotspots.activateOneHotspot(kNorad01HeSpotID);
|
||||
g_allHotspots.activateOneHotspot(kNorad01OSpotID);
|
||||
g_allHotspots.activateOneHotspot(kNorad01NSpotID);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlphaFillingStation::newFillingItem(Item *item) {
|
||||
switch (_state) {
|
||||
case kWaitingForAttach:
|
||||
if (item)
|
||||
showIntakeInProgress(0);
|
||||
break;
|
||||
case kWaitingForDispense:
|
||||
dispenseGas();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Pegasus
|
||||
90
engines/pegasus/neighborhood/norad/alpha/fillingstation.h
Normal file
90
engines/pegasus/neighborhood/norad/alpha/fillingstation.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_FILLINGSTATION_H
|
||||
#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_FILLINGSTATION_H
|
||||
|
||||
#include "pegasus/interaction.h"
|
||||
#include "pegasus/movie.h"
|
||||
#include "pegasus/notification.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
class Item;
|
||||
|
||||
class NoradAlphaFillingStation : public GameInteraction, public NotificationReceiver {
|
||||
public:
|
||||
NoradAlphaFillingStation(Neighborhood *);
|
||||
~NoradAlphaFillingStation() override {}
|
||||
|
||||
void handleInput(const Input &, const Hotspot *) override;
|
||||
|
||||
void clickInHotspot(const Input &, const Hotspot *) override;
|
||||
void activateHotspots() override;
|
||||
|
||||
void newFillingItem(Item *);
|
||||
|
||||
protected:
|
||||
void receiveNotification(Notification *, const NotificationFlags) override;
|
||||
|
||||
void openInteraction() override;
|
||||
void initInteraction() override;
|
||||
void closeInteraction() override;
|
||||
|
||||
void powerUpFinished();
|
||||
void splashFinished();
|
||||
void intakeWarningFinished();
|
||||
void intakeHighlightFinished();
|
||||
void dispenseHighlightFinished();
|
||||
void ArHighlightFinished();
|
||||
void CO2HighlightFinished();
|
||||
void HeHighlightFinished();
|
||||
void OHighlightFinished();
|
||||
void NHighlightFinished();
|
||||
|
||||
void showIntakeInProgress(uint16);
|
||||
|
||||
void clickInIntake();
|
||||
void clickInDispense();
|
||||
void clickInAr();
|
||||
void clickInCO2();
|
||||
void clickInHe();
|
||||
void clickInO();
|
||||
void clickInN();
|
||||
|
||||
void dispenseGas();
|
||||
|
||||
void setStaticState(TimeValue, int16);
|
||||
void setSegmentState(TimeValue, TimeValue, NotificationFlags, int16);
|
||||
|
||||
Movie _rightSideMovie;
|
||||
Notification _rightSideNotification;
|
||||
NotificationCallBack _rightSideCallBack;
|
||||
int16 _state;
|
||||
ItemID _dispenseItemID;
|
||||
};
|
||||
|
||||
} // End of namespace Pegasus
|
||||
|
||||
#endif
|
||||
969
engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
Normal file
969
engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
Normal file
@@ -0,0 +1,969 @@
|
||||
/* 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/cursor.h"
|
||||
#include "pegasus/energymonitor.h"
|
||||
#include "pegasus/gamestate.h"
|
||||
#include "pegasus/interface.h"
|
||||
#include "pegasus/pegasus.h"
|
||||
#include "pegasus/ai/ai_area.h"
|
||||
#include "pegasus/items/biochips/arthurchip.h"
|
||||
#include "pegasus/items/inventory/airmask.h"
|
||||
#include "pegasus/neighborhood/norad/constants.h"
|
||||
#include "pegasus/neighborhood/norad/subcontrolroom.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/ecrmonitor.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/fillingstation.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/noradalpha.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/subchase.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
static const ExtraID kShowThermalScan = 1000;
|
||||
|
||||
static const HotSpotID kThermalScanHotSpotID = 10000;
|
||||
|
||||
const uint32 NoradAlpha::_noradAlphaClawExtras[22] = {
|
||||
kN22ClawFromAToB,
|
||||
kN22ClawALoop,
|
||||
kN22ClawAPinch,
|
||||
kN22ClawACounterclockwise,
|
||||
kN22ClawAClockwise,
|
||||
kN22ClawFromBToA,
|
||||
kN22ClawFromBToC,
|
||||
kN22ClawFromBToD,
|
||||
kN22ClawBLoop,
|
||||
kN22ClawBPinch,
|
||||
kN22ClawBCounterclockwise,
|
||||
kN22ClawBClockwise,
|
||||
kN22ClawFromCToB,
|
||||
kN22ClawCLoop,
|
||||
kN22ClawCPinch,
|
||||
kN22ClawCCounterclockwise,
|
||||
kN22ClawCClockwise,
|
||||
kN22ClawFromDToB,
|
||||
kN22ClawDLoop,
|
||||
kN22ClawDPinch,
|
||||
kN22ClawDCounterclockwise,
|
||||
kN22ClawDClockwise
|
||||
};
|
||||
|
||||
NoradAlpha::NoradAlpha(InputHandler *nextHandler, PegasusEngine *owner)
|
||||
: Norad(nextHandler, owner, "Norad Alpha", kNoradAlphaID),
|
||||
_thermalScanSpot(kThermalScanHotSpotID), _extraMovie(kNoDisplayElement) {
|
||||
_elevatorUpRoomID = kNorad11South;
|
||||
_elevatorDownRoomID = kNorad12South;
|
||||
_elevatorUpSpotID = kNorad12ElevatorUpSpotID;
|
||||
_elevatorDownSpotID = kNorad11ElevatorDownSpotID;
|
||||
|
||||
_subRoomEntryRoom1 = kNorad10;
|
||||
_subRoomEntryDir1 = kEast;
|
||||
_subRoomEntryRoom2 = kNorad21;
|
||||
_subRoomEntryDir2 = kWest;
|
||||
_upperPressureDoorRoom = kNorad10East;
|
||||
_lowerPressureDoorRoom = kNorad21West;
|
||||
|
||||
_upperPressureDoorUpSpotID = kAlphaUpperPressureDoorUpSpotID;
|
||||
_upperPressureDoorDownSpotID = kAlphaUpperPressureDoorDownSpotID;
|
||||
_upperPressureDoorAbortSpotID = kNorad10EastOutSpotID;
|
||||
|
||||
_lowerPressureDoorUpSpotID = kAlphaLowerPressureDoorUpSpotID;
|
||||
_lowerPressureDoorDownSpotID = kAlphaLowerPressureDoorDownSpotID;
|
||||
_lowerPressureDoorAbortSpotID = kNorad21WestOutSpotID;
|
||||
|
||||
_pressureSoundIn = kAlphaPressureDoorIntro1In;
|
||||
_pressureSoundOut = kAlphaPressureDoorIntro1Out;
|
||||
_equalizeSoundIn = kAlphaPressureDoorIntro2In;
|
||||
_equalizeSoundOut = kAlphaPressureDoorIntro2Out;
|
||||
_accessDeniedIn = kAlphaAccessDeniedIn;
|
||||
_accessDeniedOut = kAlphaAccessDeniedOut;
|
||||
|
||||
_platformRoom = kNorad19West;
|
||||
_subControlRoom = kNorad22West;
|
||||
|
||||
_subPrepFailed = false;
|
||||
_fillingStationItem = nullptr;
|
||||
|
||||
setIsItemTaken(kGasCanister);
|
||||
}
|
||||
|
||||
NoradAlpha::~NoradAlpha() {
|
||||
if (_vm->isDVD())
|
||||
_vm->getAllHotspots().remove(&_thermalScanSpot);
|
||||
}
|
||||
|
||||
void NoradAlpha::init() {
|
||||
Norad::init();
|
||||
|
||||
_extraMovieCallBack.setNotification(&_neighborhoodNotification);
|
||||
|
||||
if (_vm->isDVD()) {
|
||||
_thermalScanSpot.setArea(Common::Rect(216, 112, 336, 312));
|
||||
_thermalScanSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
|
||||
_vm->getAllHotspots().push_back(&_thermalScanSpot);
|
||||
}
|
||||
|
||||
Hotspot *hotspot = _vm->getAllHotspots().findHotspotByID(kN01GasCanisterSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kPickUpItemSpotFlag, kPickUpItemSpotFlag);
|
||||
HotspotInfoTable::Entry *hotspotEntry = findHotspotEntry(kN01GasCanisterSpotID);
|
||||
hotspotEntry->hotspotItem = kGasCanister;
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kN01ArgonCanisterSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kPickUpItemSpotFlag, kPickUpItemSpotFlag);
|
||||
hotspotEntry = findHotspotEntry(kN01ArgonCanisterSpotID);
|
||||
hotspotEntry->hotspotItem = kArgonCanister;
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kN01NitrogenCanisterSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kPickUpItemSpotFlag, kPickUpItemSpotFlag);
|
||||
hotspotEntry = findHotspotEntry(kN01NitrogenCanisterSpotID);
|
||||
hotspotEntry->hotspotItem = kNitrogenCanister;
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kN01AirMaskSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kPickUpItemSpotFlag, kPickUpItemSpotFlag);
|
||||
hotspotEntry = findHotspotEntry(kN01AirMaskSpotID);
|
||||
hotspotEntry->hotspotItem = kAirMask;
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kN01GasOutletSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kDropItemSpotFlag, kDropItemSpotFlag);
|
||||
}
|
||||
|
||||
void NoradAlpha::start() {
|
||||
if (g_energyMonitor) {
|
||||
g_energyMonitor->stopEnergyDraining();
|
||||
g_energyMonitor->restoreLastEnergyValue();
|
||||
_vm->resetEnergyDeathReason();
|
||||
g_energyMonitor->startEnergyDraining();
|
||||
}
|
||||
|
||||
NeighborhoodID itemNeighborhood;
|
||||
RoomID itemRoom;
|
||||
DirectionConstant itemDirection;
|
||||
|
||||
Item *item = (Item *)_vm->getAllItems().findItemByID(kGasCanister);
|
||||
item->getItemRoom(itemNeighborhood, itemRoom, itemDirection);
|
||||
|
||||
if (itemNeighborhood == getObjectID()) {
|
||||
_fillingStationItem = item;
|
||||
} else {
|
||||
item = (Item *)_vm->getAllItems().findItemByID(kAirMask);
|
||||
item->getItemRoom(itemNeighborhood, itemRoom, itemDirection);
|
||||
|
||||
if (itemNeighborhood == getObjectID()) {
|
||||
_fillingStationItem = item;
|
||||
} else {
|
||||
item = (Item *)_vm->getAllItems().findItemByID(kNitrogenCanister);
|
||||
item->getItemRoom(itemNeighborhood, itemRoom, itemDirection);
|
||||
|
||||
if (itemNeighborhood == getObjectID()) {
|
||||
_fillingStationItem = item;
|
||||
} else {
|
||||
item = (Item *)_vm->getAllItems().findItemByID(kArgonCanister);
|
||||
item->getItemRoom(itemNeighborhood, itemRoom, itemDirection);
|
||||
if (itemNeighborhood == getObjectID())
|
||||
_fillingStationItem = item;
|
||||
else
|
||||
_fillingStationItem = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!GameState.getNoradGassed())
|
||||
forceStridingStop(kNorad03, kEast, kAltNoradAlphaNormal);
|
||||
|
||||
GameState.setNoradArrivedFromSub(false);
|
||||
Norad::start();
|
||||
}
|
||||
|
||||
void NoradAlpha::setUpAIRules() {
|
||||
Neighborhood::setUpAIRules();
|
||||
|
||||
if (g_AIArea) {
|
||||
AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/Norad/XN01WD1", false);
|
||||
AIHasItemCondition *hasGasCanisterCondition = new AIHasItemCondition(kGasCanister);
|
||||
AIRule *rule = new AIRule(hasGasCanisterCondition, messageAction);
|
||||
g_AIArea->addAIRule(rule);
|
||||
}
|
||||
}
|
||||
|
||||
bool NoradAlpha::okayToJump() {
|
||||
bool result = Neighborhood::okayToJump();
|
||||
|
||||
if (!result)
|
||||
playSpotSoundSync(kAlphaCantTransportIn, kAlphaCantTransportOut);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void NoradAlpha::getExtraCompassMove(const ExtraTable::Entry &entry, FaderMoveSpec &compassMove) {
|
||||
if (entry.extra == kNorad19ExitToSub) {
|
||||
compassMove.makeTwoKnotFaderSpec(kNoradAlphaMovieScale, entry.movieStart, 270 + kSubPlatformCompassAngle,
|
||||
entry.movieEnd, 90 + 20 + 360);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 10 * kNoradAlphaFrameDuration, 270 + kSubPlatformCompassAngle);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 29 * kNoradAlphaFrameDuration, 270 + kSubPlatformCompassAngle + 20);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 52 * kNoradAlphaFrameDuration, 270 + kSubPlatformCompassAngle + 20);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 84 * kNoradAlphaFrameDuration, 360 + 90);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 198 * kNoradAlphaFrameDuration, 360 + 90);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 270 * kNoradAlphaFrameDuration, 360 + 90 + 15);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 280 * kNoradAlphaFrameDuration, 360 + 90 + 20);
|
||||
} else {
|
||||
Norad::getExtraCompassMove(entry, compassMove);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::playClawMonitorIntro() {
|
||||
playSpotSoundSync(kAlphaLoadClawIntroIn, kAlphaLoadClawIntroOut);
|
||||
}
|
||||
|
||||
GameInteraction *NoradAlpha::makeInteraction(const InteractionID interactionID) {
|
||||
switch (interactionID) {
|
||||
case kNoradECRMonitorInteractionID:
|
||||
return new NoradAlphaECRMonitor(this);
|
||||
case kNoradFillingStationInteractionID:
|
||||
return new NoradAlphaFillingStation(this);
|
||||
case kNoradSubChaseInteractionID:
|
||||
return new SubChase(this);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Norad::makeInteraction(interactionID);
|
||||
}
|
||||
|
||||
void NoradAlpha::loadAmbientLoops() {
|
||||
// clone2727 would like to point out that the following comment does not quite
|
||||
// match the code logic below
|
||||
|
||||
/*
|
||||
Logic:
|
||||
|
||||
loop sound 1:
|
||||
if gassed,
|
||||
play warning loop of some sort
|
||||
else
|
||||
play nothing
|
||||
loop sound 2:
|
||||
if gassed and not wearing air mask
|
||||
if in ECR
|
||||
play breathing water loop
|
||||
else
|
||||
play breathing
|
||||
else
|
||||
if in ECR
|
||||
play water loop
|
||||
if at N07 north
|
||||
play unmanned loop
|
||||
*/
|
||||
|
||||
if (!GameState.getNoradSeenTimeStream() || !g_interface || _vm->getEnergyDeathReason() == kDeathSubDestroyed)
|
||||
return;
|
||||
|
||||
RoomID room = GameState.getCurrentRoom();
|
||||
if (GameState.getNoradGassed()) {
|
||||
if (room >= kNorad11 && room <= kNorad19West) {
|
||||
if (_vm->isDVD())
|
||||
loadLoopSound1("Sounds/Norad/NEW SUB AMB.44K.AIFF", kNoradWarningVolume * 3);
|
||||
else
|
||||
loadLoopSound1("Sounds/Norad/NEW SUB AMB.22K.AIFF", kNoradWarningVolume * 3);
|
||||
} else if (room >= kNorad21 && room <= kNorad22West) {
|
||||
if (_vm->isDVD())
|
||||
loadLoopSound1("Sounds/Norad/SUB CONTRL LOOP.32K.AIFF", kNoradWarningVolume * 3);
|
||||
else
|
||||
loadLoopSound1("Sounds/Norad/SUB CONTRL LOOP.22K.AIFF", kNoradWarningVolume * 3);
|
||||
} else {
|
||||
if (_vm->isDVD())
|
||||
loadLoopSound1("Sounds/Norad/WARNING LOOP.32K.AIFF", kNoradWarningVolume);
|
||||
else
|
||||
loadLoopSound1("Sounds/Norad/WARNING LOOP.22K.AIFF", kNoradWarningVolume);
|
||||
}
|
||||
} else {
|
||||
loadLoopSound1("");
|
||||
}
|
||||
|
||||
if (GameState.getNoradGassed() && !g_airMask->isAirFilterOn()) {
|
||||
if (room >= kNorad01 && room <= kNorad01West) {
|
||||
loadLoopSound2("Sounds/Norad/Breathing Water.22K.AIFF", kNoradSuckWindVolume);
|
||||
} else if (room == kNorad02) {
|
||||
if (GameState.isCurrentDoorOpen())
|
||||
loadLoopSound2("Sounds/Norad/Breathing Water.22K.AIFF", kNoradSuckWindVolume);
|
||||
else
|
||||
loadLoopSound2("Sounds/Norad/SUCKING WIND.22K.AIFF", kNoradSuckWindVolume, 0, 0);
|
||||
} else {
|
||||
loadLoopSound2("Sounds/Norad/SUCKING WIND.22K.AIFF", kNoradSuckWindVolume, 0, 0);
|
||||
}
|
||||
} else {
|
||||
if (room >= kNorad01 && room <= kNorad01West) {
|
||||
loadLoopSound2("Sounds/Norad/WATER FLOWING.AIFF", 0x100 / 2);
|
||||
} else if (room == kNorad02) {
|
||||
if (GameState.isCurrentDoorOpen())
|
||||
loadLoopSound2("Sounds/Norad/WATER FLOWING.AIFF", 0x100 / 2);
|
||||
else
|
||||
loadLoopSound2("");
|
||||
} else {
|
||||
loadLoopSound2("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NoradAlpha::checkContinuePoint(const RoomID room, const DirectionConstant direction) {
|
||||
switch (MakeRoomView(room, direction)) {
|
||||
case MakeRoomView(kNorad02, kEast):
|
||||
case MakeRoomView(kNorad06, kEast):
|
||||
case MakeRoomView(kNorad11, kEast):
|
||||
case MakeRoomView(kNorad15, kEast):
|
||||
case MakeRoomView(kNorad19, kWest):
|
||||
case MakeRoomView(kNorad21, kSouth):
|
||||
makeContinuePoint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::arriveAt(const RoomID room, const DirectionConstant direction) {
|
||||
Norad::arriveAt(room, direction);
|
||||
|
||||
switch (GameState.getCurrentRoom()) {
|
||||
case kNorad01:
|
||||
arriveAtNorad01();
|
||||
break;
|
||||
case kNorad01East:
|
||||
arriveAtNorad01East();
|
||||
break;
|
||||
case kNorad01West:
|
||||
arriveAtNorad01West();
|
||||
break;
|
||||
case kNorad04:
|
||||
arriveAtNorad04();
|
||||
break;
|
||||
case kNorad07:
|
||||
if (_vm->isDVD() && GameState.getLastRoom() == kNorad06)
|
||||
startExtraSequence(kShowThermalScan, kExtraCompletedFlag, kFilterNoInput);
|
||||
break;
|
||||
case kNorad07North:
|
||||
GameState.setScoringSawUnconsciousOperator(true);
|
||||
if (g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA70", kArthurNoradSawUnconsciousOperator);
|
||||
break;
|
||||
case kNorad11:
|
||||
GameState.setScoringWentThroughPressureDoor(true);
|
||||
break;
|
||||
case kNorad22:
|
||||
arriveAtNorad22();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::arriveAtNorad01() {
|
||||
Item *argonCanister, *nitrogenCanister;
|
||||
|
||||
switch (GameState.getCurrentDirection()) {
|
||||
case kSouth:
|
||||
if (!GameState.getNoradSeenTimeStream()) {
|
||||
GameState.setNoradN22MessagePlayed(false);
|
||||
requestExtraSequence(kNoradArriveFromTSA, kExtraCompletedFlag, kFilterNoInput);
|
||||
// You are no match for me, human.
|
||||
requestExtraSequence(kNorad01RobotTaunt, kExtraCompletedFlag, kFilterNoInput);
|
||||
}
|
||||
break;
|
||||
case kEast:
|
||||
if (g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA33", kArthurNoradAtSecurityMonitor);
|
||||
break;
|
||||
case kWest:
|
||||
if (GameState.getLastRoom() == kNorad01West) {
|
||||
argonCanister = g_allItems.findItemByID(kArgonCanister);
|
||||
nitrogenCanister = g_allItems.findItemByID(kNitrogenCanister);
|
||||
if (((GameState.isTakenItemID(kArgonCanister) && argonCanister->getItemState() != kArgonFull) ||
|
||||
(GameState.isTakenItemID(kNitrogenCanister) && nitrogenCanister->getItemState() != kNitrogenFull)) && g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA34", kArthurNoradDidntFillCanisters);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::arriveAtNorad01East() {
|
||||
GameState.setScoringSawSecurityMonitor(true);
|
||||
newInteraction(kNoradECRMonitorInteractionID);
|
||||
}
|
||||
|
||||
void NoradAlpha::arriveAtNorad01West() {
|
||||
newInteraction(kNoradFillingStationInteractionID);
|
||||
}
|
||||
|
||||
void NoradAlpha::arriveAtNorad04() {
|
||||
if (GameState.getCurrentDirection() == kEast && !GameState.getNoradGassed())
|
||||
playDeathExtra(kNorad04EastDeath, kDeathWokeUpNorad);
|
||||
}
|
||||
|
||||
void NoradAlpha::arriveAtNorad22() {
|
||||
if (!GameState.getNoradN22MessagePlayed() && GameState.getCurrentDirection() == kSouth) {
|
||||
startExtraSequence(kNorad22SouthIntro, kExtraCompletedFlag, kFilterNoInput);
|
||||
GameState.setNoradN22MessagePlayed(true);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::turnTo(const DirectionConstant direction) {
|
||||
Norad::turnTo(direction);
|
||||
if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad01, kEast) && g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA33", kArthurNoradAtSecurityMonitor);
|
||||
}
|
||||
|
||||
void NoradAlpha::bumpIntoWall() {
|
||||
requestSpotSound(kAlphaBumpIntoWallIn, kAlphaBumpIntoWallOut, kFilterNoInput, 0);
|
||||
Neighborhood::bumpIntoWall();
|
||||
}
|
||||
|
||||
void NoradAlpha::startExtraSequence(const ExtraID extraID, const NotificationFlags flags, const InputBits interruptionFilter) {
|
||||
TimeValue segmentStart = 0, segmentStop = 0;
|
||||
bool loopSequence = false;
|
||||
Common::Rect pushBounds;
|
||||
NotificationFlags extraFlags;
|
||||
|
||||
switch (extraID) {
|
||||
case kShowThermalScan:
|
||||
_turnPush.getBounds(pushBounds);
|
||||
|
||||
switch (extraID) {
|
||||
case kShowThermalScan:
|
||||
_extraMovie.initFromMovieFile("Images/Norad Alpha/N07NS.movie");
|
||||
segmentStart = 0;
|
||||
segmentStop = _extraMovie.getDuration();
|
||||
loopSequence = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_lastExtra = extraID;
|
||||
_turnPush.hide();
|
||||
|
||||
if (!loopSequence && g_AIArea)
|
||||
g_AIArea->lockAIOut();
|
||||
|
||||
extraFlags = flags;
|
||||
_interruptionFilter = interruptionFilter;
|
||||
// Stop the nav movie before doing anything else
|
||||
_navMovie.stop();
|
||||
_navMovie.stopDisplaying();
|
||||
|
||||
_extraMovie.setVolume(_vm->getSoundFXLevel());
|
||||
_extraMovie.moveElementTo(pushBounds.left, pushBounds.top);
|
||||
_extraMovie.setDisplayOrder(kNavMovieOrder + 1);
|
||||
_extraMovie.startDisplaying();
|
||||
_extraMovie.show();
|
||||
_extraMovie.setFlags(0);
|
||||
_extraMovie.setSegment(segmentStart, segmentStop);
|
||||
_extraMovie.setTime(segmentStart);
|
||||
if (loopSequence)
|
||||
_extraMovie.setFlags(kLoopTimeBase);
|
||||
else
|
||||
extraFlags |= kNeighborhoodMovieCompletedFlag;
|
||||
_extraMovieCallBack.cancelCallBack();
|
||||
_extraMovieCallBack.initCallBack(&_extraMovie, kCallBackAtExtremes);
|
||||
if (extraFlags != 0) {
|
||||
_extraMovieCallBack.setCallBackFlag(extraFlags);
|
||||
_extraMovieCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
}
|
||||
_extraMovie.start();
|
||||
break;
|
||||
default:
|
||||
Neighborhood::startExtraSequence(extraID, flags, interruptionFilter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::receiveNotification(Notification *notification, const NotificationFlags flags) {
|
||||
if ((flags & kExtraCompletedFlag) != 0) {
|
||||
switch (_lastExtra) {
|
||||
case kShowThermalScan:
|
||||
_interruptionFilter = kFilterAllInput;
|
||||
_extraMovie.stopDisplaying();
|
||||
_extraMovie.releaseMovie();
|
||||
_navMovie.startDisplaying();
|
||||
break;
|
||||
case kNorad19ExitToSub:
|
||||
if (_vm->isDVD()) {
|
||||
_interruptionFilter = kFilterAllInput;
|
||||
_vm->_cursor->hide();
|
||||
setNextHandler(_vm);
|
||||
throwAwayInterface();
|
||||
loadLoopSound1("");
|
||||
newInteraction(kNoradSubChaseInteractionID);
|
||||
GameState.setScoringEnteredSub(true);
|
||||
}
|
||||
break;
|
||||
case kNoradArriveFromTSA:
|
||||
GameState.setNoradSeenTimeStream(true);
|
||||
loadAmbientLoops();
|
||||
break;
|
||||
case kNorad01RobotTaunt:
|
||||
if (_vm->isChattyAI())
|
||||
g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Norad/XN01SB", false, kWarningInterruption);
|
||||
_interruptionFilter = kFilterAllInput;
|
||||
makeContinuePoint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Norad::receiveNotification(notification, flags);
|
||||
|
||||
if ((flags & kExtraCompletedFlag) != 0) {
|
||||
switch (_lastExtra) {
|
||||
case kNorad22SouthIntro:
|
||||
loopExtraSequence(kNorad22SouthReply);
|
||||
playSpotSoundSync(kN22ReplyIn, kN22ReplyOut);
|
||||
startExtraSequence(kNorad22SouthFinish, kExtraCompletedFlag, kFilterNoInput);
|
||||
break;
|
||||
case kNorad22SouthFinish:
|
||||
if (g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBB29", kArthurNoradSawSubMessage);
|
||||
_interruptionFilter = kFilterAllInput;
|
||||
// Force ArriveAt to do its thing...
|
||||
GameState.setCurrentRoom(kNorad21);
|
||||
arriveAt(kNorad22, kSouth);
|
||||
break;
|
||||
case kN22ClawFromAToB:
|
||||
case kN22ClawAPinch:
|
||||
case kN22ClawACounterclockwise:
|
||||
case kN22ClawAClockwise:
|
||||
case kN22ClawFromBToA:
|
||||
case kN22ClawFromBToC:
|
||||
case kN22ClawFromBToD:
|
||||
case kN22ClawBPinch:
|
||||
case kN22ClawBCounterclockwise:
|
||||
case kN22ClawBClockwise:
|
||||
case kN22ClawFromCToB:
|
||||
case kN22ClawCPinch:
|
||||
case kN22ClawCCounterclockwise:
|
||||
case kN22ClawCClockwise:
|
||||
case kN22ClawFromDToB:
|
||||
case kN22ClawDPinch:
|
||||
case kN22ClawDCounterclockwise:
|
||||
case kN22ClawDClockwise:
|
||||
if (g_arthurChip) {
|
||||
if (_vm->getRandomBit())
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA64", kArthurNoradPlayedWithClaw);
|
||||
else
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA66", kArthurNoradPlayedWithClaw);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_AIArea->checkMiddleArea();
|
||||
}
|
||||
|
||||
void NoradAlpha::getZoomEntry(const HotSpotID spotID, ZoomTable::Entry &entry) {
|
||||
Norad::getZoomEntry(spotID, entry);
|
||||
|
||||
ExtraTable::Entry extra;
|
||||
|
||||
if (spotID == kNorad01GasSpotID) {
|
||||
if (_fillingStationItem) {
|
||||
if (_fillingStationItem->getObjectID() == kGasCanister) {
|
||||
getExtraEntry(kNorad01ZoomInWithGasCanister, extra);
|
||||
entry.movieStart = extra.movieStart;
|
||||
entry.movieEnd = extra.movieEnd;
|
||||
} else {
|
||||
entry.clear();
|
||||
}
|
||||
}
|
||||
} else if (spotID == kNorad01GasOutSpotID) {
|
||||
if (_fillingStationItem) {
|
||||
if (_fillingStationItem->getObjectID() == kGasCanister) {
|
||||
getExtraEntry(kNorad01ZoomOutWithGasCanister, extra);
|
||||
entry.movieStart = extra.movieStart;
|
||||
entry.movieEnd = extra.movieEnd;
|
||||
} else {
|
||||
entry.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TimeValue NoradAlpha::getViewTime(const RoomID room, const DirectionConstant direction) {
|
||||
ExtraTable::Entry entry;
|
||||
|
||||
if (room == kNorad01 && direction == kSouth && !GameState.getNoradSeenTimeStream()) {
|
||||
getExtraEntry(kNoradArriveFromTSA, entry);
|
||||
return entry.movieStart;
|
||||
}
|
||||
|
||||
if (room == kNorad01 && direction == kWest) {
|
||||
if (!_fillingStationItem) {
|
||||
return Norad::getViewTime(room, direction);
|
||||
} else {
|
||||
getExtraEntry(kN01WGasCanister, entry);
|
||||
return entry.movieStart;
|
||||
}
|
||||
} else if (room == kNorad01West && direction == kWest) {
|
||||
uint32 extraID = 0xffffffff;
|
||||
if (_fillingStationItem) {
|
||||
switch (_fillingStationItem->getObjectID()) {
|
||||
case kArgonCanister:
|
||||
if (GameState.getNoradFillingStationOn())
|
||||
extraID = kN01WZArgonCanisterLit;
|
||||
else
|
||||
extraID = kN01WZArgonCanisterDim;
|
||||
break;
|
||||
case kGasCanister:
|
||||
if (GameState.getNoradFillingStationOn())
|
||||
extraID = kN01WZGasCanisterLit;
|
||||
else
|
||||
extraID = kN01WZGasCanisterDim;
|
||||
break;
|
||||
case kAirMask:
|
||||
if (GameState.getNoradFillingStationOn())
|
||||
extraID = kN01WZAirMaskLit;
|
||||
else
|
||||
extraID = kN01WZAirMaskDim;
|
||||
break;
|
||||
case kNitrogenCanister:
|
||||
if (GameState.getNoradFillingStationOn())
|
||||
extraID = kN01WZNitrogenCanisterLit;
|
||||
else
|
||||
extraID = kN01WZNitrogenCanisterDim;
|
||||
break;
|
||||
default:
|
||||
// Should never happen.
|
||||
break;
|
||||
}
|
||||
} else if (GameState.getNoradFillingStationOn()) {
|
||||
extraID = kN01WZEmptyLit;
|
||||
}
|
||||
|
||||
if (extraID == 0xffffffff) {
|
||||
return Norad::getViewTime(room, direction);
|
||||
} else {
|
||||
getExtraEntry(extraID, entry);
|
||||
return entry.movieStart;
|
||||
}
|
||||
}
|
||||
|
||||
return Norad::getViewTime(room, direction);
|
||||
}
|
||||
|
||||
void NoradAlpha::setSoundFXLevel(const uint16 level) {
|
||||
Neighborhood::setSoundFXLevel(level);
|
||||
|
||||
if (_extraMovie.isMovieValid())
|
||||
_extraMovie.setVolume(level);
|
||||
}
|
||||
|
||||
void NoradAlpha::turnOnFillingStation() {
|
||||
if (GameState.getCurrentRoom() == kNorad01West && !GameState.getNoradFillingStationOn()) {
|
||||
GameState.setNoradFillingStationOn(true);
|
||||
updateViewFrame();
|
||||
if (g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA72", kArthurNoradSawFillingStation);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::turnOffFillingStation() {
|
||||
if (GameState.getCurrentRoom() == kNorad01West && GameState.getNoradFillingStationOn()) {
|
||||
GameState.setNoradFillingStationOn(false);
|
||||
updateViewFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::activateHotspots() {
|
||||
Norad::activateHotspots();
|
||||
|
||||
switch (GameState.getCurrentRoomAndView()) {
|
||||
case MakeRoomView(kNorad01West, kWest):
|
||||
if (_vm->getDragType() == kDragInventoryUse) {
|
||||
if (!_fillingStationItem) {
|
||||
ItemID itemID = _vm->getDraggingItem()->getObjectID();
|
||||
if (itemID == kArgonCanister || itemID == kGasCanister || itemID == kAirMask ||
|
||||
itemID == kNitrogenCanister)
|
||||
_vm->getAllHotspots().activateOneHotspot(kN01GasOutletSpotID);
|
||||
}
|
||||
} else {
|
||||
HotSpotID spotID;
|
||||
|
||||
if (_fillingStationItem) {
|
||||
switch (_fillingStationItem->getObjectID()) {
|
||||
case kArgonCanister:
|
||||
spotID = kN01ArgonCanisterSpotID;
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kNorad01GasOutSpotID);
|
||||
break;
|
||||
case kGasCanister:
|
||||
spotID = kN01GasCanisterSpotID;
|
||||
break;
|
||||
case kAirMask:
|
||||
spotID = kN01AirMaskSpotID;
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kNorad01GasOutSpotID);
|
||||
break;
|
||||
case kNitrogenCanister:
|
||||
spotID = kN01NitrogenCanisterSpotID;
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kNorad01GasOutSpotID);
|
||||
break;
|
||||
default:
|
||||
// Should never happen.
|
||||
spotID = kNoHotSpotID;
|
||||
break;
|
||||
}
|
||||
_vm->getAllHotspots().activateOneHotspot(spotID);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MakeRoomView(kNorad07, kNorth):
|
||||
if (_vm->isDVD())
|
||||
_vm->getAllHotspots().activateOneHotspot(kThermalScanHotSpotID);
|
||||
break;
|
||||
case MakeRoomView(kNorad10, kEast):
|
||||
if (GameState.isCurrentDoorOpen())
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kNorad10DoorSpotID);
|
||||
break;
|
||||
case MakeRoomView(kNorad21, kWest):
|
||||
if (GameState.isCurrentDoorOpen())
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kNorad21WestSpotID);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::clickInHotspot(const Input &input, const Hotspot *cursorSpot) {
|
||||
Norad::clickInHotspot(input, cursorSpot);
|
||||
|
||||
if (_vm->getDragType() == kDragInventoryUse) {
|
||||
if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad01West, kWest)) {
|
||||
Item *item = _vm->getDraggingItem();
|
||||
if (item->getObjectID() == kAirMask || item->getObjectID() == kArgonCanister ||
|
||||
item->getObjectID() == kNitrogenCanister || item->getObjectID() == kGasCanister) {
|
||||
HotspotInfoTable::Entry *hotspotEntry = findHotspotEntry(kN01GasOutletSpotID);
|
||||
hotspotEntry->hotspotItem = item->getObjectID();
|
||||
}
|
||||
}
|
||||
} else if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad07, kNorth) &&
|
||||
cursorSpot->getObjectID() == kThermalScanHotSpotID) {
|
||||
startExtraSequence(kShowThermalScan, kExtraCompletedFlag, kFilterNoInput);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::takeItemFromRoom(Item *item) {
|
||||
if (GameState.getCurrentRoom() == kNorad01West) {
|
||||
if (_fillingStationItem == item) {
|
||||
_fillingStationItem = nullptr;
|
||||
GameState.setNoradGassed(false);
|
||||
checkAirMask();
|
||||
((NoradAlphaFillingStation *)_currentInteraction)->newFillingItem(nullptr);
|
||||
forceStridingStop(kNorad03, kEast, kAltNoradAlphaNormal);
|
||||
}
|
||||
}
|
||||
|
||||
Norad::takeItemFromRoom(item);
|
||||
}
|
||||
|
||||
void NoradAlpha::dropItemIntoRoom(Item *item, Hotspot *droppedSpot) {
|
||||
if (GameState.getCurrentRoom() == kNorad01West) {
|
||||
if (!_fillingStationItem) {
|
||||
_fillingStationItem = item;
|
||||
((NoradAlphaFillingStation *)_currentInteraction)->newFillingItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
Norad::dropItemIntoRoom(item, droppedSpot);
|
||||
}
|
||||
|
||||
void NoradAlpha::getClawInfo(HotSpotID &outSpotID, HotSpotID &prepSpotID, HotSpotID &clawControlSpotID, HotSpotID &pinchClawSpotID,
|
||||
HotSpotID &moveClawDownSpotID, HotSpotID &moveClawRightSpotID, HotSpotID &moveClawLeftSpotID, HotSpotID &moveClawUpSpotID,
|
||||
HotSpotID &clawCCWSpotID, HotSpotID &clawCWSpotID, uint32 &clawPosition, const uint32 *&clawExtraIDs) {
|
||||
outSpotID = kNorad22MonitorOutSpotID;
|
||||
prepSpotID = kNorad22LaunchPrepSpotID;
|
||||
clawControlSpotID = kNorad22ClawControlSpotID;
|
||||
pinchClawSpotID = kNorad22ClawPinchSpotID;
|
||||
moveClawDownSpotID = kNorad22ClawDownSpotID;
|
||||
moveClawRightSpotID = kNorad22ClawRightSpotID;
|
||||
moveClawLeftSpotID = kNorad22ClawLeftSpotID;
|
||||
moveClawUpSpotID = kNorad22ClawUpSpotID;
|
||||
clawCCWSpotID = kNorad22ClawCCWSpotID;
|
||||
clawCWSpotID = kNorad22ClawCWSpotID;
|
||||
clawPosition = kClawAtD;
|
||||
clawExtraIDs = _noradAlphaClawExtras;
|
||||
}
|
||||
|
||||
Hotspot *NoradAlpha::getItemScreenSpot(Item *item, DisplayElement *element) {
|
||||
switch (item->getObjectID()) {
|
||||
case kGasCanister:
|
||||
return _vm->getAllHotspots().findHotspotByID(kN01GasCanisterSpotID);
|
||||
case kAirMask:
|
||||
return _vm->getAllHotspots().findHotspotByID(kN01AirMaskSpotID);
|
||||
case kArgonCanister:
|
||||
return _vm->getAllHotspots().findHotspotByID(kN01ArgonCanisterSpotID);
|
||||
case kNitrogenCanister:
|
||||
return _vm->getAllHotspots().findHotspotByID(kN01NitrogenCanisterSpotID);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Norad::getItemScreenSpot(item, element);
|
||||
}
|
||||
|
||||
Common::Path NoradAlpha::getEnvScanMovie() {
|
||||
Common::Path movieName = Neighborhood::getEnvScanMovie();
|
||||
|
||||
if (movieName.empty()) {
|
||||
RoomID room = GameState.getCurrentRoom();
|
||||
if (room >= kNorad01 && room <= kNorad01West)
|
||||
return "Images/AI/Norad/XNE1";
|
||||
else if ((room >= kNorad02 && room <= kNorad19West))
|
||||
return "Images/AI/Norad/XNE2";
|
||||
|
||||
return "Images/AI/Norad/XNE3";
|
||||
}
|
||||
|
||||
return movieName;
|
||||
}
|
||||
|
||||
uint NoradAlpha::getNumHints() {
|
||||
uint numHints = Neighborhood::getNumHints();
|
||||
|
||||
if (numHints == 0) {
|
||||
switch (GameState.getCurrentRoomAndView()) {
|
||||
case MakeRoomView(kNorad01, kNorth):
|
||||
case MakeRoomView(kNorad01, kSouth):
|
||||
case MakeRoomView(kNorad01, kEast):
|
||||
case MakeRoomView(kNorad01, kWest):
|
||||
case MakeRoomView(kNorad01East, kEast):
|
||||
case MakeRoomView(kNorad01West, kWest):
|
||||
if (GameState.getNoradGassed()) {
|
||||
if (g_airMask->isAirFilterOn())
|
||||
numHints = 0;
|
||||
else
|
||||
numHints = 3;
|
||||
} else {
|
||||
numHints = 2;
|
||||
}
|
||||
break;
|
||||
case MakeRoomView(kNorad19West, kWest):
|
||||
if (getSubPrepFailed() && GameState.getNoradSubPrepState() != kSubPrepped)
|
||||
numHints = 1;
|
||||
break;
|
||||
case MakeRoomView(kNorad22, kWest):
|
||||
numHints = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return numHints;
|
||||
}
|
||||
|
||||
Common::Path NoradAlpha::getHintMovie(uint hintNum) {
|
||||
Common::Path movieName = Neighborhood::getHintMovie(hintNum);
|
||||
|
||||
if (movieName.empty()) {
|
||||
switch (GameState.getCurrentRoomAndView()) {
|
||||
case MakeRoomView(kNorad01, kNorth):
|
||||
case MakeRoomView(kNorad01, kSouth):
|
||||
case MakeRoomView(kNorad01, kEast):
|
||||
case MakeRoomView(kNorad01, kWest):
|
||||
case MakeRoomView(kNorad01East, kEast):
|
||||
case MakeRoomView(kNorad01West, kWest):
|
||||
switch (hintNum) {
|
||||
case 1:
|
||||
if (GameState.getNoradGassed())
|
||||
return "Images/AI/Norad/XN01SW";
|
||||
|
||||
return "Images/AI/Norad/XN01WD2";
|
||||
case 2:
|
||||
if (GameState.getNoradGassed()) {
|
||||
if (_vm->playerHasItemID(kAirMask))
|
||||
// Mask must not be on if we get here...
|
||||
return "Images/AI/Globals/XGLOB1A";
|
||||
|
||||
return "Images/AI/Globals/XGLOB3D";
|
||||
}
|
||||
|
||||
return "Images/AI/Globals/XGLOB5C";
|
||||
case 3:
|
||||
return "Images/AI/Norad/XN01SH";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MakeRoomView(kNorad19West, kWest):
|
||||
return "Images/AI/Norad/XN19NH";
|
||||
case MakeRoomView(kNorad22, kWest):
|
||||
return "Images/AI/Globals/XGLOB1C";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return movieName;
|
||||
}
|
||||
|
||||
void NoradAlpha::closeDoorOffScreen(const RoomID room, const DirectionConstant) {
|
||||
switch (room) {
|
||||
case kNorad12:
|
||||
case kNorad13:
|
||||
case kNorad18:
|
||||
case kNorad19:
|
||||
playSpotSoundSync(kAlphaElevatorDoorCloseIn, kAlphaElevatorDoorCloseOut);
|
||||
break;
|
||||
default:
|
||||
playSpotSoundSync(kAlphaRegDoorCloseIn, kAlphaRegDoorCloseOut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradAlpha::findSpotEntry(const RoomID room, const DirectionConstant direction, SpotFlags flags, SpotTable::Entry &spotEntry) {
|
||||
if (room == kNorad01 && direction == kSouth)
|
||||
spotEntry.clear();
|
||||
else
|
||||
Norad::findSpotEntry(room, direction, flags, spotEntry);
|
||||
}
|
||||
|
||||
bool NoradAlpha::canSolve() {
|
||||
return Norad::canSolve() || getHintMovie(1) == "Images/AI/Norad/XN01SW";
|
||||
}
|
||||
|
||||
void NoradAlpha::doSolve() {
|
||||
Norad::doSolve();
|
||||
|
||||
if (getHintMovie(1) == "Images/AI/Norad/XN01SW") {
|
||||
_vm->addItemToInventory(g_airMask);
|
||||
g_airMask->putMaskOn();
|
||||
}
|
||||
}
|
||||
|
||||
Common::Path NoradAlpha::getNavMovieName() {
|
||||
return "Images/Norad Alpha/Norad Alpha.movie";
|
||||
}
|
||||
|
||||
Common::Path NoradAlpha::getSoundSpotsName() {
|
||||
return "Sounds/Norad/Norad Alpha Spots";
|
||||
}
|
||||
|
||||
} // End of namespace Pegasus
|
||||
126
engines/pegasus/neighborhood/norad/alpha/noradalpha.h
Normal file
126
engines/pegasus/neighborhood/norad/alpha/noradalpha.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_NORADALPHA_H
|
||||
#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_NORADALPHA_H
|
||||
|
||||
#include "pegasus/neighborhood/norad/norad.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
class Item;
|
||||
class SubChase;
|
||||
|
||||
class NoradAlpha : public Norad {
|
||||
friend class SubChase;
|
||||
public:
|
||||
NoradAlpha(InputHandler *, PegasusEngine *);
|
||||
~NoradAlpha() override;
|
||||
|
||||
void init() override;
|
||||
void start() override;
|
||||
|
||||
bool okayToJump() override;
|
||||
|
||||
void playClawMonitorIntro() override;
|
||||
|
||||
void getExtraCompassMove(const ExtraTable::Entry &, FaderMoveSpec &) override;
|
||||
|
||||
void turnOnFillingStation();
|
||||
void turnOffFillingStation();
|
||||
Item *getFillingItem() { return _fillingStationItem; }
|
||||
bool gasCanisterIntake();
|
||||
|
||||
void takeItemFromRoom(Item *) override;
|
||||
void dropItemIntoRoom(Item *, Hotspot *) override;
|
||||
|
||||
GameInteraction *makeInteraction(const InteractionID) override;
|
||||
|
||||
void getClawInfo(HotSpotID &outSpotID, HotSpotID &prepSpotID, HotSpotID &clawControlSpotID,
|
||||
HotSpotID &pinchClawSpotID, HotSpotID &moveClawDownSpotID, HotSpotID &moveClawRightSpotID,
|
||||
HotSpotID &moveClawLeftSpotID, HotSpotID &moveClawUpSpotID, HotSpotID &clawCCWSpotID,
|
||||
HotSpotID &clawCWSpotID, uint32 &, const uint32 *&) override;
|
||||
|
||||
void loadAmbientLoops() override;
|
||||
|
||||
Common::Path getEnvScanMovie() override;
|
||||
uint getNumHints() override;
|
||||
Common::Path getHintMovie(uint) override;
|
||||
void setUpAIRules() override;
|
||||
|
||||
void setSubPrepFailed(bool value) { _subPrepFailed = value; }
|
||||
bool getSubPrepFailed() { return _subPrepFailed; }
|
||||
|
||||
void closeDoorOffScreen(const RoomID, const DirectionConstant) override;
|
||||
void findSpotEntry(const RoomID, const DirectionConstant, SpotFlags, SpotTable::Entry &) override;
|
||||
void clickInHotspot(const Input &, const Hotspot *) override;
|
||||
|
||||
void checkContinuePoint(const RoomID, const DirectionConstant) override;
|
||||
|
||||
void setSoundFXLevel(const uint16) override;
|
||||
|
||||
bool canSolve() override;
|
||||
void doSolve() override;
|
||||
|
||||
protected:
|
||||
static const uint32 _noradAlphaClawExtras[22];
|
||||
|
||||
virtual void arriveAtNorad01();
|
||||
virtual void arriveAtNorad01East();
|
||||
virtual void arriveAtNorad01West();
|
||||
virtual void arriveAtNorad04();
|
||||
virtual void arriveAtNorad22();
|
||||
|
||||
void arriveAt(const RoomID, const DirectionConstant) override;
|
||||
void turnTo(const DirectionConstant) override;
|
||||
|
||||
void startExtraSequence(const ExtraID, const NotificationFlags, const InputBits) override;
|
||||
|
||||
void getZoomEntry(const HotSpotID, ZoomTable::Entry &) override;
|
||||
TimeValue getViewTime(const RoomID, const DirectionConstant) override;
|
||||
|
||||
void receiveNotification(Notification *, const NotificationFlags) override;
|
||||
|
||||
void activateHotspots() override;
|
||||
|
||||
Hotspot *getItemScreenSpot(Item *, DisplayElement *) override;
|
||||
|
||||
void bumpIntoWall() override;
|
||||
|
||||
Hotspot _thermalScanSpot;
|
||||
|
||||
Movie _extraMovie;
|
||||
NotificationCallBack _extraMovieCallBack;
|
||||
|
||||
Item *_fillingStationItem;
|
||||
|
||||
bool _subPrepFailed;
|
||||
|
||||
Common::Path getSoundSpotsName() override;
|
||||
Common::Path getNavMovieName() override;
|
||||
};
|
||||
|
||||
} // End of namespace Pegasus
|
||||
|
||||
#endif
|
||||
238
engines/pegasus/neighborhood/norad/alpha/panorama.cpp
Normal file
238
engines/pegasus/neighborhood/norad/alpha/panorama.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
/* 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 "common/macresman.h"
|
||||
#include "common/stream.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/panorama.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
Panorama::Panorama() : _panoramaMovie(kNoDisplayElement) {
|
||||
blankFields();
|
||||
}
|
||||
|
||||
Panorama::~Panorama() {
|
||||
releasePanorama();
|
||||
}
|
||||
|
||||
void Panorama::blankFields() {
|
||||
_viewBounds = Common::Rect();
|
||||
_drawBounds = Common::Rect();
|
||||
_mask = nullptr;
|
||||
_panoramaWidth = 0;
|
||||
_panoramaHeight = 0;
|
||||
_stripWidth = 0;
|
||||
_stripLeft = -1;
|
||||
_stripRight = -1;
|
||||
}
|
||||
|
||||
void Panorama::releasePanorama() {
|
||||
if (_panoramaMovie.isMovieValid()) {
|
||||
_panoramaMovie.releaseMovie();
|
||||
_panoramaWorld.deallocateSurface();
|
||||
blankFields();
|
||||
}
|
||||
}
|
||||
|
||||
static const uint32 kPanoramaResType = MKTAG('P', 'a', 'n', 'I'); // Panorama Information.
|
||||
static const uint16 kPanoramaResID = 128;
|
||||
|
||||
void Panorama::initFromMovieFile(const Common::Path &fileName) {
|
||||
// First, we need the resource fork for other reasons -- PanI resource
|
||||
Common::MacResManager *resFork = new Common::MacResManager();
|
||||
if (!resFork->open(fileName) || !resFork->hasResFork())
|
||||
error("Could not open the resource fork of '%s'", fileName.toString().c_str());
|
||||
|
||||
Common::SeekableReadStream *resource = resFork->getResource(kPanoramaResType, kPanoramaResID);
|
||||
if (!resource)
|
||||
error("No panorama information in the resource fork of '%s'", fileName.toString().c_str());
|
||||
|
||||
_panoramaWidth = resource->readUint16BE();
|
||||
_panoramaHeight = resource->readUint16BE();
|
||||
_stripWidth = resource->readUint16BE();
|
||||
|
||||
delete resource;
|
||||
delete resFork;
|
||||
|
||||
// Now we open the movie like normal
|
||||
_panoramaMovie.initFromMovieFile(fileName);
|
||||
}
|
||||
|
||||
void Panorama::setMask(Surface *mask) {
|
||||
_mask = mask;
|
||||
}
|
||||
|
||||
// If the panorama is not open, do nothing and return.
|
||||
// Otherwise, set up the view bounds.
|
||||
void Panorama::setViewBounds(const Common::Rect &newView) {
|
||||
if (!isPanoramaOpen())
|
||||
return;
|
||||
|
||||
if (newView.isEmpty())
|
||||
return;
|
||||
|
||||
Common::Rect r = newView;
|
||||
|
||||
if (r.width() > _panoramaWidth) {
|
||||
r.left = 0;
|
||||
r.right = _panoramaWidth;
|
||||
} else {
|
||||
if (r.right > _panoramaWidth)
|
||||
r.translate(_panoramaWidth - r.right, 0);
|
||||
|
||||
if (r.left < 0)
|
||||
r.translate(-r.left, 0);
|
||||
}
|
||||
|
||||
if (r.height() > _panoramaHeight) {
|
||||
r.top = 0;
|
||||
r.bottom = _panoramaHeight;
|
||||
} else {
|
||||
if (r.bottom > _panoramaHeight)
|
||||
r.translate(0, _panoramaHeight - r.bottom);
|
||||
|
||||
if (r.top < 0)
|
||||
r.translate(0, -r.top);
|
||||
}
|
||||
|
||||
if (_viewBounds != r) {
|
||||
CoordType stripLeft = 0;
|
||||
|
||||
if (r.width() != _viewBounds.width() || !_panoramaWorld.isSurfaceValid()) {
|
||||
_panoramaWorld.deallocateSurface();
|
||||
makeNewSurface(r);
|
||||
} else {
|
||||
CoordType stripRight;
|
||||
calcStripRange(r, stripLeft, stripRight);
|
||||
loadStrips(stripLeft, stripRight);
|
||||
}
|
||||
|
||||
_viewBounds = r;
|
||||
_drawBounds = r;
|
||||
_drawBounds.translate(-stripLeft * _stripWidth, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Panorama::getViewBounds(Common::Rect &r) const {
|
||||
r = _viewBounds;
|
||||
}
|
||||
|
||||
void Panorama::getPanoramaBounds(Common::Rect &r) const {
|
||||
r = Common::Rect(0, 0, _panoramaWidth, _panoramaHeight);
|
||||
}
|
||||
|
||||
void Panorama::drawPanorama(const Common::Rect &destRect) {
|
||||
if (_panoramaWorld.isSurfaceValid()) {
|
||||
if (_mask)
|
||||
_panoramaWorld.copyToCurrentPortMasked(_drawBounds, destRect, _mask);
|
||||
else
|
||||
_panoramaWorld.copyToCurrentPortTransparent(_drawBounds, destRect);
|
||||
}
|
||||
}
|
||||
|
||||
// Make a new Surface big enough to show r, which is assumed to be a valid view bounds.
|
||||
// Assumptions:
|
||||
// r is a valid view bounds.
|
||||
// _panoramaWorld is not allocated.
|
||||
// _panoramaHeight, _stripWidth is correct.
|
||||
// _panoramaMovie is allocated.
|
||||
void Panorama::makeNewSurface(const Common::Rect& view) {
|
||||
CoordType stripLeft, stripRight;
|
||||
calcStripRange(view, stripLeft, stripRight);
|
||||
|
||||
Common::Rect r(0, 0, (stripRight - stripLeft + 1) * _stripWidth, _panoramaHeight);
|
||||
_panoramaWorld.allocateSurface(r);
|
||||
_panoramaMovie.shareSurface(&_panoramaWorld);
|
||||
loadStrips(stripLeft, stripRight);
|
||||
}
|
||||
|
||||
// Assumes view is not empty.
|
||||
void Panorama::calcStripRange(const Common::Rect &view, CoordType &stripLeft, CoordType &stripRight) {
|
||||
stripLeft = view.left / _stripWidth;
|
||||
stripRight = (view.left - view.left % _stripWidth + _stripWidth - 1 + view.width()) / _stripWidth;
|
||||
}
|
||||
|
||||
// Load in all needed strips to put range (stripLeft, stripRight) into the
|
||||
// panorama's Surface. Try to optimize by saving any pixels already in the Surface.
|
||||
// Assumptions:
|
||||
// Surface is allocated and is big enough for maximum range of
|
||||
// stripLeft and stripRight
|
||||
void Panorama::loadStrips(CoordType stripLeft, CoordType stripRight) {
|
||||
if (_stripLeft == -1) {
|
||||
// Surface has just been allocated.
|
||||
// Load in all strips.
|
||||
for (CoordType i = stripLeft; i <= stripRight; i++)
|
||||
loadOneStrip(i, stripLeft);
|
||||
|
||||
_stripLeft = stripLeft;
|
||||
_stripRight = stripRight;
|
||||
} else if (stripLeft != _stripLeft) {
|
||||
CoordType overlapLeft = MAX(stripLeft, _stripLeft);
|
||||
CoordType overlapRight = MIN(stripRight, _stripRight);
|
||||
|
||||
if (overlapLeft <= overlapRight) {
|
||||
Common::Rect r1((overlapLeft - _stripLeft) * _stripWidth, 0,
|
||||
(overlapRight - _stripLeft + 1) * _stripWidth, _panoramaHeight);
|
||||
|
||||
if (stripLeft < _stripLeft) {
|
||||
Common::Rect bounds;
|
||||
_panoramaWorld.getSurfaceBounds(bounds);
|
||||
_panoramaWorld.getSurface()->move(bounds.right - r1.right, 0, _panoramaHeight);
|
||||
|
||||
for (CoordType i = stripLeft; i < _stripLeft; i++)
|
||||
loadOneStrip(i, stripLeft);
|
||||
} else {
|
||||
_panoramaWorld.getSurface()->move(-r1.left, 0, _panoramaHeight);
|
||||
|
||||
for (CoordType i = _stripRight + 1; i <= stripRight; i++)
|
||||
loadOneStrip(i, stripLeft);
|
||||
}
|
||||
} else {
|
||||
// No overlap.
|
||||
// Load everything.
|
||||
for (CoordType i = stripLeft; i <= stripRight; i++)
|
||||
loadOneStrip(i, stripLeft);
|
||||
}
|
||||
|
||||
_stripLeft = stripLeft;
|
||||
_stripRight = stripRight;
|
||||
} else if (stripRight > _stripRight) {
|
||||
// Need to add one or more strips.
|
||||
for (CoordType i = _stripRight + 1; i <= stripRight; i++)
|
||||
loadOneStrip(i, _stripLeft);
|
||||
|
||||
_stripRight = stripRight;
|
||||
} else if (stripRight < _stripRight) {
|
||||
// Need to chop off one strip.
|
||||
_stripRight = stripRight;
|
||||
}
|
||||
}
|
||||
|
||||
void Panorama::loadOneStrip(CoordType stripToLoad, CoordType leftStrip) {
|
||||
_panoramaMovie.moveMovieBoxTo((stripToLoad - leftStrip) * _stripWidth, 0);
|
||||
_panoramaMovie.setTime(stripToLoad, 1);
|
||||
_panoramaMovie.redrawMovieWorld();
|
||||
}
|
||||
|
||||
} // End of namespace Pegasus
|
||||
97
engines/pegasus/neighborhood/norad/alpha/panorama.h
Normal file
97
engines/pegasus/neighborhood/norad/alpha/panorama.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_PANORAMA_H
|
||||
#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_PANORAMA_H
|
||||
|
||||
#include "pegasus/movie.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
/*
|
||||
|
||||
Panorama implements a wide image using a specially constructed movie file.
|
||||
The movie holds the image as a series of vertical strips, say 16 or 32 pixels wide.
|
||||
|
||||
The panorama bounds defines the entire panorama. The view bounds represents the
|
||||
area on the panorama that is kept in memory.
|
||||
|
||||
The panorama bounds is also stored in the movie file; it cannot be changed. The
|
||||
view bounds must always be a subset of the panorama bounds.
|
||||
|
||||
In actuality, the area kept in memory is at least as wide as the view bounds (but
|
||||
may be wider to coincide with the width of the movies slices), and is as tall as
|
||||
the panorama bounds. The view bounds is used by the drawPanorama function to draw
|
||||
a piece of the panorama to the current screen.
|
||||
|
||||
The panorama movie is built at a time scale of 1, with each strip lasting for one
|
||||
second, so that strip number corresponds exactly with the time value at which the
|
||||
strip is stored.
|
||||
|
||||
TO USE:
|
||||
|
||||
Call one initFromMovieFile to open the movie. Then set up a view rect by
|
||||
calling setViewBounds. Once these two functions have been called, drawPanorama
|
||||
will draw the panorama.
|
||||
|
||||
*/
|
||||
|
||||
class Panorama {
|
||||
public:
|
||||
Panorama();
|
||||
virtual ~Panorama();
|
||||
|
||||
void initFromMovieFile(const Common::Path &);
|
||||
void releasePanorama();
|
||||
bool isPanoramaOpen() { return _panoramaMovie.isMovieValid(); }
|
||||
|
||||
void setViewBounds(const Common::Rect &);
|
||||
void getViewBounds(Common::Rect &) const;
|
||||
|
||||
void setMask(Surface *);
|
||||
|
||||
void getPanoramaBounds(Common::Rect &) const;
|
||||
|
||||
void drawPanorama(const Common::Rect &);
|
||||
|
||||
protected:
|
||||
void blankFields();
|
||||
void makeNewSurface(const Common::Rect &);
|
||||
void calcStripRange(const Common::Rect &, CoordType &, CoordType &);
|
||||
void loadStrips(CoordType, CoordType);
|
||||
void loadOneStrip(CoordType, CoordType);
|
||||
|
||||
Movie _panoramaMovie;
|
||||
Surface _panoramaWorld, *_mask;
|
||||
Common::Rect _viewBounds;
|
||||
Common::Rect _drawBounds;
|
||||
CoordType _panoramaWidth, _panoramaHeight;
|
||||
CoordType _stripWidth; // Pixels per strip.
|
||||
CoordType _numStrips;
|
||||
CoordType _stripLeft, _stripRight;
|
||||
};
|
||||
|
||||
} // End of namespace Pegasus
|
||||
|
||||
#endif
|
||||
90
engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp
Normal file
90
engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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/neighborhood/norad/alpha/panoramascroll.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
PanoramaScroll::PanoramaScroll(const DisplayElementID id) : IdlerAnimation(id) {
|
||||
_boundsWidth = 0;
|
||||
_totalWidth = 0;
|
||||
}
|
||||
|
||||
void PanoramaScroll::initFromMovieFile(const Common::Path &fileName) {
|
||||
_panorama.initFromMovieFile(fileName);
|
||||
|
||||
Common::Rect r;
|
||||
_panorama.getPanoramaBounds(r);
|
||||
_totalWidth = r.width();
|
||||
}
|
||||
|
||||
void PanoramaScroll::initMaskFromPICTFile(const Common::Path &fileName) {
|
||||
if (!_panorama.isPanoramaOpen())
|
||||
return;
|
||||
|
||||
_mask.getImageFromPICTFile(fileName);
|
||||
_panorama.setMask(&_mask);
|
||||
}
|
||||
|
||||
void PanoramaScroll::releasePanorama() {
|
||||
if (_panorama.isPanoramaOpen())
|
||||
_panorama.releasePanorama();
|
||||
|
||||
_mask.deallocateSurface();
|
||||
}
|
||||
|
||||
void PanoramaScroll::setBounds(const Common::Rect &r) {
|
||||
Animation::setBounds(r);
|
||||
|
||||
_boundsWidth = r.width();
|
||||
|
||||
Common::Rect r2;
|
||||
_panorama.getViewBounds(r2);
|
||||
r2.right = r2.left + _boundsWidth;
|
||||
r2.bottom = r2.top + r.height();
|
||||
_panorama.setViewBounds(r2);
|
||||
}
|
||||
|
||||
void PanoramaScroll::draw(const Common::Rect &) {
|
||||
_panorama.drawPanorama(_bounds);
|
||||
}
|
||||
|
||||
void PanoramaScroll::timeChanged(const TimeValue newTime) {
|
||||
CoordType leftPixel = (_totalWidth - _boundsWidth) * newTime / getDuration();
|
||||
|
||||
Common::Rect r;
|
||||
_panorama.getViewBounds(r);
|
||||
if (leftPixel != r.left) {
|
||||
_panorama.getViewBounds(r);
|
||||
r.moveTo(leftPixel, 0);
|
||||
_panorama.setViewBounds(r);
|
||||
triggerRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
void PanoramaScroll::getPanoramaBounds(Common::Rect &r) const {
|
||||
_panorama.getPanoramaBounds(r);
|
||||
}
|
||||
|
||||
} // End of namespace Pegasus
|
||||
59
engines/pegasus/neighborhood/norad/alpha/panoramascroll.h
Normal file
59
engines/pegasus/neighborhood/norad/alpha/panoramascroll.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_PANORAMASCROLL_H
|
||||
#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_PANORAMASCROLL_H
|
||||
|
||||
#include "pegasus/neighborhood/norad/alpha/panorama.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
class PanoramaScroll : public IdlerAnimation {
|
||||
public:
|
||||
PanoramaScroll(const DisplayElementID);
|
||||
~PanoramaScroll() override {}
|
||||
|
||||
void initFromMovieFile(const Common::Path &);
|
||||
void initMaskFromPICTFile(const Common::Path &);
|
||||
|
||||
void releasePanorama();
|
||||
|
||||
bool isPanoramaOpen() { return _panorama.isPanoramaOpen(); }
|
||||
void getPanoramaBounds(Common::Rect &) const;
|
||||
|
||||
void setBounds(const Common::Rect&) override;
|
||||
|
||||
void draw(const Common::Rect &) override;
|
||||
|
||||
protected:
|
||||
void timeChanged(const TimeValue) override;
|
||||
|
||||
Panorama _panorama;
|
||||
Surface _mask;
|
||||
CoordType _totalWidth, _boundsWidth;
|
||||
};
|
||||
|
||||
} // End of namespace Pegasus
|
||||
|
||||
#endif
|
||||
458
engines/pegasus/neighborhood/norad/alpha/subchase.cpp
Normal file
458
engines/pegasus/neighborhood/norad/alpha/subchase.cpp
Normal file
@@ -0,0 +1,458 @@
|
||||
/* 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-2013 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/gamestate.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/subchase.h"
|
||||
#include "pegasus/neighborhood/norad/alpha/noradalpha.h"
|
||||
#include "pegasus/neighborhood/norad/constants.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
static const TimeScale kSubChaseScale = 600;
|
||||
|
||||
static const DisplayOrder kSubChaseOrder = 27000;
|
||||
|
||||
// Segment start and end points.
|
||||
|
||||
static const TimeValue kIntroStart = 0;
|
||||
static const TimeValue kIntroEnd = 2400;
|
||||
static const TimeValue kDialogStart = kIntroEnd;
|
||||
static const TimeValue kDialogEnd = 20920;
|
||||
static const TimeValue kBranch1Start = kDialogEnd;
|
||||
static const TimeValue kBranch1End = 32120;
|
||||
static const TimeValue kBranch2LeftStart = kBranch1End;
|
||||
static const TimeValue kBranch2LeftEnd = 48080;
|
||||
static const TimeValue kBranch3Start = kBranch2LeftEnd;
|
||||
static const TimeValue kBranch3End = 61080;
|
||||
static const TimeValue kBranch4Start = kBranch3End;
|
||||
static const TimeValue kBranch4End = 84080;
|
||||
static const TimeValue kBranch5Start = kBranch4End;
|
||||
static const TimeValue kBranch5End = 94840;
|
||||
static const TimeValue kBranch6Start = kBranch5End;
|
||||
static const TimeValue kBranch6End = 106040;
|
||||
static const TimeValue kBranch7LeftStart = kBranch6End;
|
||||
static const TimeValue kBranch7LeftEnd = 118840;
|
||||
static const TimeValue kExitStart = kBranch7LeftEnd;
|
||||
static const TimeValue kExitEnd = 133200;
|
||||
static const TimeValue kBranch2RightStart = 133200;
|
||||
static const TimeValue kBranch2RightEnd = 149160;
|
||||
static const TimeValue kBranch7RightStart = 168000;
|
||||
static const TimeValue kBranch7RightEnd = 180800;
|
||||
|
||||
// Death start and end points.
|
||||
|
||||
static const TimeValue kDeath4Start = 149160;
|
||||
static const TimeValue kDeath4End = 158040;
|
||||
static const TimeValue kDeath5Start = kDeath4End;
|
||||
static const TimeValue kDeath5End = 163760;
|
||||
static const TimeValue kDeath6Start = kDeath5End;
|
||||
static const TimeValue kDeath6End = 168000;
|
||||
static const TimeValue kDeath7Start = 180800;
|
||||
static const TimeValue kDeath7End = 187040;
|
||||
|
||||
// Chase state.
|
||||
|
||||
enum {
|
||||
kSubDialog,
|
||||
kSubBranch1,
|
||||
kSubBranch2Left,
|
||||
kSubBranch2Right,
|
||||
kSubBranch3,
|
||||
kSubBranch4,
|
||||
kSubBranch5,
|
||||
kSubBranch6,
|
||||
kSubBranch7Left,
|
||||
kSubBranch7Right,
|
||||
kSubExit
|
||||
};
|
||||
|
||||
void HintTimerEvent::fire() {
|
||||
subChase->hintTimerExpired(*this);
|
||||
}
|
||||
|
||||
void BlinkTimerEvent::fire() {
|
||||
subChase->blinkTimerExpired(*this);
|
||||
}
|
||||
|
||||
SubChase::SubChase(Neighborhood *handler) : ChaseInteraction(kNoradSubChaseInteractionID, handler,
|
||||
kNoradSubChaseNotificationID, g_vm), _subMovie(kNoDisplayElement),
|
||||
_hintPict(kNoDisplayElement), _blinkPict(kNoDisplayElement), _canSteerSub(true) {
|
||||
}
|
||||
|
||||
void SubChase::setSoundFXLevel(const uint16 fxLevel) {
|
||||
_subMovie.setVolume(fxLevel);
|
||||
}
|
||||
|
||||
void SubChase::openInteraction() {
|
||||
_subMovie.initFromMovieFile("Images/Norad Alpha/Sub Chase Movie");
|
||||
_subMovie.setVolume(g_vm->getSoundFXLevel());
|
||||
_subMovie.moveElementTo(0, 0);
|
||||
_subMovie.setDisplayOrder(kSubChaseOrder);
|
||||
_subMovie.startDisplaying();
|
||||
_subMovie.show();
|
||||
|
||||
_subCallBack.setNotification(&_chaseNotification);
|
||||
_subCallBack.initCallBack(&_subMovie, kCallBackAtExtremes);
|
||||
|
||||
ChaseInteraction::openInteraction();
|
||||
|
||||
_steerPict.setDisplayOrder(kSubChaseOrder + 1);
|
||||
_steerPict.moveElementTo(kNoradSubSteerLeft, kNoradSubSteerTop);
|
||||
|
||||
_hintPict.initFromPICTFile("Images/Norad Alpha/Sub Chase steerk1.pict", true);
|
||||
_hintPict.setDisplayOrder(kSubChaseOrder + 1);
|
||||
_hintPict.moveElementTo(kNoradSubHintLeft, kNoradSubHintTop);
|
||||
_blinkPict.initFromPICTFile("Images/Norad Alpha/Sub Chase steerk0.pict", true);
|
||||
_blinkPict.setDisplayOrder(kSubChaseOrder + 1);
|
||||
_blinkPict.moveElementTo(kNoradSubHintLeft, kNoradSubHintTop);
|
||||
}
|
||||
|
||||
void SubChase::initInteraction() {
|
||||
_canSteerSub = !GameState.getWalkthroughMode();
|
||||
|
||||
_owner->playMovieSegment(&_subMovie, kIntroStart, kIntroEnd);
|
||||
|
||||
_subCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
|
||||
if (_canSteerSub) {
|
||||
_steerPict.startDisplaying();
|
||||
_hintPict.startDisplaying();
|
||||
_blinkPict.startDisplaying();
|
||||
startHintTimer(20000 - kDialogStart, kSubChaseScale, kStartedHint);
|
||||
_subCallBack.setCallBackFlag(kChaseEnteredBranchZone);
|
||||
_subMovie.setSegment(kDialogStart, kBranch1End - kDecisionTime);
|
||||
} else {
|
||||
_subCallBack.setCallBackFlag(kChaseFinished);
|
||||
_subMovie.setSegment(kDialogStart, kExitEnd);
|
||||
}
|
||||
|
||||
_subState = kSubDialog;
|
||||
_subMovie.setTime(kDialogStart);
|
||||
_subMovie.start();
|
||||
|
||||
ChaseInteraction::initInteraction();
|
||||
}
|
||||
|
||||
void SubChase::closeInteraction() {
|
||||
_subMovie.stop();
|
||||
_subMovie.stopDisplaying();
|
||||
_subMovie.releaseMovie();
|
||||
_subCallBack.releaseCallBack();
|
||||
|
||||
_hintPict.hide();
|
||||
_hintPict.deallocateSurface();
|
||||
|
||||
_blinkPict.hide();
|
||||
_blinkPict.deallocateSurface();
|
||||
|
||||
ChaseInteraction::closeInteraction();
|
||||
}
|
||||
|
||||
void SubChase::receiveNotification(Notification *notification, const NotificationFlags flags) {
|
||||
if (notification == &_chaseNotification && flags == kChaseFinished) {
|
||||
if (_subState != kSubDialog && _subState != kSubExit) {
|
||||
// We died
|
||||
((NoradAlpha *)_owner)->die(kDeathSubDestroyed);
|
||||
} else {
|
||||
_subMovie.stopDisplaying();
|
||||
g_vm->_gfx->enableErase();
|
||||
g_vm->_gfx->updateDisplay();
|
||||
g_vm->_gfx->disableErase();
|
||||
g_vm->jumpToNewEnvironment(kNoradDeltaID, kNorad41, kEast);
|
||||
}
|
||||
}
|
||||
ChaseInteraction::receiveNotification(notification, flags);
|
||||
}
|
||||
|
||||
void SubChase::handleInput(const Input &input, const Hotspot *cursorSpot) {
|
||||
if (_subMovie.getTime() < kBranch1Start && input.anyInput()) {
|
||||
if (_canSteerSub) {
|
||||
if (!_blinkFuse.isFuseLit()) {
|
||||
// If the hint is not blinking then it must not be running, so display it
|
||||
_hintPict.show();
|
||||
startBlinkTimer(10, 10, kEnteredBlinkState);
|
||||
}
|
||||
_subState = kSubBranch1;
|
||||
startHintTimer(3000, kSubChaseScale, kEndedHint);
|
||||
} else {
|
||||
_subState = kSubExit;
|
||||
}
|
||||
_subMovie.setTime(kBranch1Start);
|
||||
} else {
|
||||
ChaseInteraction::handleInput(input, cursorSpot);
|
||||
}
|
||||
}
|
||||
|
||||
void SubChase::setUpBranch() {
|
||||
TimeValue branchStart, branchEnd;
|
||||
|
||||
branchStart = 0;
|
||||
branchEnd = 0;
|
||||
switch (_subState) {
|
||||
case kSubDialog:
|
||||
case kSubBranch1:
|
||||
branchStart = kBranch1End - kDecisionTime;
|
||||
branchEnd = kBranch1End;
|
||||
break;
|
||||
case kSubBranch2Left:
|
||||
branchStart = kBranch2LeftEnd - kDecisionTime;
|
||||
branchEnd = kBranch2LeftEnd;
|
||||
break;
|
||||
case kSubBranch2Right:
|
||||
branchStart = kBranch2RightEnd - kDecisionTime;
|
||||
branchEnd = kBranch2RightEnd;
|
||||
break;
|
||||
case kSubBranch3:
|
||||
branchStart = kBranch3End - kDecisionTime;
|
||||
branchEnd = kBranch3End;
|
||||
break;
|
||||
case kSubBranch4:
|
||||
branchStart = kBranch4End - kDecisionTime;
|
||||
branchEnd = kBranch4End;
|
||||
break;
|
||||
case kSubBranch5:
|
||||
branchStart = kBranch5End - kDecisionTime;
|
||||
branchEnd = kBranch5End;
|
||||
break;
|
||||
case kSubBranch6:
|
||||
branchStart = kBranch6End - kDecisionTime;
|
||||
branchEnd = kBranch6End;
|
||||
break;
|
||||
case kSubBranch7Left:
|
||||
branchStart = kBranch7LeftEnd - kDecisionTime;
|
||||
branchEnd = kBranch7LeftEnd;
|
||||
break;
|
||||
case kSubBranch7Right:
|
||||
branchStart = kBranch7RightEnd - kDecisionTime;
|
||||
branchEnd = kBranch7RightEnd;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_subMovie.setSegment(branchStart, branchEnd);
|
||||
|
||||
_subCallBack.setCallBackFlag(kChaseExitedBranchZone);
|
||||
_subCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
}
|
||||
|
||||
void SubChase::branchLeft() {
|
||||
TimeValue branchStart, branchEnd;
|
||||
NotificationFlags flag;
|
||||
|
||||
branchStart = 0;
|
||||
branchEnd = 0;
|
||||
flag = 0;
|
||||
switch (_subState) {
|
||||
case kSubDialog:
|
||||
case kSubBranch1:
|
||||
branchStart = kBranch2LeftStart;
|
||||
branchEnd = kBranch2LeftEnd;
|
||||
// Don't show the controls hint when we approach the whale
|
||||
// since the branch segments here are identical
|
||||
flag = kChaseExitedBranchZone;
|
||||
_subState = kSubBranch2Left;
|
||||
break;
|
||||
case kSubBranch2Left:
|
||||
case kSubBranch2Right:
|
||||
branchStart = kBranch3Start;
|
||||
branchEnd = kBranch3End - kDecisionTime;
|
||||
flag = kChaseEnteredBranchZone;
|
||||
_subState = kSubBranch3;
|
||||
break;
|
||||
case kSubBranch3:
|
||||
branchStart = kBranch4Start;
|
||||
branchEnd = kBranch4End - kDecisionTime;
|
||||
flag = kChaseEnteredBranchZone;
|
||||
_subState = kSubBranch4;
|
||||
break;
|
||||
case kSubBranch4:
|
||||
branchStart = kDeath5Start;
|
||||
branchEnd = kDeath5End;
|
||||
flag = kChaseFinished;
|
||||
_subState = kSubBranch5;
|
||||
break;
|
||||
case kSubBranch5:
|
||||
branchStart = kBranch6Start;
|
||||
branchEnd = kBranch6End - kDecisionTime;
|
||||
flag = kChaseEnteredBranchZone;
|
||||
_subState = kSubBranch6;
|
||||
break;
|
||||
case kSubBranch6:
|
||||
branchStart = kBranch7LeftStart;
|
||||
branchEnd = kBranch7LeftEnd;
|
||||
flag = kChaseExitedBranchZone;
|
||||
_subState = kSubBranch7Left;
|
||||
break;
|
||||
case kSubBranch7Left:
|
||||
case kSubBranch7Right:
|
||||
branchStart = kExitStart;
|
||||
branchEnd = kExitEnd;
|
||||
flag = kChaseFinished;
|
||||
_subState = kSubExit;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_subMovie.setSegment(branchStart, branchEnd);
|
||||
_subMovie.setTime(branchStart);
|
||||
|
||||
_subCallBack.setCallBackFlag(flag);
|
||||
_subCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
}
|
||||
|
||||
void SubChase::branchRight() {
|
||||
TimeValue branchStart, branchEnd;
|
||||
NotificationFlags flag;
|
||||
|
||||
branchStart = 0;
|
||||
branchEnd = 0;
|
||||
flag = 0;
|
||||
switch (_subState) {
|
||||
case kSubDialog:
|
||||
case kSubBranch1:
|
||||
branchStart = kBranch2RightStart;
|
||||
branchEnd = kBranch2RightEnd;
|
||||
// Don't show the controls hint when we approach the whale
|
||||
// since the branch segments here are identical
|
||||
flag = kChaseExitedBranchZone;
|
||||
_subState = kSubBranch2Right;
|
||||
break;
|
||||
case kSubBranch2Left:
|
||||
case kSubBranch2Right:
|
||||
branchStart = kBranch3Start;
|
||||
branchEnd = kBranch3End - kDecisionTime;
|
||||
flag = kChaseEnteredBranchZone;
|
||||
_subState = kSubBranch3;
|
||||
break;
|
||||
case kSubBranch3:
|
||||
branchStart = kDeath4Start;
|
||||
branchEnd = kDeath4End;
|
||||
flag = kChaseFinished;
|
||||
_subState = kSubBranch4;
|
||||
break;
|
||||
case kSubBranch4:
|
||||
branchStart = kBranch5Start;
|
||||
branchEnd = kBranch5End - kDecisionTime;
|
||||
flag = kChaseEnteredBranchZone;
|
||||
_subState = kSubBranch5;
|
||||
break;
|
||||
case kSubBranch5:
|
||||
branchStart = kDeath6Start;
|
||||
branchEnd = kDeath6End;
|
||||
flag = kChaseFinished;
|
||||
_subState = kSubBranch6;
|
||||
break;
|
||||
case kSubBranch6:
|
||||
if (g_vm->getRandomBit()) {
|
||||
branchStart = kBranch7RightStart;
|
||||
branchEnd = kBranch7RightEnd;
|
||||
flag = kChaseExitedBranchZone;
|
||||
} else {
|
||||
branchStart = kDeath7Start;
|
||||
branchEnd = kDeath7End;
|
||||
flag = kChaseFinished;
|
||||
}
|
||||
_subState = kSubBranch7Right;
|
||||
break;
|
||||
case kSubBranch7Left:
|
||||
case kSubBranch7Right:
|
||||
branchStart = kExitStart;
|
||||
branchEnd = kExitEnd;
|
||||
flag = kChaseFinished;
|
||||
_subState = kSubExit;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_subMovie.setSegment(branchStart, branchEnd);
|
||||
_subMovie.setTime(branchStart);
|
||||
|
||||
_subCallBack.setCallBackFlag(flag);
|
||||
_subCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
||||
}
|
||||
|
||||
void SubChase::dontBranch() {
|
||||
if (g_vm->getRandomBit())
|
||||
branchLeft();
|
||||
else
|
||||
branchRight();
|
||||
}
|
||||
|
||||
void SubChase::startHintTimer(TimeValue time, TimeScale scale, HintTimerCode code) {
|
||||
if (_canSteerSub) {
|
||||
_hintFuse.primeFuse(time, scale);
|
||||
_hintEvent.subChase = this;
|
||||
_hintEvent.theEvent = code;
|
||||
_hintFuse.setFunctor(new Common::Functor0Mem<void, HintTimerEvent>(&_hintEvent, &HintTimerEvent::fire));
|
||||
_hintFuse.lightFuse();
|
||||
}
|
||||
}
|
||||
|
||||
void SubChase::hintTimerExpired(HintTimerEvent &event) {
|
||||
switch (event.theEvent) {
|
||||
case kStartedHint:
|
||||
_hintPict.show();
|
||||
startBlinkTimer(10, 10, kEnteredBlinkState);
|
||||
startHintTimer(3920, kSubChaseScale, kEndedHint);
|
||||
break;
|
||||
case kEndedHint:
|
||||
_hintPict.hide();
|
||||
_blinkPict.hide();
|
||||
_blinkFuse.stopFuse();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SubChase::startBlinkTimer(TimeValue time, TimeScale scale, BlinkTimerCode code) {
|
||||
_blinkFuse.primeFuse(time, scale);
|
||||
_blinkEvent.subChase = this;
|
||||
_blinkEvent.theEvent = code;
|
||||
_blinkFuse.setFunctor(new Common::Functor0Mem<void, BlinkTimerEvent>(&_blinkEvent, &BlinkTimerEvent::fire));
|
||||
_blinkFuse.lightFuse();
|
||||
}
|
||||
|
||||
void SubChase::blinkTimerExpired(BlinkTimerEvent &event) {
|
||||
switch (event.theEvent) {
|
||||
case kEnteredBlinkState:
|
||||
_hintPict.hide();
|
||||
_blinkPict.show();
|
||||
startBlinkTimer(5, 10, kExitedBlinkState);
|
||||
break;
|
||||
case kExitedBlinkState:
|
||||
_blinkPict.hide();
|
||||
_hintPict.show();
|
||||
startBlinkTimer(10, 10, kEnteredBlinkState);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Pegasus
|
||||
110
engines/pegasus/neighborhood/norad/alpha/subchase.h
Normal file
110
engines/pegasus/neighborhood/norad/alpha/subchase.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* 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-2013 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_SUBCHASE_H
|
||||
#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_SUBCHASE_H
|
||||
|
||||
#include "pegasus/chase.h"
|
||||
#include "pegasus/movie.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
class NoradAlpha;
|
||||
class SubChase;
|
||||
|
||||
enum HintTimerCode {
|
||||
kStartedHint,
|
||||
kEndedHint
|
||||
};
|
||||
|
||||
struct HintTimerEvent {
|
||||
SubChase *subChase;
|
||||
HintTimerCode theEvent;
|
||||
|
||||
void fire();
|
||||
};
|
||||
|
||||
enum BlinkTimerCode {
|
||||
kEnteredBlinkState,
|
||||
kExitedBlinkState
|
||||
};
|
||||
|
||||
struct BlinkTimerEvent {
|
||||
SubChase *subChase;
|
||||
BlinkTimerCode theEvent;
|
||||
|
||||
void fire();
|
||||
};
|
||||
|
||||
class SubChase : public ChaseInteraction {
|
||||
friend class NoradAlpha;
|
||||
friend struct HintTimerEvent;
|
||||
friend struct BlinkTimerEvent;
|
||||
public:
|
||||
|
||||
SubChase(Neighborhood *);
|
||||
virtual ~SubChase() {}
|
||||
|
||||
void setSoundFXLevel(const uint16);
|
||||
|
||||
void handleInput(const Input &, const Hotspot *);
|
||||
|
||||
protected:
|
||||
|
||||
void openInteraction();
|
||||
void initInteraction();
|
||||
void closeInteraction();
|
||||
|
||||
void receiveNotification(Notification *, const NotificationFlags);
|
||||
|
||||
void startBranching();
|
||||
void setUpBranch();
|
||||
void branchLeft();
|
||||
void branchRight();
|
||||
void dontBranch();
|
||||
|
||||
void startHintTimer(TimeValue, TimeScale, HintTimerCode);
|
||||
void hintTimerExpired(HintTimerEvent &);
|
||||
|
||||
void startBlinkTimer(TimeValue, TimeScale, BlinkTimerCode);
|
||||
void blinkTimerExpired(BlinkTimerEvent &);
|
||||
|
||||
Movie _subMovie;
|
||||
NotificationCallBack _subCallBack;
|
||||
Picture _hintPict;
|
||||
Picture _blinkPict;
|
||||
FuseFunction _hintFuse;
|
||||
FuseFunction _blinkFuse;
|
||||
|
||||
HintTimerEvent _hintEvent;
|
||||
BlinkTimerEvent _blinkEvent;
|
||||
|
||||
short _subState;
|
||||
|
||||
bool _canSteerSub;
|
||||
};
|
||||
|
||||
} // End of namespace Pegasus
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user