diff options
author | Matthew Hoops | 2011-09-22 20:17:09 -0400 |
---|---|---|
committer | Matthew Hoops | 2011-09-22 20:17:09 -0400 |
commit | 84731ef872ee3e704e0ed6d6ca2e88509c859d7b (patch) | |
tree | 0c92230cd6d29d31f1d8071c0e6876ed21984106 /engines/pegasus | |
parent | cde643cc17ed60840f51def25e249ff75cf456f2 (diff) | |
download | scummvm-rg350-84731ef872ee3e704e0ed6d6ca2e88509c859d7b.tar.gz scummvm-rg350-84731ef872ee3e704e0ed6d6ca2e88509c859d7b.tar.bz2 scummvm-rg350-84731ef872ee3e704e0ed6d6ca2e88509c859d7b.zip |
PEGASUS: Add the EnergyMonitor class
Diffstat (limited to 'engines/pegasus')
-rwxr-xr-x | engines/pegasus/constants.h | 127 | ||||
-rwxr-xr-x | engines/pegasus/energymonitor.cpp | 291 | ||||
-rwxr-xr-x | engines/pegasus/energymonitor.h | 111 | ||||
-rw-r--r-- | engines/pegasus/module.mk | 1 | ||||
-rw-r--r-- | engines/pegasus/pegasus.cpp | 22 | ||||
-rw-r--r-- | engines/pegasus/pegasus.h | 15 |
6 files changed, 559 insertions, 8 deletions
diff --git a/engines/pegasus/constants.h b/engines/pegasus/constants.h index 8d2a95bcd2..519e97e9ec 100755 --- a/engines/pegasus/constants.h +++ b/engines/pegasus/constants.h @@ -556,6 +556,133 @@ const tGameMenuCommand kMenuCmdEjectRestart = kMenuCmdCancelRestart + 1; const TimeValue kMenuButtonHiliteTime = 20; const TimeScale kMenuButtonHiliteScale = kSixtyTicksPerSecond; +// PICT resources: + +// Warning light PICTs: + +const tResIDType kLightOffID = 128; +const tResIDType kLightYellowID = 129; +const tResIDType kLightOrangeID = 130; +const tResIDType kLightRedID = 131; + +// Date PICTs: + +const tResIDType kDatePrehistoricID = 138; +const tResIDType kDate2112ID = 139; +const tResIDType kDate2185ID = 140; +const tResIDType kDate2310ID = 141; +const tResIDType kDate2318ID = 142; + +///////////////////////////////////////////// +// +// Display Order + +const tDisplayOrder kCroppedMovieLayer = 11000; + +const tDisplayOrder kMonitorLayer = 12000; + +const tDisplayOrder kDragSpriteLayer = 15000; +const tDisplayOrder kDragSpriteOrder = kDragSpriteLayer; + +const tDisplayOrder kInterfaceLayer = 20000; +const tDisplayOrder kBackground1Order = kInterfaceLayer; +const tDisplayOrder kBackground2Order = kBackground1Order + 1; +const tDisplayOrder kBackground3Order = kBackground2Order + 1; +const tDisplayOrder kBackground4Order = kBackground3Order + 1; +const tDisplayOrder kDateOrder = kBackground4Order + 1; +const tDisplayOrder kCompassOrder = kDateOrder + 1; +const tDisplayOrder kEnergyBarOrder = kCompassOrder + 1; +const tDisplayOrder kEnergyLightOrder = kEnergyBarOrder + 1; + +const tDisplayOrder kAILayer = 22000; +const tDisplayOrder kAILeftAreaOrder = kAILayer; +const tDisplayOrder kAIMiddleAreaOrder = kAILeftAreaOrder + 1; +const tDisplayOrder kAIRightAreaOrder = kAIMiddleAreaOrder + 1; +const tDisplayOrder kAIMovieOrder = kAIRightAreaOrder + 1; + +const tDisplayOrder kHilitesLayer = 23000; +const tDisplayOrder kInventoryHiliteOrder = kHilitesLayer; +const tDisplayOrder kBiochipHiliteOrder = kInventoryHiliteOrder + 1; + +const tDisplayOrder kPanelsLayer = 25000; +const tDisplayOrder kInventoryPushOrder = kPanelsLayer; +const tDisplayOrder kInventoryLidOrder = kInventoryPushOrder + 1; +const tDisplayOrder kBiochipPushOrder = kInventoryLidOrder + 1; +const tDisplayOrder kBiochipLidOrder = kBiochipPushOrder + 1; +const tDisplayOrder kFinalMessageOrder = kBiochipLidOrder + 1; + +const tDisplayOrder kInfoLayer = 26000; +const tDisplayOrder kInfoBackgroundOrder = kInfoLayer; +const tDisplayOrder kInfoSpinOrder = kInfoBackgroundOrder + 1; + +const tDisplayOrder kScreenDimmerOrder = 30000; + +const tDisplayOrder kPauseScreenLayer = 31000; +const tDisplayOrder kPauseMenuOrder = kPauseScreenLayer; +const tDisplayOrder kSaveGameOrder = kPauseMenuOrder + 1; +const tDisplayOrder kContinueOrder = kSaveGameOrder + 1; +const tDisplayOrder kRestoreOrder = kContinueOrder + 1; +const tDisplayOrder kSoundFXOrder = kRestoreOrder + 1; +const tDisplayOrder kAmbienceOrder = kSoundFXOrder + 1; +const tDisplayOrder kWalkthruOrder = kAmbienceOrder + 1; +const tDisplayOrder kQuitToMainMenuOrder = kWalkthruOrder + 1; +const tDisplayOrder kPauseLargeHiliteOrder = kQuitToMainMenuOrder + 1; +const tDisplayOrder kPauseSmallHiliteOrder = kPauseLargeHiliteOrder + 1; + +///////////////////////////////////////////// +// +// Death reasons. +enum { + // Caldoria + kDeathUncreatedInCaldoria = 1, + kDeathCardBomb, + kDeathShotBySinclair, + kDeathSinclairShotDelegate, + kDeathNuclearExplosion, + + // TSA + kDeathUncreatedInTSA, + kDeathShotByTSARobots, + + // Prehistoric + kDeathFallOffCliff, + kDeathEatenByDinosaur, + kDeathStranded, + + // Norad + kDeathGassedInNorad, + kDeathArrestedInNorad, + kDeathWokeUpNorad, + kDeathSubDestroyed, // Unused + kDeathRobotThroughNoradDoor, + kDeathRobotSubControlRoom, + + // Mars + kDeathWrongShuttleLock, + kDeathArrestedInMars, + kDeathRunOverByPod, + kDeathDidntGetOutOfWay, + kDeathReactorBurn, + kDeathDidntFindMarsBomb, + kDeathDidntDisarmMarsBomb, + kDeathNoMaskInMaze, + kDeathNoAirInMaze, + kDeathGroundByMazebot, + kDeathMissedOreBucket, + kDeathDidntLeaveBucket, + kDeathRanIntoCanyonWall, // Unused + kDeathRanIntoSpaceJunk, + + // WSC + kDeathDidntStopPoison, + kDeathArrestedInWSC, + kDeathHitByPlasma, + kDeathShotOnCatwalk, + + // Winning + kPlayerWonGame +}; + } // End of namespace Pegasus #endif diff --git a/engines/pegasus/energymonitor.cpp b/engines/pegasus/energymonitor.cpp new file mode 100755 index 0000000000..fc22a32416 --- /dev/null +++ b/engines/pegasus/energymonitor.cpp @@ -0,0 +1,291 @@ +/* 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/surface.h" + +namespace Pegasus { + +Blinker::Blinker() { + _sprite = 0; + _frame1 = -1; + _frame2 = -1; + _blinkDuration = 0; +} + +void Blinker::startBlinking(Sprite *sprite, int32 frame1, int32 frame2, uint32 numBlinks, TimeValue blinkDuration, TimeScale blinkScale) { + stopBlinking(); + _sprite = sprite; + _frame1 = frame1; + _frame2 = frame2; + _blinkDuration = blinkDuration; + setScale(blinkScale); + setSegment(0, blinkDuration * numBlinks * 2, blinkScale); + setTime(0); + start(); +} + +void Blinker::stopBlinking() { + if (_sprite) { + _sprite->setCurrentFrameIndex(_frame2); + _sprite = 0; + stop(); + } +} + +void Blinker::timeChanged(const TimeValue time) { + if (_sprite && _blinkDuration != 0) { + if (((time / _blinkDuration) & 1) != 0 || time == getDuration()) { + _sprite->setCurrentFrameIndex(_frame2); + if (!isRunning()) + stopBlinking(); + } else { + _sprite->setCurrentFrameIndex(_frame1); + } + } +} + +static const tNotificationFlags kEnergyExpiredFlag = 1; + +EnergyMonitor *g_energyMonitor = 0; + +EnergyMonitor::EnergyMonitor() : IdlerAnimation(kEnergyBarID), _energyLight(kWarningLightID) { + PegasusEngine *vm = (PegasusEngine *)g_engine; + + _stage = kStageNoStage; + + _calibrating = false; + _dontFlash = false; + + setBounds(338, 48, 434, 54); + + setDisplayOrder(kEnergyBarOrder); + startDisplaying(); + + SpriteFrame *frame = new SpriteFrame(); + frame->initFromPICTResource(vm->_resFork, kLightOffID); + _energyLight.addFrame(frame, 0, 0); + + frame = new SpriteFrame(); + frame->initFromPICTResource(vm->_resFork, kLightYellowID); + _energyLight.addFrame(frame, 0, 0); + + frame = new SpriteFrame(); + frame->initFromPICTResource(vm->_resFork, kLightOrangeID); + _energyLight.addFrame(frame, 0, 0); + + frame = new SpriteFrame(); + frame->initFromPICTResource(vm->_resFork, kLightRedID); + _energyLight.addFrame(frame, 0, 0); + + _energyLight.setBounds(540, 35, 600, 59); + _energyLight.setDisplayOrder(kEnergyLightOrder); + _energyLight.startDisplaying(); + + setScale(1); + setSegment(0, kMaxJMPEnergy); + + setEnergyValue(kCasualEnergy); + + g_energyMonitor = this; +} + +EnergyMonitor::~EnergyMonitor() { + g_energyMonitor = 0; +} + +void EnergyMonitor::setEnergyValue(const uint32 value) { + if (isRunning()) { + stop(); + setTime(getStop() - value); + start(); + } else { + setTime(getStop() - value); + } +} + +void EnergyMonitor::startEnergyDraining() { + if (!isRunning()) { + _energyLight.show(); + start(); + show(); + } +} + +void EnergyMonitor::setEnergyDrainRate(Common::Rational rate) { + setRate(rate); +} + +Common::Rational EnergyMonitor::getEnergyDrainRate() { + return getRate(); +} + +void EnergyMonitor::stopEnergyDraining() { + if (isRunning()) { + stop(); + _energyLight.hide(); + hide(); + } +} + +void EnergyMonitor::drainEnergy(const int32 delta) { + setTime(getTime() + delta); +} + +int32 EnergyMonitor::getCurrentEnergy() { + return kMaxJMPEnergy - getTime(); +} + +void EnergyMonitor::timeChanged(const TimeValue currentTime) { + if (currentTime == getStop()) { + // TODO: Die :P + if (((PegasusEngine *)g_engine)->getEnergyDeathReason() != -1) + error("You're dead"); + } else { + uint32 currentEnergy = kMaxJMPEnergy - currentTime; + + tEnergyStage newStage; + if (currentEnergy > kWorriedEnergy) + newStage = kStageCasual; + else if (currentEnergy > kNervousEnergy) + newStage = kStageWorried; + else if (currentEnergy > kPanicStrickenEnergy) + newStage = kStageNervous; + else + newStage = kStagePanicStricken; + + if (_stage != newStage) { + uint32 newFrame; + + switch (newStage) { + case kStageCasual: + _barColor = g_system->getScreenFormat().RGBToColor(0x48, 0xB0, 0xD8); + newFrame = kFrameLightOff; + break; + case kStageWorried: + _barColor = g_system->getScreenFormat().RGBToColor(0xD8, 0xC0, 0x30); + newFrame = kFrameLightYellow; + break; + case kStageNervous: + _barColor = g_system->getScreenFormat().RGBToColor(0xD8, 0x78, 0x38); + newFrame = kFrameLightOrange; + break; + case kStagePanicStricken: + _barColor = g_system->getScreenFormat().RGBToColor(0xD8, 0x40, 0x38); + newFrame = kFrameLightRed; + break; + default: + error("no stage in energy monitor?"); + break; + } + + _stage = newStage; + uint32 oldFrame = _energyLight.getCurrentFrameIndex(); + + if (!_calibrating) { + if (oldFrame > newFrame || oldFrame == 0xffffffff || _dontFlash) { + _energyLight.setCurrentFrameIndex(newFrame); + _dontFlash = false; + } else { + _lightBlinker.startBlinking(&_energyLight, oldFrame, newFrame, 4, 1, 3); + triggerRedraw(); + } + } + } + + Common::Rect r; + calcLevelRect(r); + if (r != _levelRect) { + _levelRect = r; + triggerRedraw(); + } + } +} + +void EnergyMonitor::calcLevelRect(Common::Rect &r) { + if (getStop() == 0) { + r = Common::Rect(); + } else { + getBounds(r); + r.left = r.right - r.width() * (kMaxJMPEnergy - getTime()) / getStop(); + } +} + +void EnergyMonitor::draw(const Common::Rect &r) { + Common::Rect r2 = r.findIntersectingRect(_levelRect); + + if (!r2.isEmpty()) { + Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getWorkArea(); + screen->fillRect(r2, _barColor); + } +} + +void EnergyMonitor::calibrateEnergyBar() { + PegasusEngine *vm = (PegasusEngine *)g_engine; + + _calibrating = true; + + // TODO: set death reason to -1 + + uint32 numFrames = _energyLight.getNumFrames(); + for (uint32 i = 1; i < numFrames; i++) { + _energyLight.setCurrentFrameIndex(i); + _energyLight.show(); + vm->delayShell(1, 3); + _energyLight.hide(); + vm->delayShell(1, 3); + } + + _energyLight.setCurrentFrameIndex(0); + _energyLight.hide(); + show(); + setEnergyValue(0); + setEnergyDrainRate(-kMaxJMPEnergy / 2); + + // Make sure warning light is hidden... + _energyLight.hide(); + while (getCurrentEnergy() != (int32)kMaxJMPEnergy) + vm->refreshDisplay(); + + vm->refreshDisplay(); + setEnergyDrainRate(0); + hide(); + + _calibrating = false; +} + +void EnergyMonitor::restoreLastEnergyValue() { + PegasusEngine *vm = (PegasusEngine *)g_engine; + + _dontFlash = true; + setEnergyValue(vm->getSavedEnergyValue()); + vm->resetEnergyDeathReason(); +} + +void EnergyMonitor::saveCurrentEnergyValue() { + ((PegasusEngine *)g_engine)->setLastEnergyValue(getCurrentEnergy()); +} + +} // End of namespace Pegasus diff --git a/engines/pegasus/energymonitor.h b/engines/pegasus/energymonitor.h new file mode 100755 index 0000000000..cb5d4498fc --- /dev/null +++ b/engines/pegasus/energymonitor.h @@ -0,0 +1,111 @@ +/* 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. + * + */ + +#ifndef PEGASUS_ENERGYMONITOR_H +#define PEGASUS_ENERGYMONITOR_H + +#include "pegasus/elements.h" + +namespace Pegasus { + +class Sprite; + +class Blinker : private IdlerTimeBase { +public: + Blinker(); + virtual ~Blinker() {} + + void startBlinking(Sprite *sprite, int32 frame1, int32 frame2, uint32 numBlinks, TimeValue blinkDuration, TimeScale blinkScale); + void stopBlinking(); + +protected: + virtual void timeChanged(const TimeValue); + + Sprite *_sprite; + int32 _frame1; + int32 _frame2; + TimeValue _blinkDuration; +}; + +// Energy monitor constants. + +// These are in seconds. +// Max is two hours +static const uint32 kMaxJMPEnergy = 7200; + +static const uint32 kCasualEnergy = kMaxJMPEnergy * 100 / 100; // 100% +static const uint32 kWorriedEnergy = kMaxJMPEnergy * 50 / 100; // 50% +static const uint32 kNervousEnergy = kMaxJMPEnergy * 25 / 100; // 25% +static const uint32 kPanicStrickenEnergy = kMaxJMPEnergy * 5 / 100; // 5% + +static const uint32 kFullEnergy = kCasualEnergy; + +static const uint32 kFrameLightOff = 0; +static const uint32 kFrameLightYellow = 1; +static const uint32 kFrameLightOrange = 2; +static const uint32 kFrameLightRed = 3; + +static const int kEnergyDrainNormal = 1; +static const int kMarsReactorEnergyDrainNoShield = 6; +static const int kMarsReactorEnergyDrainWithShield = 3; +static const int kWSCPoisonEnergyDrainWithDart = 20; +static const int kWSCPoisonEnergyDrainNoDart = 10; + +class EnergyMonitor : private IdlerAnimation { +public: + EnergyMonitor(); + virtual ~EnergyMonitor(); + + void setEnergyValue(const uint32); + void startEnergyDraining(); + void setEnergyDrainRate(Common::Rational); + Common::Rational getEnergyDrainRate(); + void stopEnergyDraining(); + void drainEnergy(const int32); + int32 getCurrentEnergy(); + + void restoreLastEnergyValue(); + void saveCurrentEnergyValue(); + + void calibrateEnergyBar(); + +protected: + void timeChanged(const TimeValue); + void calcLevelRect(Common::Rect &); + void draw(const Common::Rect &); + + uint32 _barColor; + Common::Rect _levelRect; + tEnergyStage _stage; + Sprite _energyLight; + Blinker _lightBlinker; + bool _calibrating, _dontFlash; +}; + +extern EnergyMonitor *g_energyMonitor; + +} // End of namespace Pegasus + +#endif diff --git a/engines/pegasus/module.mk b/engines/pegasus/module.mk index cc0b3ec7cc..2909a22b68 100644 --- a/engines/pegasus/module.mk +++ b/engines/pegasus/module.mk @@ -5,6 +5,7 @@ MODULE_OBJS = \ cursor.o \ detection.o \ elements.o \ + energymonitor.o \ fader.o \ gamestate.o \ graphics.o \ diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp index 368dc298fb..816d01cf55 100644 --- a/engines/pegasus/pegasus.cpp +++ b/engines/pegasus/pegasus.cpp @@ -51,6 +51,7 @@ PegasusEngine::PegasusEngine(OSystem *syst, const PegasusGameDescription *gamede _continuePoint = 0; _saveAllowed = _loadAllowed = true; _gameMenu = 0; + _deathReason = kDeathStranded; } PegasusEngine::~PegasusEngine() { @@ -359,11 +360,11 @@ bool PegasusEngine::loadFromStream(Common::ReadStream *stream) { // Game State GameState.readGameState(stream); - // TODO: Energy - stream->readUint32BE(); + // Energy + setLastEnergyValue(stream->readUint32BE() >> 16); - // TODO: Death reason - stream->readByte(); + // Death reason + setEnergyDeathReason(stream->readByte()); // TODO: This is as far as we can go right now return true; @@ -403,11 +404,11 @@ bool PegasusEngine::writeToStream(Common::WriteStream *stream, int saveType) { // Game State GameState.writeGameState(stream); - // TODO: Energy - stream->writeUint32BE(0); + // Energy + stream->writeUint32BE(getSavedEnergyValue() << 16); - // TODO: Death reason - stream->writeByte(0); + // Death reason + stream->writeByte(getEnergyDeathReason()); // Items g_allItems.writeToStream(stream); @@ -823,4 +824,9 @@ void PegasusEngine::refreshDisplay() { _gfx->updateDisplay(); } +void PegasusEngine::resetEnergyDeathReason() { + // TODO! + _deathReason = kDeathStranded; +} + } // End of namespace Pegasus diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h index 73a95c9a10..2990811e60 100644 --- a/engines/pegasus/pegasus.h +++ b/engines/pegasus/pegasus.h @@ -90,6 +90,15 @@ public: void resetIntroTimer(); void refreshDisplay(); + // Energy + void setLastEnergyValue(const int32 value) { _savedEnergyValue = value; } + int32 getSavedEnergyValue() { return _savedEnergyValue; } + + // Death + void setEnergyDeathReason(const tDeathReason reason) { _deathReason = reason; } + tDeathReason getEnergyDeathReason() { return _deathReason; } + void resetEnergyDeathReason(); + protected: Common::Error run(); @@ -140,6 +149,12 @@ private: GameMenu *_gameMenu; void doGameMenuCommand(const tGameMenuCommand); void doInterfaceOverview(); + + // Energy + int32 _savedEnergyValue; + + // Death + tDeathReason _deathReason; }; } // End of namespace Pegasus |