Skip to content

Commit

Permalink
PEGASUS: Add the base Norad code
Browse files Browse the repository at this point in the history
(Common stuff between both Norad Alpha and Norad Delta)
  • Loading branch information
Matthew Hoops committed Oct 20, 2011
1 parent 422ff6c commit d6dee9f
Show file tree
Hide file tree
Showing 14 changed files with 3,351 additions and 2 deletions.
6 changes: 6 additions & 0 deletions engines/pegasus/module.mk
Expand Up @@ -59,6 +59,12 @@ MODULE_OBJS = \
neighborhood/caldoria/caldoriamirror.o \
neighborhood/mars/reactor.o \
neighborhood/mars/mars.o \
neighborhood/norad/norad.o \
neighborhood/norad/noradelevator.o \
neighborhood/norad/pressuredoor.o \
neighborhood/norad/pressuretracker.o \
neighborhood/norad/subcontrolroom.o \
neighborhood/norad/subplatform.o \
neighborhood/prehistoric/prehistoric.o \
neighborhood/tsa/fulltsa.o \
neighborhood/tsa/tinytsa.o \
Expand Down
15 changes: 13 additions & 2 deletions engines/pegasus/movie.cpp
Expand Up @@ -57,8 +57,19 @@ void Movie::initFromMovieFile(const Common::String &fileName, bool transparent)

releaseMovie();
_video = new Video::QuickTimeDecoder();
if (!_video->loadFile(fileName))
error("Could not load video '%s'", fileName.c_str());
if (!_video->loadFile(fileName)) {
// Replace any colon with an underscore, since only Mac OS X
// supports that. See PegasusEngine::detectOpeningClosingDirectory()
// for more info.
Common::String newName(fileName);
if (newName.contains(':'))
for (uint i = 0; i < newName.size(); i++)
if (newName[i] == ':')
newName.setChar(i, '_');

if (!_video->loadFile(newName))
error("Could not load video '%s'", fileName.c_str());
}

_video->pauseVideo(true);

