/* 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #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/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); 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 == kNorad79West) { if (_privateFlags.getFlag(kNoradPrivateFinishedGlobeGameFlag)) loadLoopSound1("Sounds/Norad/GlobAmb2.22K.AIFF"); else loadLoopSound1("Sounds/Norad/RedAlert.22K.AIFF"); } else if (room >= kNorad78 && room <= kNorad79) { // clone2727 says: This looks like it should be loadLoopSound1... loadLoopSound2("Sounds/Norad/RedAlert.22K.AIFF"); } else if (GameState.getNoradGassed()) { if (room >= kNorad41 && room <= kNorad49South) loadLoopSound1("Sounds/Norad/NEW SUB AMB.22K.AIFF", kNoradWarningVolume * 3); else if (room >= kNorad59 && room <= kNorad60West) loadLoopSound1("Sounds/Norad/SUB CONTRL LOOP.22K.AIFF", kNoradWarningVolume * 3); 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) loadLoopSound2("Sounds/Norad/N54NAS.22K.AIFF", 0x100 / 2); else loadLoopSound2(""); } } else { // Start them off at zero... if (GameState.getNoradGassed()) 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; } } 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 && !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); } break; case kNorad54North: GameState.setScoringSawRobotAt54North(true); break; case kNorad68: if (GameState.getNoradRetScanGood()) openDoor(); 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 != 0 && retScan->getObjectID() == kRetinalScanBiochip) { ((RetScanChip *)retScan)->searchForLaser(); succeedRetinalScan(); } else { failRetinalScan(); } } void NoradDelta::arriveAtNorad79West() { if (!GameState.getNoradPlayedGlobeGame()) newInteraction(kNoradGlobeGameInteractionID); } 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(); g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Norad/XN60WD1", false, kWarningInterruption); } 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); g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Norad/XN59WD", false, kWarningInterruption); } void NoradDelta::playerBeatRobotWithClaw() { GameState.setNoradBeatRobotWithClaw(true); updateViewFrame(); GameState.setScoringStoppedNoradRobot(true); GameState.setScoringNoradGandhi(true); 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::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); break; case kNoradDeltaRetinalScanBad: retScan = (RetScanChip *)_vm->getCurrentBiochip(); retScan->setItemState(kNormalItem); playSpotSoundSync(kRetinalScanFailedIn, kRetinalScanFailedOut); downButton(dummy); break; case kNoradDeltaRetinalScanGood: retScan = (RetScanChip *)_vm->getCurrentBiochip(); retScan->setItemState(kNormalItem); downButton(dummy); break; case kN59RobotDisappears: case kN60RobotDisappears: recallToTSASuccess(); break; } _interruptionFilter = kFilterAllInput; } 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; } 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; } 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; } 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; } if (id != kNoHotSpotID) return _vm->getAllHotspots().findHotspotByID(id); return Norad::getItemScreenSpot(item, element); } Common::String 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 == 0 || retScan->getObjectID() != kRetinalScanBiochip) numHints = 2; } else if (!GameState.isCurrentDoorOpen()) { numHints = 2; } break; } } return numHints; } Common::String NoradDelta::getHintMovie(uint hintNum) { Common::String 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"; } } 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 != 0 && 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 != 0 && biochip->getObjectID() != kRetinalScanBiochip && g_interface) g_interface->setCurrentBiochipID(kRetinalScanBiochip); Hotspot *spot = _vm->getAllHotspots().findHotspotByID(kNorad68WestSpotID); Input scratch; InputHandler::_inputHandler->clickInHotspot(scratch, spot); } } Common::String NoradDelta::getSoundSpotsName() { return "Sounds/Norad/Norad Delta Spots"; } Common::String NoradDelta::getNavMovieName() { return "Images/Norad Delta/Norad Delta.movie"; } } // End of namespace Pegasus