Initial commit
This commit is contained in:
1270
engines/pegasus/neighborhood/norad/delta/globegame.cpp
Normal file
1270
engines/pegasus/neighborhood/norad/delta/globegame.cpp
Normal file
File diff suppressed because it is too large
Load Diff
172
engines/pegasus/neighborhood/norad/delta/globegame.h
Normal file
172
engines/pegasus/neighborhood/norad/delta/globegame.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/* 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_DELTA_GLOBEGAME_H
|
||||
#define PEGASUS_NEIGHBORHOOD_NORAD_DELTA_GLOBEGAME_H
|
||||
|
||||
#include "pegasus/interaction.h"
|
||||
#include "pegasus/movie.h"
|
||||
#include "pegasus/notification.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
enum GlobeTrackDirection {
|
||||
kTrackLeft,
|
||||
kTrackRight,
|
||||
kTrackUp,
|
||||
kTrackDown
|
||||
};
|
||||
|
||||
// This class assumes that the globe movie is built at 15 frames per second with a
|
||||
// time scale of 600, yielding 40 time unit per frame.
|
||||
|
||||
class GlobeTracker : public Tracker {
|
||||
public:
|
||||
GlobeTracker(Movie *, Picture *, Picture *, Picture *, Picture *);
|
||||
~GlobeTracker() override {}
|
||||
|
||||
void setTrackParameters(const Hotspot *, GlobeTrackDirection);
|
||||
void continueTracking(const Input &) override;
|
||||
void startTracking(const Input &) override;
|
||||
void stopTracking(const Input &) override;
|
||||
void activateHotspots() override;
|
||||
bool stopTrackingInput(const Input &) override;
|
||||
|
||||
protected:
|
||||
void trackGlobeMovie();
|
||||
void stopGlobeMovie();
|
||||
|
||||
Movie *_globeMovie;
|
||||
Picture *_leftHighlight;
|
||||
Picture *_rightHighlight;
|
||||
Picture *_upHighlight;
|
||||
Picture *_downHighlight;
|
||||
const Hotspot *_trackSpot;
|
||||
int _trackTime;
|
||||
GlobeTrackDirection _trackDirection;
|
||||
};
|
||||
|
||||
class GlobeCountdown : public IdlerAnimation {
|
||||
public:
|
||||
GlobeCountdown(const DisplayElementID);
|
||||
~GlobeCountdown() override {}
|
||||
|
||||
void setCountdownTime(const int);
|
||||
void startCountdown();
|
||||
void stopCountdown();
|
||||
|
||||
void setDisplayOrder(const DisplayOrder);
|
||||
void show() override;
|
||||
void hide() override;
|
||||
void moveElementTo(const CoordType, const CoordType) override;
|
||||
|
||||
void draw(const Common::Rect &) override;
|
||||
|
||||
protected:
|
||||
Surface _digits;
|
||||
int16 _digitOffset;
|
||||
};
|
||||
|
||||
static const int16 kNumAllSilos = 40;
|
||||
static const int16 kNumTargetSilos = 10;
|
||||
static const int16 kNumLongSlices = 72;
|
||||
|
||||
class GlobeGame : public GameInteraction, public NotificationReceiver {
|
||||
public:
|
||||
GlobeGame(Neighborhood *);
|
||||
~GlobeGame() override {}
|
||||
|
||||
void setSoundFXLevel(const uint16) override;
|
||||
|
||||
void handleInput(const Input &, const Hotspot *) override;
|
||||
void clickInHotspot(const Input &, const Hotspot *) override;
|
||||
void activateHotspots() override;
|
||||
|
||||
bool canSolve() override;
|
||||
void doSolve() override;
|
||||
|
||||
struct Point3D {
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
struct Line3D {
|
||||
Point3D pt1, pt2;
|
||||
};
|
||||
|
||||
protected:
|
||||
// Latitude (-90 - 90) and longitude (-180 - 180)
|
||||
static const int16 _siloCoords[kNumAllSilos][2];
|
||||
|
||||
static const int16 _targetSilo[kNumTargetSilos];
|
||||
static const int16 _timeLimit[kNumTargetSilos];
|
||||
static const TimeValue _siloName[kNumTargetSilos][2];
|
||||
|
||||
void openInteraction() override;
|
||||
void initInteraction() override;
|
||||
void closeInteraction() override;
|
||||
|
||||
void receiveNotification(Notification *, const NotificationFlags) override;
|
||||
|
||||
void spinGlobe(const Input &, const Hotspot *, GlobeTrackDirection);
|
||||
void clickGlobe(const Input &);
|
||||
|
||||
int16 findClickedSilo(const Input &);
|
||||
|
||||
void globeMovieFrameToOrigin(int16, int16 &, int16 &);
|
||||
void globePointToLatLong(const Point3D &, int16, int16, int16 &, int16 &);
|
||||
void screenPointTo3DPoint(int16, int16, Point3D &);
|
||||
bool lineHitsGlobe(const Line3D &, Point3D &);
|
||||
|
||||
Movie _robotMovie;
|
||||
Movie _monitorMovie;
|
||||
Movie _globeMovie;
|
||||
Movie _upperNamesMovie;
|
||||
Movie _lowerNamesMovie;
|
||||
Notification _globeNotification;
|
||||
NotificationCallBack _robotCallBack;
|
||||
NotificationCallBack _monitorCallBack;
|
||||
GlobeTracker _globeTracker;
|
||||
Picture _globeCircleLeft;
|
||||
Picture _globeCircleRight;
|
||||
Picture _globeCircleUp;
|
||||
Picture _globeCircleDown;
|
||||
Picture _motionHighlightLeft;
|
||||
Picture _motionHighlightRight;
|
||||
Picture _motionHighlightUp;
|
||||
Picture _motionHighlightDown;
|
||||
Picture _targetHighlightUpperLeft;
|
||||
Picture _targetHighlightUpperRight;
|
||||
Picture _targetHighlightLowerLeft;
|
||||
Picture _targetHighlightLowerRight;
|
||||
GlobeCountdown _countdown;
|
||||
NotificationCallBack _countdownCallBack;
|
||||
int16 _gameState;
|
||||
int16 _currentSiloIndex;
|
||||
Notification *_neighborhoodNotification;
|
||||
bool _playedInstructions;
|
||||
};
|
||||
|
||||
} // End of namespace Pegasus
|
||||
|
||||
#endif
|
||||
984
engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
Normal file
984
engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
Normal file
@@ -0,0 +1,984 @@
|
||||
/* 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/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/biochips/opticalchip.h"
|
||||
#include "pegasus/items/biochips/retscanchip.h"
|
||||
#include "pegasus/items/inventory/airmask.h"
|
||||
#include "pegasus/neighborhood/norad/constants.h"
|
||||
#include "pegasus/neighborhood/norad/subcontrolroom.h"
|
||||
#include "pegasus/neighborhood/norad/delta/globegame.h"
|
||||
#include "pegasus/neighborhood/norad/delta/noraddelta.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
const uint32 NoradDelta::_noradDeltaClawExtras[22] = {
|
||||
kN60ClawFromAToB,
|
||||
kN60ClawALoop,
|
||||
kN60ClawAPinch,
|
||||
kN60ClawACounterclockwise,
|
||||
kN60ClawAClockwise,
|
||||
kN60ClawFromBToA,
|
||||
kN60ClawFromBToC,
|
||||
kN60ClawFromBToD,
|
||||
kN60ClawBLoop,
|
||||
kN60ClawBPinch,
|
||||
kN60ClawBCounterclockwise,
|
||||
kN60ClawBClockwise,
|
||||
kN60ClawFromCToB,
|
||||
kN60ClawCLoop,
|
||||
kN60ClawCPinch,
|
||||
kN60ClawCCounterclockwise,
|
||||
kN60ClawCClockwise,
|
||||
kN60ClawFromDToB,
|
||||
kN60ClawDLoop,
|
||||
kN60ClawDPinch,
|
||||
kN60ClawDCounterclockwise,
|
||||
kN60ClawDClockwise
|
||||
};
|
||||
|
||||
NoradDelta::NoradDelta(InputHandler *nextHandler, PegasusEngine *owner) : Norad(nextHandler, owner, "Norad Delta", kNoradDeltaID) {
|
||||
_elevatorUpRoomID = kNorad49South;
|
||||
_elevatorDownRoomID = kNorad48South;
|
||||
_elevatorUpSpotID = kNorad48ElevatorUpSpotID;
|
||||
_elevatorDownSpotID = kNorad49ElevatorDownSpotID;
|
||||
|
||||
// Pressure door stuff.
|
||||
|
||||
_subRoomEntryRoom1 = kNorad50;
|
||||
_subRoomEntryDir1 = kEast;
|
||||
_subRoomEntryRoom2 = kNorad59;
|
||||
_subRoomEntryDir2 = kWest;
|
||||
_upperPressureDoorRoom = kNorad50East;
|
||||
_lowerPressureDoorRoom = kNorad59West;
|
||||
|
||||
_upperPressureDoorUpSpotID = kDeltaUpperPressureDoorUpSpotID;
|
||||
_upperPressureDoorDownSpotID = kDeltaUpperPressureDoorDownSpotID;
|
||||
_upperPressureDoorAbortSpotID = kNorad50DoorOutSpotID;
|
||||
|
||||
_lowerPressureDoorUpSpotID = kDeltaLowerPressureDoorUpSpotID;
|
||||
_lowerPressureDoorDownSpotID = kDeltaLowerPressureDoorDownSpotID;
|
||||
_lowerPressureDoorAbortSpotID = kNorad59WestOutSpotID;
|
||||
|
||||
_pressureSoundIn = kPressureDoorIntro1In;
|
||||
_pressureSoundOut = kPressureDoorIntro1Out;
|
||||
_equalizeSoundIn = kPressureDoorIntro2In;
|
||||
_equalizeSoundOut = kPressureDoorIntro2Out;
|
||||
_accessDeniedIn = kDeltaAccessDeniedIn;
|
||||
_accessDeniedOut = kDeltaAccessDeniedOut;
|
||||
|
||||
GameState.setNoradSubPrepState(kSubDamaged);
|
||||
|
||||
_subControlRoom = kNorad60West;
|
||||
}
|
||||
|
||||
void NoradDelta::init() {
|
||||
Norad::init();
|
||||
|
||||
// Little fix for the retinal scan zoom in spot...
|
||||
Hotspot *hotspot = _vm->getAllHotspots().findHotspotByID(kNorad68WestSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kZoomInSpotFlag, kZoomInSpotFlag | kZoomOutSpotFlag);
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kNorad79WestSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kZoomInSpotFlag, kZoomInSpotFlag | kZoomOutSpotFlag);
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kDelta59RobotShieldBiochipSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
|
||||
HotspotInfoTable::Entry *hotspotEntry = findHotspotEntry(kDelta59RobotShieldBiochipSpotID);
|
||||
hotspotEntry->hotspotItem = kShieldBiochip;
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kDelta59RobotOpMemBiochipSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
|
||||
hotspotEntry = findHotspotEntry(kDelta59RobotOpMemBiochipSpotID);
|
||||
hotspotEntry->hotspotItem = kOpticalBiochip;
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kDelta59RobotRetinalBiochipSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
|
||||
hotspotEntry = findHotspotEntry(kDelta59RobotRetinalBiochipSpotID);
|
||||
hotspotEntry->hotspotItem = kRetinalScanBiochip;
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kDelta60RobotShieldBiochipSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
|
||||
hotspotEntry = findHotspotEntry(kDelta60RobotShieldBiochipSpotID);
|
||||
hotspotEntry->hotspotItem = kShieldBiochip;
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kDelta60RobotOpMemBiochipSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
|
||||
hotspotEntry = findHotspotEntry(kDelta60RobotOpMemBiochipSpotID);
|
||||
hotspotEntry->hotspotItem = kOpticalBiochip;
|
||||
|
||||
hotspot = _vm->getAllHotspots().findHotspotByID(kDelta60RobotRetinalBiochipSpotID);
|
||||
hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
|
||||
hotspotEntry = findHotspotEntry(kDelta60RobotRetinalBiochipSpotID);
|
||||
hotspotEntry->hotspotItem = kRetinalScanBiochip;
|
||||
}
|
||||
|
||||
void NoradDelta::start() {
|
||||
if (g_energyMonitor) {
|
||||
g_energyMonitor->stopEnergyDraining();
|
||||
g_energyMonitor->restoreLastEnergyValue();
|
||||
_vm->resetEnergyDeathReason();
|
||||
g_energyMonitor->startEnergyDraining();
|
||||
}
|
||||
|
||||
Norad::start();
|
||||
}
|
||||
|
||||
void NoradDelta::setUpAIRules() {
|
||||
Neighborhood::setUpAIRules();
|
||||
|
||||
if (g_AIArea) {
|
||||
AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/Norad/XN07NE", false);
|
||||
AILocationCondition *locCondition = new AILocationCondition(1);
|
||||
locCondition->addLocation(MakeRoomView(kNorad68, kWest));
|
||||
AIRule *rule = new AIRule(locCondition, messageAction);
|
||||
g_AIArea->addAIRule(rule);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::getExtraCompassMove(const ExtraTable::Entry &entry, FaderMoveSpec &compassMove) {
|
||||
switch (entry.extra) {
|
||||
case kArriveFromSubChase:
|
||||
compassMove.makeTwoKnotFaderSpec(kNoradDeltaMovieScale, entry.movieStart, 20, entry.movieEnd, 90);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 25 * kNoradDeltaFrameDuration, 20);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 94 * kNoradDeltaFrameDuration, 45);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 101 * kNoradDeltaFrameDuration, 45);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 146 * kNoradDeltaFrameDuration, 90 + 15);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 189 * kNoradDeltaFrameDuration, 90 + 15);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 204 * kNoradDeltaFrameDuration, 90 + 30);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 214 * kNoradDeltaFrameDuration, 90 + 20);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 222 * kNoradDeltaFrameDuration, 90 + 20);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 228 * kNoradDeltaFrameDuration, 90 + 10);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 245 * kNoradDeltaFrameDuration, 90 + 85);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 262 * kNoradDeltaFrameDuration, 90 + 70);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 273 * kNoradDeltaFrameDuration, 90 + 80);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 287 * kNoradDeltaFrameDuration, 90);
|
||||
break;
|
||||
case kN60PlayerFollowsRobotToDoor:
|
||||
compassMove.makeTwoKnotFaderSpec(kNoradDeltaMovieScale, entry.movieStart, 270 + kSubControlCompassAngle,
|
||||
entry.movieEnd, 270 - 15);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 280, 270 + kSubControlCompassAngle);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 920, 360);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 1840, 360);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 2520, 270);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 3760, 270);
|
||||
compassMove.insertFaderKnot(entry.movieStart + 4640, 270 + kSubControlCompassAngle);
|
||||
break;
|
||||
case kN59PlayerWins2:
|
||||
compassMove.makeTwoKnotFaderSpec(kNoradDeltaMovieScale, entry.movieStart, 270, entry.movieEnd, 280);
|
||||
compassMove.insertFaderKnot(entry.movieEnd - 1000, 270);
|
||||
// fall through
|
||||
// FIXME: fall through intentional?
|
||||
default:
|
||||
Norad::getExtraCompassMove(entry, compassMove);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GameInteraction *NoradDelta::makeInteraction(const InteractionID interactionID) {
|
||||
if (interactionID == kNoradGlobeGameInteractionID)
|
||||
return new GlobeGame(this);
|
||||
|
||||
return Norad::makeInteraction(interactionID);
|
||||
}
|
||||
|
||||
void NoradDelta::playClawMonitorIntro() {
|
||||
playSpotSoundSync(kLoadClawIntroIn, kLoadClawIntroOut);
|
||||
}
|
||||
|
||||
void NoradDelta::getExitEntry(const RoomID room, const DirectionConstant direction, ExitTable::Entry &entry) {
|
||||
Norad::getExitEntry(room, direction, entry);
|
||||
|
||||
if (room == kNorad61 && direction == kSouth)
|
||||
entry.movieStart += kNoradDeltaFrameDuration;
|
||||
}
|
||||
|
||||
void NoradDelta::getZoomEntry(const HotSpotID id, ZoomTable::Entry &zoomEntry) {
|
||||
Norad::getZoomEntry(id, zoomEntry);
|
||||
|
||||
if (id == kNorad59WestSpotID && GameState.getNoradPlayedGlobeGame()) {
|
||||
ExtraTable::Entry extraEntry;
|
||||
getExtraEntry(kN59ZoomWithRobot, extraEntry);
|
||||
zoomEntry.movieStart = extraEntry.movieStart;
|
||||
zoomEntry.movieEnd = extraEntry.movieEnd;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::loadAmbientLoops() {
|
||||
/*
|
||||
Logic:
|
||||
|
||||
loop sound 1:
|
||||
if room == kNorad79West
|
||||
if player globe game
|
||||
play kNoradGlobeLoop2SoundNum
|
||||
else
|
||||
play kNoradRedAlertLoopSoundNum
|
||||
else if room >= kNorad78 && room <= kNorad79
|
||||
play kNoradGlobeLoop2SoundNum
|
||||
else if gassed,
|
||||
if room >= kNorad41 && room <= kNorad49South
|
||||
play kNoradNewSubLoopSoundNum, kNoradWarningVolume
|
||||
else if room >= kNorad59 && room <= kNorad60West
|
||||
play kNoradSubControlLoopSoundNum, kNoradWarningVolume
|
||||
else
|
||||
play kNoradWarningLoopSoundNum, kNoradWarningVolume
|
||||
else
|
||||
play nothing
|
||||
loop sound 2:
|
||||
if gassed and not wearing air mask
|
||||
if room == kNorad54North
|
||||
play breathing unmanned loop
|
||||
else
|
||||
play breathing
|
||||
else
|
||||
if room == kNorad54North
|
||||
play unmanned loop
|
||||
else
|
||||
play nothing
|
||||
*/
|
||||
|
||||
if (GameState.getNoradArrivedFromSub()) {
|
||||
RoomID room = GameState.getCurrentRoom();
|
||||
|
||||
if (room >= kNorad78 && room <= kNorad79West) {
|
||||
if (GameState.getNoradPlayedGlobeGame()) {
|
||||
// blitter moved clone2727's globe room loop fix up here
|
||||
// since the original didn't play the red alert sound during the
|
||||
// globe game.
|
||||
|
||||
// clone2727 added this fix so we can play the correct sound
|
||||
// with the DVD version. This originally loaded it into slot 2,
|
||||
// which in addition to having the corrupted sound on the disk,
|
||||
// caused it to never play.
|
||||
if (_vm->isDVD())
|
||||
loadLoopSound1("Sounds/Norad/GlobAmb2.32K.AIFF");
|
||||
else
|
||||
loadLoopSound1("Sounds/Norad/GlobAmb2.22K.AIFF");
|
||||
} else
|
||||
loadLoopSound1("Sounds/Norad/RedAlert.22K.AIFF");
|
||||
} else if (GameState.getNoradGassed()) {
|
||||
if (room >= kNorad41 && room <= kNorad49South) {
|
||||
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 >= kNorad59 && room <= kNorad60West) {
|
||||
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 == kNorad54North)
|
||||
loadLoopSound2("Sounds/Norad/Breathing Typing.22K.AIFF", 0x100 / 2);
|
||||
else
|
||||
loadLoopSound2("Sounds/Norad/SUCKING WIND.22K.AIFF", kNoradSuckWindVolume, 0, 0);
|
||||
} else {
|
||||
if (room == kNorad54North) {
|
||||
if (_vm->isDVD())
|
||||
loadLoopSound2("Sounds/Norad/N54NAS.32K.AIFF", 0x100 / 2);
|
||||
else
|
||||
loadLoopSound2("Sounds/Norad/N54NAS.22K.AIFF", 0x100 / 2);
|
||||
} else
|
||||
loadLoopSound2("");
|
||||
}
|
||||
} else {
|
||||
// Start them off at zero...
|
||||
if (GameState.getNoradGassed()) {
|
||||
if (_vm->isDVD())
|
||||
loadLoopSound1("Sounds/Norad/NEW SUB AMB.44K.AIFF", 0, 0, 0);
|
||||
else
|
||||
loadLoopSound1("Sounds/Norad/NEW SUB AMB.22K.AIFF", 0, 0, 0);
|
||||
}
|
||||
if (!g_airMask->isAirFilterOn())
|
||||
loadLoopSound2("Sounds/Norad/SUCKING WIND.22K.AIFF", 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::checkContinuePoint(const RoomID room, const DirectionConstant direction) {
|
||||
switch (MakeRoomView(room, direction)) {
|
||||
case MakeRoomView(kNorad41, kEast):
|
||||
case MakeRoomView(kNorad49, kEast):
|
||||
case MakeRoomView(kNorad49, kWest):
|
||||
case MakeRoomView(kNorad61, kSouth):
|
||||
case MakeRoomView(kNorad68, kEast):
|
||||
case MakeRoomView(kNorad79, kWest):
|
||||
makeContinuePoint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::arriveAt(const RoomID room, const DirectionConstant direction) {
|
||||
if (room != kNorad68)
|
||||
GameState.setNoradRetScanGood(false);
|
||||
|
||||
Norad::arriveAt(room, direction);
|
||||
|
||||
FaderMoveSpec loop1Spec, loop2Spec;
|
||||
ExtraTable::Entry entry;
|
||||
|
||||
switch (room) {
|
||||
case kNorad41:
|
||||
if (direction == kEast) {
|
||||
if (!GameState.getNoradArrivedFromSub()) {
|
||||
GameState.setNoradPlayedGlobeGame(false);
|
||||
|
||||
GameState.setNoradBeatRobotWithClaw(false);
|
||||
GameState.setNoradBeatRobotWithDoor(false);
|
||||
GameState.setNoradRetScanGood(false);
|
||||
|
||||
GameState.setScoringExitedSub(true);
|
||||
|
||||
getExtraEntry(kArriveFromSubChase, entry);
|
||||
|
||||
loop1Spec.makeTwoKnotFaderSpec(kNoradDeltaMovieScale, 0, 0, entry.movieEnd -
|
||||
entry.movieStart, kNoradWarningVolume);
|
||||
loop1Spec.insertFaderKnot(7320, 0);
|
||||
loop1Spec.insertFaderKnot(7880, kNoradWarningVolume);
|
||||
|
||||
loop2Spec.makeTwoKnotFaderSpec(kNoradDeltaMovieScale, 0, 0, entry.movieEnd -
|
||||
entry.movieStart, kNoradSuckWindVolume);
|
||||
loop1Spec.insertFaderKnot(7320, 0);
|
||||
loop1Spec.insertFaderKnot(7880, kNoradSuckWindVolume);
|
||||
|
||||
startExtraSequence(kArriveFromSubChase, kExtraCompletedFlag, kFilterNoInput);
|
||||
|
||||
startLoop1Fader(loop1Spec);
|
||||
startLoop2Fader(loop2Spec);
|
||||
} else {
|
||||
if (g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA08", kArthurNoradExitedSub);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kNorad54:
|
||||
if (g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA71", kArthurNoradApproachedDamagedDoor);
|
||||
break;
|
||||
case kNorad54North:
|
||||
GameState.setScoringSawRobotAt54North(true);
|
||||
break;
|
||||
case kNorad68:
|
||||
if (GameState.getNoradRetScanGood())
|
||||
openDoor();
|
||||
else if (!_vm->playerHasItemID(kRetinalScanBiochip) && g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA39", kArthurNoradAtRetScanNoBiochip);
|
||||
break;
|
||||
case kNorad68West:
|
||||
arriveAtNorad68West();
|
||||
break;
|
||||
case kNorad79West:
|
||||
arriveAtNorad79West();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::doorOpened() {
|
||||
Norad::doorOpened();
|
||||
GameState.setNoradRetScanGood(false);
|
||||
}
|
||||
|
||||
void NoradDelta::arriveAtNorad68West() {
|
||||
playSpotSoundSync(kHoldForRetinalIn, kHoldForRetinalOut);
|
||||
|
||||
BiochipItem *retScan = _vm->getCurrentBiochip();
|
||||
|
||||
if (retScan != nullptr && retScan->getObjectID() == kRetinalScanBiochip) {
|
||||
((RetScanChip *)retScan)->searchForLaser();
|
||||
succeedRetinalScan();
|
||||
} else {
|
||||
failRetinalScan();
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::arriveAtNorad79West() {
|
||||
if (!GameState.getNoradPlayedGlobeGame())
|
||||
newInteraction(kNoradGlobeGameInteractionID);
|
||||
}
|
||||
|
||||
void NoradDelta::turnTo(const DirectionConstant direction) {
|
||||
Norad::turnTo(direction);
|
||||
if (g_arthurChip) {
|
||||
switch (GameState.getCurrentRoomAndView()) {
|
||||
case MakeRoomView(kNorad54, kNorth):
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA71", kArthurNoradApproachedDamagedDoor);
|
||||
break;
|
||||
case MakeRoomView(kNorad68, kWest):
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA39", kArthurNoradApproachedDamagedDoor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::bumpIntoWall() {
|
||||
requestSpotSound(kDeltaBumpIntoWallIn, kDeltaBumpIntoWallOut, kFilterNoInput, 0);
|
||||
Neighborhood::bumpIntoWall();
|
||||
}
|
||||
|
||||
void NoradDelta::failRetinalScan() {
|
||||
startExtraSequence(kNoradDeltaRetinalScanBad, kExtraCompletedFlag, kFilterNoInput);
|
||||
}
|
||||
|
||||
void NoradDelta::succeedRetinalScan() {
|
||||
startExtraSequence(kNoradDeltaRetinalScanGood, kExtraCompletedFlag, kFilterNoInput);
|
||||
GameState.setNoradRetScanGood(true);
|
||||
GameState.setScoringUsedRetinalChip(true);
|
||||
}
|
||||
|
||||
void NoradDelta::getDoorEntry(const RoomID room, const DirectionConstant direction, DoorTable::Entry &entry) {
|
||||
Norad::getDoorEntry(room, direction, entry);
|
||||
|
||||
if (room == kNorad68 && direction == kWest && !GameState.getNoradRetScanGood())
|
||||
entry.flags = kDoorPresentMask | kDoorLockedMask;
|
||||
}
|
||||
|
||||
void NoradDelta::finishedGlobeGame() {
|
||||
GameState.setNoradPlayedGlobeGame(true);
|
||||
_privateFlags.setFlag(kNoradPrivateFinishedGlobeGameFlag, true);
|
||||
GameState.setScoringFinishedGlobeGame(true);
|
||||
loadAmbientLoops();
|
||||
if (g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA63", kArthurNoradThreatenedByRobot);
|
||||
if (_vm->isChattyAI())
|
||||
g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Norad/XN60WD1", false, kWarningInterruption);
|
||||
updateViewFrame();
|
||||
}
|
||||
|
||||
bool NoradDelta::playingAgainstRobot() {
|
||||
return GameState.getNoradPlayedGlobeGame();
|
||||
}
|
||||
|
||||
void NoradDelta::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 = kNorad60MonitorOutSpotID;
|
||||
prepSpotID = kNorad60LaunchPrepSpotID;
|
||||
clawControlSpotID = kNorad60ClawControlSpotID;
|
||||
pinchClawSpotID = kNorad60ClawPinchSpotID;
|
||||
moveClawDownSpotID = kNorad60ClawDownSpotID;
|
||||
moveClawRightSpotID = kNorad60ClawRightSpotID;
|
||||
moveClawLeftSpotID = kNorad60ClawLeftSpotID;
|
||||
moveClawUpSpotID = kNorad60ClawUpSpotID;
|
||||
clawCCWSpotID = kNorad60ClawCCWSpotID;
|
||||
clawCWSpotID = kNorad60ClawCWSpotID;
|
||||
clawPosition = kClawAtC;
|
||||
clawExtraIDs = _noradDeltaClawExtras;
|
||||
}
|
||||
|
||||
void NoradDelta::playerBeatRobotWithDoor() {
|
||||
GameState.setNoradBeatRobotWithDoor(true);
|
||||
updateViewFrame();
|
||||
GameState.setScoringStoppedNoradRobot(true);
|
||||
if (_vm->isChattyAI())
|
||||
g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Norad/XN59WD", false, kWarningInterruption);
|
||||
}
|
||||
|
||||
void NoradDelta::playerBeatRobotWithClaw() {
|
||||
GameState.setNoradBeatRobotWithClaw(true);
|
||||
updateViewFrame();
|
||||
GameState.setScoringStoppedNoradRobot(true);
|
||||
GameState.setScoringNoradGandhi(true);
|
||||
if (_vm->isChattyAI())
|
||||
g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Norad/XN59WD", false, kWarningInterruption);
|
||||
}
|
||||
|
||||
TimeValue NoradDelta::getViewTime(const RoomID room, const DirectionConstant direction) {
|
||||
ExtraTable::Entry entry;
|
||||
|
||||
if (room == kNorad41 && direction == kSouth && !GameState.getNoradArrivedFromSub()) {
|
||||
getExtraEntry(kArriveFromSubChase, entry);
|
||||
return entry.movieStart;
|
||||
}
|
||||
|
||||
if (GameState.getNoradBeatRobotWithDoor()) {
|
||||
if (_privateFlags.getFlag(kNoradPrivateRobotHeadOpenFlag)) {
|
||||
uint32 extraID = kN59Biochips111;
|
||||
if (_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag))
|
||||
extraID += 1;
|
||||
if (_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag))
|
||||
extraID += 2;
|
||||
if (_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag))
|
||||
extraID += 4;
|
||||
getExtraEntry(extraID, entry);
|
||||
return entry.movieStart;
|
||||
}
|
||||
|
||||
getExtraEntry(kN59RobotHeadOpens, entry);
|
||||
return entry.movieStart;
|
||||
} else if (GameState.getNoradBeatRobotWithClaw()) {
|
||||
if (_privateFlags.getFlag(kNoradPrivateRobotHeadOpenFlag)) {
|
||||
uint32 extraID = kN60Biochips111;
|
||||
if (_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag))
|
||||
extraID += 1;
|
||||
if (_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag))
|
||||
extraID += 2;
|
||||
if (_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag))
|
||||
extraID += 4;
|
||||
getExtraEntry(extraID, entry);
|
||||
return entry.movieStart;
|
||||
}
|
||||
|
||||
getExtraEntry(kN60RobotHeadOpens, entry);
|
||||
return entry.movieStart;
|
||||
}
|
||||
|
||||
return Norad::getViewTime(room, direction);
|
||||
}
|
||||
|
||||
void NoradDelta::openDoor() {
|
||||
if (GameState.getCurrentRoom() == kNorad59 && GameState.getCurrentDirection() == kWest && GameState.getNoradPlayedGlobeGame()) {
|
||||
Input scratch;
|
||||
InputHandler::_inputHandler->clickInHotspot(scratch, _vm->getAllHotspots().findHotspotByID(kNorad59WestSpotID));
|
||||
} else {
|
||||
Norad::openDoor();
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::cantMoveThatWay(CanOpenDoorReason reason) {
|
||||
// WORKAROUND: The door outside the launch console room isn't treated as a door,
|
||||
// so play the correct sound.
|
||||
if (reason == kCantMoveBlocked && GameState.getCurrentRoomAndView() == MakeRoomView(kNorad67, kNorth)) {
|
||||
cantOpenDoor(kCantOpenLocked);
|
||||
return;
|
||||
}
|
||||
|
||||
Neighborhood::cantMoveThatWay(reason);
|
||||
}
|
||||
|
||||
void NoradDelta::activateHotspots() {
|
||||
Norad::activateHotspots();
|
||||
|
||||
if (GameState.getCurrentRoom() == kNorad59West && GameState.getCurrentDirection() == kWest && GameState.getNoradBeatRobotWithDoor()) {
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kNorad59WestOutSpotID);
|
||||
|
||||
if (_privateFlags.getFlag(kNoradPrivateRobotHeadOpenFlag)) {
|
||||
if (!_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag))
|
||||
_vm->getAllHotspots().activateOneHotspot(kDelta59RobotShieldBiochipSpotID);
|
||||
else
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kDelta59RobotShieldBiochipSpotID);
|
||||
|
||||
if (!_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag))
|
||||
_vm->getAllHotspots().activateOneHotspot(kDelta59RobotOpMemBiochipSpotID);
|
||||
else
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kDelta59RobotOpMemBiochipSpotID);
|
||||
|
||||
if (!_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag))
|
||||
_vm->getAllHotspots().activateOneHotspot(kDelta59RobotRetinalBiochipSpotID);
|
||||
else
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kDelta59RobotRetinalBiochipSpotID);
|
||||
} else
|
||||
_vm->getAllHotspots().activateOneHotspot(kDelta59RobotHeadSpotID);
|
||||
} else if (GameState.getCurrentRoom() == kNorad60West && GameState.getCurrentDirection() == kWest &&
|
||||
GameState.getNoradBeatRobotWithClaw()) {
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kNorad60MonitorOutSpotID);
|
||||
|
||||
if (_privateFlags.getFlag(kNoradPrivateRobotHeadOpenFlag)) {
|
||||
if (!_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag))
|
||||
_vm->getAllHotspots().activateOneHotspot(kDelta60RobotShieldBiochipSpotID);
|
||||
else
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kDelta60RobotShieldBiochipSpotID);
|
||||
|
||||
if (!_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag))
|
||||
_vm->getAllHotspots().activateOneHotspot(kDelta60RobotOpMemBiochipSpotID);
|
||||
else
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kDelta60RobotOpMemBiochipSpotID);
|
||||
|
||||
if (!_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag))
|
||||
_vm->getAllHotspots().activateOneHotspot(kDelta60RobotRetinalBiochipSpotID);
|
||||
else
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kDelta60RobotRetinalBiochipSpotID);
|
||||
} else {
|
||||
_vm->getAllHotspots().activateOneHotspot(kDelta60RobotHeadSpotID);
|
||||
}
|
||||
} else if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad50, kEast)) {
|
||||
if (GameState.isCurrentDoorOpen())
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kNorad50DoorSpotID);
|
||||
} else if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad59, kWest)) {
|
||||
if (GameState.isCurrentDoorOpen())
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kNorad59WestSpotID);
|
||||
} else if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad68, kWest)) {
|
||||
// WORKAROUND: Make sure the retinal hotspot is disabled after the door opens.
|
||||
// Fixes a bug in the original.
|
||||
if (GameState.isCurrentDoorOpen())
|
||||
_vm->getAllHotspots().deactivateOneHotspot(kNorad68WestSpotID);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::clickInHotspot(const Input &input, const Hotspot *clickedSpot) {
|
||||
switch (clickedSpot->getObjectID()) {
|
||||
case kDelta59RobotHeadSpotID:
|
||||
startExtraSequence(kN59RobotHeadOpens, kExtraCompletedFlag, kFilterNoInput);
|
||||
break;
|
||||
case kDelta60RobotHeadSpotID:
|
||||
startExtraSequence(kN60RobotHeadOpens, kExtraCompletedFlag, kFilterNoInput);
|
||||
break;
|
||||
default:
|
||||
Norad::clickInHotspot(input, clickedSpot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::receiveNotification(Notification *notification, const NotificationFlags flags) {
|
||||
Norad::receiveNotification(notification, flags);
|
||||
|
||||
if ((flags & kExtraCompletedFlag) != 0) {
|
||||
RetScanChip *retScan;
|
||||
Input dummy;
|
||||
|
||||
switch (_lastExtra) {
|
||||
case kArriveFromSubChase:
|
||||
GameState.setNoradArrivedFromSub(true);
|
||||
GameState.setCurrentRoom(kNoRoomID);
|
||||
GameState.setCurrentDirection(kNoDirection);
|
||||
arriveAt(kNorad41, kEast);
|
||||
break;
|
||||
case kN59RobotHeadOpens:
|
||||
case kN60RobotHeadOpens:
|
||||
_privateFlags.setFlag(kNoradPrivateRobotHeadOpenFlag, true);
|
||||
if (g_arthurChip) {
|
||||
switch (_vm->getRandomNumber(2)) {
|
||||
case 0:
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA36", kArthurNoradRobotHeadOpen);
|
||||
break;
|
||||
case 1:
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA37", kArthurNoradRobotHeadOpen);
|
||||
break;
|
||||
case 2:
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA40", kArthurNoradRobotHeadOpen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kNoradDeltaRetinalScanBad:
|
||||
retScan = (RetScanChip *)_vm->getCurrentBiochip();
|
||||
retScan->setItemState(kNormalItem);
|
||||
playSpotSoundSync(kRetinalScanFailedIn, kRetinalScanFailedOut);
|
||||
downButton(dummy);
|
||||
if (g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA13", kArthurNoradAtRetScanNoBiochip);
|
||||
break;
|
||||
case kNoradDeltaRetinalScanGood:
|
||||
retScan = (RetScanChip *)_vm->getCurrentBiochip();
|
||||
retScan->setItemState(kNormalItem);
|
||||
downButton(dummy);
|
||||
break;
|
||||
case kN59RobotDisappears:
|
||||
case kN60RobotDisappears:
|
||||
recallToTSASuccess();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_interruptionFilter = kFilterAllInput;
|
||||
} else if ((flags & kSpotSoundCompletedFlag) != 0) {
|
||||
if (_spotSounds.getStart() == kToDeactivateIn && g_arthurChip)
|
||||
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBB41", kArthurNoradStartGlobeGame);
|
||||
}
|
||||
|
||||
g_AIArea->checkMiddleArea();
|
||||
}
|
||||
|
||||
void NoradDelta::pickedUpItem(Item *item) {
|
||||
switch (item->getObjectID()) {
|
||||
case kShieldBiochip:
|
||||
if (_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag) &&
|
||||
_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag) &&
|
||||
_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag)) {
|
||||
GameState.setNoradFinished(true);
|
||||
|
||||
if (GameState.getCurrentRoom() == kNorad59West)
|
||||
startExtraSequence(kN59RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
|
||||
else
|
||||
startExtraSequence(kN60RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
|
||||
}
|
||||
break;
|
||||
case kRetinalScanBiochip:
|
||||
if (_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag) &&
|
||||
_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag) &&
|
||||
_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag)) {
|
||||
GameState.setNoradFinished(true);
|
||||
|
||||
if (GameState.getCurrentRoom() == kNorad59West)
|
||||
startExtraSequence(kN59RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
|
||||
else
|
||||
startExtraSequence(kN60RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
|
||||
}
|
||||
break;
|
||||
case kOpticalBiochip:
|
||||
g_opticalChip->addPoseidon();
|
||||
GameState.setScoringGotNoradOpMemChip();
|
||||
|
||||
if (_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag) &&
|
||||
_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag) &&
|
||||
_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag)) {
|
||||
GameState.setNoradFinished(true);
|
||||
|
||||
if (GameState.getCurrentRoom() == kNorad59West)
|
||||
startExtraSequence(kN59RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
|
||||
else
|
||||
startExtraSequence(kN60RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Norad::pickedUpItem(item);
|
||||
}
|
||||
|
||||
void NoradDelta::takeItemFromRoom(Item *item) {
|
||||
switch (item->getObjectID()) {
|
||||
case kShieldBiochip:
|
||||
_privateFlags.setFlag(kNoradPrivateGotShieldChipFlag, true);
|
||||
break;
|
||||
case kRetinalScanBiochip:
|
||||
_privateFlags.setFlag(kNoradPrivateGotRetScanChipFlag, true);
|
||||
break;
|
||||
case kOpticalBiochip:
|
||||
_privateFlags.setFlag(kNoradPrivateGotOpticalChipFlag, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Norad::takeItemFromRoom(item);
|
||||
}
|
||||
|
||||
void NoradDelta::dropItemIntoRoom(Item *item, Hotspot *hotspot) {
|
||||
switch (item->getObjectID()) {
|
||||
case kShieldBiochip:
|
||||
_privateFlags.setFlag(kNoradPrivateGotShieldChipFlag, false);
|
||||
break;
|
||||
case kOpticalBiochip:
|
||||
_privateFlags.setFlag(kNoradPrivateGotOpticalChipFlag, false);
|
||||
break;
|
||||
case kRetinalScanBiochip:
|
||||
_privateFlags.setFlag(kNoradPrivateGotRetScanChipFlag, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Norad::dropItemIntoRoom(item, hotspot);
|
||||
}
|
||||
|
||||
Hotspot *NoradDelta::getItemScreenSpot(Item *item, DisplayElement *element) {
|
||||
HotSpotID id = kNoHotSpotID;
|
||||
|
||||
switch (item->getObjectID()) {
|
||||
case kShieldBiochip:
|
||||
if (GameState.getNoradBeatRobotWithDoor())
|
||||
id = kDelta59RobotShieldBiochipSpotID;
|
||||
else
|
||||
id = kDelta60RobotShieldBiochipSpotID;
|
||||
break;
|
||||
case kOpticalBiochip:
|
||||
if (GameState.getNoradBeatRobotWithDoor())
|
||||
id = kDelta59RobotOpMemBiochipSpotID;
|
||||
else
|
||||
id = kDelta60RobotOpMemBiochipSpotID;
|
||||
break;
|
||||
case kRetinalScanBiochip:
|
||||
if (GameState.getNoradBeatRobotWithDoor())
|
||||
id = kDelta59RobotRetinalBiochipSpotID;
|
||||
else
|
||||
id = kDelta60RobotRetinalBiochipSpotID;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (id != kNoHotSpotID)
|
||||
return _vm->getAllHotspots().findHotspotByID(id);
|
||||
|
||||
return Norad::getItemScreenSpot(item, element);
|
||||
}
|
||||
|
||||
Common::Path NoradDelta::getEnvScanMovie() {
|
||||
return "Images/AI/Norad/XNE2";
|
||||
}
|
||||
|
||||
uint NoradDelta::getNumHints() {
|
||||
uint numHints = Neighborhood::getNumHints();
|
||||
|
||||
if (numHints == 0) {
|
||||
switch (GameState.getCurrentRoomAndView()) {
|
||||
case MakeRoomView(kNorad60, kWest):
|
||||
if (GameState.getNoradPlayedGlobeGame())
|
||||
numHints = 2;
|
||||
else
|
||||
numHints = 1;
|
||||
break;
|
||||
case MakeRoomView(kNorad59, kNorth):
|
||||
case MakeRoomView(kNorad59, kSouth):
|
||||
case MakeRoomView(kNorad59, kEast):
|
||||
case MakeRoomView(kNorad59, kWest):
|
||||
case MakeRoomView(kNorad60, kNorth):
|
||||
case MakeRoomView(kNorad60, kSouth):
|
||||
case MakeRoomView(kNorad60, kEast):
|
||||
if (GameState.getNoradPlayedGlobeGame())
|
||||
numHints = 2;
|
||||
break;
|
||||
case MakeRoomView(kNorad68, kWest):
|
||||
if (_vm->playerHasItemID(kRetinalScanBiochip)) {
|
||||
BiochipItem *retScan = _vm->getCurrentBiochip();
|
||||
if (retScan == nullptr || retScan->getObjectID() != kRetinalScanBiochip)
|
||||
numHints = 2;
|
||||
} else if (!GameState.isCurrentDoorOpen()) {
|
||||
numHints = 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return numHints;
|
||||
}
|
||||
|
||||
Common::Path NoradDelta::getHintMovie(uint hintNum) {
|
||||
Common::Path movieName = Neighborhood::getHintMovie(hintNum);
|
||||
|
||||
if (movieName.empty()) {
|
||||
switch (GameState.getCurrentRoomAndView()) {
|
||||
case MakeRoomView(kNorad60, kWest):
|
||||
if (GameState.getNoradPlayedGlobeGame()) {
|
||||
if (hintNum == 1)
|
||||
return "Images/AI/Norad/XN60WD2";
|
||||
|
||||
return "Images/AI/Norad/XN60WD3";
|
||||
}
|
||||
|
||||
return "Images/AI/Globals/XGLOB1C";
|
||||
case MakeRoomView(kNorad59, kNorth):
|
||||
case MakeRoomView(kNorad59, kSouth):
|
||||
case MakeRoomView(kNorad59, kEast):
|
||||
case MakeRoomView(kNorad59, kWest):
|
||||
case MakeRoomView(kNorad60, kNorth):
|
||||
case MakeRoomView(kNorad60, kSouth):
|
||||
case MakeRoomView(kNorad60, kEast):
|
||||
if (hintNum == 1)
|
||||
return "Images/AI/Norad/XN60WD2";
|
||||
|
||||
return "Images/AI/Norad/XN60WD3";
|
||||
case MakeRoomView(kNorad68, kWest):
|
||||
if (_vm->playerHasItemID(kRetinalScanBiochip)) {
|
||||
if (hintNum == 1)
|
||||
return "Images/AI/Globals/XGLOB1A";
|
||||
|
||||
return "Images/AI/Globals/XGLOB1C";
|
||||
}
|
||||
|
||||
if (hintNum == 1)
|
||||
return "Images/AI/Globals/XGLOB1B";
|
||||
|
||||
return "Images/AI/Globals/XGLOB3B";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return movieName;
|
||||
}
|
||||
|
||||
void NoradDelta::closeDoorOffScreen(const RoomID room, const DirectionConstant) {
|
||||
switch (room) {
|
||||
case kNorad47:
|
||||
case kNorad48:
|
||||
case kNorad41:
|
||||
case kNorad42:
|
||||
playSpotSoundSync(kDeltaElevatorDoorCloseIn, kDeltaElevatorDoorCloseOut);
|
||||
break;
|
||||
default:
|
||||
playSpotSoundSync(kDeltaRegDoorCloseIn, kDeltaRegDoorCloseOut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool NoradDelta::canSolve() {
|
||||
if (Norad::canSolve())
|
||||
return true;
|
||||
|
||||
if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad68, kWest)) {
|
||||
BiochipItem *biochip = _vm->getCurrentBiochip();
|
||||
if (biochip != nullptr && biochip->getObjectID() != kRetinalScanBiochip)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void NoradDelta::doSolve() {
|
||||
Norad::doSolve();
|
||||
|
||||
if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad68, kWest)) {
|
||||
if (!_vm->playerHasItemID(kRetinalScanBiochip))
|
||||
_vm->addItemToBiochips((BiochipItem *)_vm->getAllItems().findItemByID(kRetinalScanBiochip));
|
||||
|
||||
BiochipItem *biochip = _vm->getCurrentBiochip();
|
||||
if (biochip != nullptr && biochip->getObjectID() != kRetinalScanBiochip && g_interface)
|
||||
g_interface->setCurrentBiochipID(kRetinalScanBiochip);
|
||||
|
||||
Hotspot *spot = _vm->getAllHotspots().findHotspotByID(kNorad68WestSpotID);
|
||||
Input scratch;
|
||||
InputHandler::_inputHandler->clickInHotspot(scratch, spot);
|
||||
}
|
||||
}
|
||||
|
||||
void NoradDelta::setSoundFXLevel(const uint16 level) {
|
||||
Neighborhood::setSoundFXLevel(level);
|
||||
|
||||
if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad54North, kNorth))
|
||||
_loop2Fader.setMasterVolume(level);
|
||||
}
|
||||
|
||||
Common::Path NoradDelta::getSoundSpotsName() {
|
||||
return "Sounds/Norad/Norad Delta Spots";
|
||||
}
|
||||
|
||||
Common::Path NoradDelta::getNavMovieName() {
|
||||
return "Images/Norad Delta/Norad Delta.movie";
|
||||
}
|
||||
|
||||
} // End of namespace Pegasus
|
||||
120
engines/pegasus/neighborhood/norad/delta/noraddelta.h
Normal file
120
engines/pegasus/neighborhood/norad/delta/noraddelta.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/* 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_DELTA_NORADDELTA_H
|
||||
#define PEGASUS_NEIGHBORHOOD_NORAD_DELTA_NORADDELTA_H
|
||||
|
||||
#include "pegasus/neighborhood/norad/norad.h"
|
||||
|
||||
namespace Pegasus {
|
||||
|
||||
class NoradDelta : public Norad {
|
||||
public:
|
||||
NoradDelta(InputHandler *, PegasusEngine *);
|
||||
~NoradDelta() override {}
|
||||
|
||||
void init() override;
|
||||
|
||||
void start() override;
|
||||
|
||||
void getExtraCompassMove(const ExtraTable::Entry &, FaderMoveSpec &) override;
|
||||
|
||||
void finishedGlobeGame();
|
||||
|
||||
GameInteraction *makeInteraction(const InteractionID) override;
|
||||
|
||||
void playClawMonitorIntro() 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 playerBeatRobotWithClaw();
|
||||
void playerBeatRobotWithDoor();
|
||||
|
||||
void loadAmbientLoops() override;
|
||||
|
||||
void setUpAIRules() override;
|
||||
Common::Path getEnvScanMovie() override;
|
||||
uint getNumHints() override;
|
||||
Common::Path getHintMovie(uint) override;
|
||||
void closeDoorOffScreen(const RoomID, const DirectionConstant) override;
|
||||
|
||||
void checkContinuePoint(const RoomID, const DirectionConstant) override;
|
||||
|
||||
bool canSolve() override;
|
||||
void doSolve() override;
|
||||
|
||||
void setSoundFXLevel(const uint16) override;
|
||||
|
||||
void doorOpened() override;
|
||||
|
||||
protected:
|
||||
enum {
|
||||
kNoradPrivateArrivedFromSubFlag,
|
||||
kNoradPrivateFinishedGlobeGameFlag,
|
||||
kNoradPrivateRobotHeadOpenFlag,
|
||||
kNoradPrivateGotShieldChipFlag,
|
||||
kNoradPrivateGotOpticalChipFlag,
|
||||
kNoradPrivateGotRetScanChipFlag,
|
||||
kNumNoradPrivateFlags
|
||||
};
|
||||
|
||||
static const uint32 _noradDeltaClawExtras[22];
|
||||
|
||||
void getExitEntry(const RoomID, const DirectionConstant, ExitTable::Entry &) override;
|
||||
void getZoomEntry(const HotSpotID, ZoomTable::Entry &) override;
|
||||
void arriveAt(const RoomID, const DirectionConstant) override;
|
||||
void arriveAtNorad68West();
|
||||
void arriveAtNorad79West();
|
||||
void turnTo(const DirectionConstant) override;
|
||||
TimeValue getViewTime(const RoomID, const DirectionConstant) override;
|
||||
void openDoor() override;
|
||||
void cantMoveThatWay(CanMoveForwardReason) override;
|
||||
void activateHotspots() override;
|
||||
void clickInHotspot(const Input &, const Hotspot *) override;
|
||||
void receiveNotification(Notification *, const NotificationFlags) override;
|
||||
void pickedUpItem(Item *item) override;
|
||||
void takeItemFromRoom(Item *item) override;
|
||||
void dropItemIntoRoom(Item *item, Hotspot *) override;
|
||||
Hotspot *getItemScreenSpot(Item *, DisplayElement *) override;
|
||||
|
||||
bool playingAgainstRobot() override;
|
||||
|
||||
void failRetinalScan();
|
||||
void succeedRetinalScan();
|
||||
void getDoorEntry(const RoomID, const DirectionConstant, DoorTable::Entry &) override;
|
||||
|
||||
void bumpIntoWall() override;
|
||||
|
||||
FlagsArray<byte, kNumNoradPrivateFlags> _privateFlags;
|
||||
|
||||
Common::Path getSoundSpotsName() override;
|
||||
Common::Path getNavMovieName() override;
|
||||
};
|
||||
|
||||
} // End of namespace Pegasus
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user