Expand Down
284 changes: 284 additions & 0 deletions engines/pegasus/neighborhood/norad/norad.cpp
@@ -0,0 +1,284 @@
/* 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/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/inventory/airmask.h"
#include "pegasus/neighborhood/norad/norad.h"
#include "pegasus/neighborhood/norad/noradelevator.h"
#include "pegasus/neighborhood/norad/pressuredoor.h"
#include "pegasus/neighborhood/norad/subcontrolroom.h"
#include "pegasus/neighborhood/norad/subplatform.h"

namespace Pegasus {

const tNotificationFlags kDoneWithPressureDoorNotification = 1;

const tNotificationFlags kNoradNotificationFlags = kDoneWithPressureDoorNotification;

// This class handles everything that Norad Alpha and Delta have in common, such as
// oxygen mask usage, the elevator and the pressure doors.

Norad::Norad(InputHandler *nextHandler, PegasusEngine *vm, const Common::String &resName, tNeighborhoodID id) :
Neighborhood(nextHandler, vm, resName, id), _noradNotification(kNoradNotificationID, vm) {
_elevatorUpSpotID = kNoHotSpotID;
_elevatorDownSpotID = kNoHotSpotID;
_elevatorUpRoomID = kNoHotSpotID;
_elevatorDownRoomID = kNoHotSpotID;

_subRoomEntryRoom1 = kNoRoomID;
_subRoomEntryDir1 = kNoDirection;
_subRoomEntryRoom2 = kNoRoomID;
_subRoomEntryDir2 = kNoDirection;
_upperPressureDoorRoom = kNoRoomID;
_lowerPressureDoorRoom = kNoRoomID;

_upperPressureDoorUpSpotID = kNoHotSpotID;
_upperPressureDoorDownSpotID = kNoHotSpotID;
_upperPressureDoorAbortSpotID = kNoHotSpotID;

_lowerPressureDoorUpSpotID = kNoHotSpotID;
_lowerPressureDoorDownSpotID = kNoHotSpotID;
_lowerPressureDoorAbortSpotID = kNoHotSpotID;

_pressureSoundIn = 0xffffffff;
_pressureSoundOut = 0xffffffff;
_equalizeSoundIn = 0xffffffff;
_equalizeSoundOut = 0xffffffff;
_accessDeniedIn = 0xffffffff;
_accessDeniedOut = 0xffffffff;

_platformRoom = kNoRoomID;
_subControlRoom = kNoRoomID;

_doneWithPressureDoor = false;

_noradNotification.notifyMe(this, kNoradNotificationFlags, kNoradNotificationFlags);
}

GameInteraction *Norad::makeInteraction(const tInteractionID interactionID) {
PressureDoor *pressureDoor;
SubControlRoom *subControl;

switch (interactionID) {
case kNoradElevatorInteractionID:
return new NoradElevator(this, _elevatorUpRoomID, _elevatorDownRoomID, _elevatorUpSpotID, _elevatorDownSpotID);
case kNoradPressureDoorInteractionID:
if (GameState.getCurrentRoom() == _upperPressureDoorRoom)
pressureDoor = new PressureDoor(this, true, _upperPressureDoorUpSpotID, _upperPressureDoorDownSpotID,
_upperPressureDoorAbortSpotID, _pressureSoundIn, _pressureSoundOut, _equalizeSoundIn, _equalizeSoundOut);
else
pressureDoor = new PressureDoor(this, false, _lowerPressureDoorUpSpotID, _lowerPressureDoorDownSpotID,
_lowerPressureDoorAbortSpotID, _pressureSoundIn, _pressureSoundOut, _equalizeSoundIn, _equalizeSoundOut);

if (GameState.getCurrentRoom() == kNorad59West && playingAgainstRobot())
pressureDoor->playAgainstRobot();

return pressureDoor;
case kNoradSubControlRoomInteractionID:
subControl = new SubControlRoom(this);

if (GameState.getCurrentRoom() == kNorad60West && playingAgainstRobot())
subControl->playAgainstRobot();

return subControl;
case kNoradSubPlatformInteractionID:
return new SubPlatform(this);
default:
return 0;
}
}

void Norad::flushGameState() {
g_energyMonitor->saveCurrentEnergyValue();
}

void Norad::start() {
setUpAirMask();
Neighborhood::start();
}

void Norad::activateHotspots() {
Neighborhood::activateHotspots();

tRoomID room = GameState.getCurrentRoom();
if (room == _elevatorUpRoomID)
_neighborhoodHotspots.activateOneHotspot(_elevatorDownSpotID);
else if (room == _elevatorDownRoomID)
_neighborhoodHotspots.activateOneHotspot(_elevatorUpSpotID);
}

void Norad::arriveAt(const tRoomID room, const tDirectionConstant direction) {
Neighborhood::arriveAt(room, direction);

if (GameState.getCurrentRoom() == _elevatorUpRoomID || GameState.getCurrentRoom() == _elevatorDownRoomID)
arriveAtNoradElevator();
else if (GameState.getCurrentRoom() == _upperPressureDoorRoom)
arriveAtUpperPressureDoorRoom();
else if (GameState.getCurrentRoom() == _lowerPressureDoorRoom)
arriveAtLowerPressureDoorRoom();
else if (GameState.getCurrentRoom() == _platformRoom)
arriveAtSubPlatformRoom();
else if (GameState.getCurrentRoom() == _subControlRoom)
arriveAtSubControlRoom();

if (_doneWithPressureDoor) {
_doneWithPressureDoor = false;
openDoor();
}
}

void Norad::arriveAtNoradElevator() {
if (_currentInteraction)
_currentInteraction->startOverInteraction();
else
newInteraction(kNoradElevatorInteractionID);
}

void Norad::arriveAtUpperPressureDoorRoom() {
newInteraction(kNoradPressureDoorInteractionID);
}

void Norad::arriveAtLowerPressureDoorRoom() {
newInteraction(kNoradPressureDoorInteractionID);
}

void Norad::arriveAtSubPlatformRoom() {
newInteraction(kNoradSubPlatformInteractionID);
}

void Norad::arriveAtSubControlRoom() {
newInteraction(kNoradSubControlRoomInteractionID);
}

int16 Norad::getStaticCompassAngle(const tRoomID room, const tDirectionConstant dir) {
int16 result = Neighborhood::getStaticCompassAngle(room, dir);

if (room == _elevatorUpRoomID || room == _elevatorDownRoomID)
result += kElevatorCompassAngle;
else if (room == _platformRoom)
result += kSubPlatformCompassAngle;
else if (room == _subControlRoom)
result += kSubControlCompassAngle;

return result;
}

tCanOpenDoorReason Norad::canOpenDoor(DoorTable::Entry &entry) {
if (((GameState.getCurrentRoom() == _subRoomEntryRoom1 && GameState.getCurrentDirection() == _subRoomEntryDir1) ||
(GameState.getCurrentRoom() == _subRoomEntryRoom2 && GameState.getCurrentDirection() == _subRoomEntryDir2)) &&
GameState.getNoradSubRoomPressure() != kNormalSubRoomPressure)
return kCantOpenBadPressure;

return Neighborhood::canOpenDoor(entry);
}

void Norad::cantOpenDoor(tCanOpenDoorReason reason) {
if (reason == kCantOpenBadPressure)
playSpotSoundSync(_pressureSoundIn, _pressureSoundOut);
else
playSpotSoundSync(_accessDeniedIn, _accessDeniedOut);
}

void Norad::startExitMovie(const ExitTable::Entry &exitEntry) {
if (GameState.getCurrentRoom() == _elevatorUpRoomID) {
if (exitEntry.exitRoom != _elevatorDownRoomID)
newInteraction(kNoInteractionID);
} else if (GameState.getCurrentRoom() == _elevatorDownRoomID) {
if (exitEntry.exitRoom != _elevatorUpRoomID)
newInteraction(kNoInteractionID);
} else {
newInteraction(kNoInteractionID);
}

Neighborhood::startExitMovie(exitEntry);
}

void Norad::startZoomMovie(const ZoomTable::Entry &zoomEntry) {
newInteraction(kNoInteractionID);
Neighborhood::startZoomMovie(zoomEntry);
}

void Norad::upButton(const Input &input) {
if (GameState.getCurrentRoom() != _elevatorUpRoomID && GameState.getCurrentRoom() != _elevatorDownRoomID)
Neighborhood::upButton(input);
}

void Norad::setUpAirMask() {
_airMaskCallBack.setNotification(&_neighborhoodNotification);
_airMaskCallBack.initCallBack(&_airMaskTimer, kCallBackAtExtremes);
_airMaskCallBack.setCallBackFlag(kAirTimerExpiredFlag);
_neighborhoodNotification.notifyMe(this, kAirTimerExpiredFlag, kAirTimerExpiredFlag);
_airMaskCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
_airMaskTimer.setScale(1);
_airMaskTimer.setSegment(0, kNoradAirMaskTimeLimit);
checkAirMask();
}

void Norad::checkAirMask() {
if (g_airMask && g_airMask->isAirFilterOn()) {
_airMaskTimer.stop();
} else if (GameState.getNoradGassed() && !_airMaskTimer.isRunning()) {
_airMaskTimer.setTime(0);
_airMaskTimer.start();
}

loadAmbientLoops();
}

void Norad::receiveNotification(Notification *notification, const tNotificationFlags flags) {
if (notification == &_neighborhoodNotification && (flags & kAirTimerExpiredFlag) != 0)
((PegasusEngine *)g_engine)->die(kDeathGassedInNorad);

Neighborhood::receiveNotification(notification, flags);

if (notification == &_noradNotification) {
// Must be kDoneWithPressureDoorNotification...
Input scratch;
_doneWithPressureDoor = true;
downButton(scratch);
}
}

uint16 Norad::getDateResID() const {
return kDate2112ID;
}

Common::String Norad::getBriefingMovie() {
return "Images/AI/Norad/XNO";
}

void Norad::pickedUpItem(Item *item) {
Neighborhood::pickedUpItem(item);
g_AIArea->checkMiddleArea();
}

void Norad::doneWithPressureDoor() {
_noradNotification.setNotificationFlags(kDoneWithPressureDoorNotification, kDoneWithPressureDoorNotification);
}

} // End of namespace Pegasus

0 comments on commit d6dee9f

Please sign in to comment.