aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorMatthew Hoops2011-09-22 20:17:09 -0400
committerMatthew Hoops2011-09-22 20:17:09 -0400
commit84731ef872ee3e704e0ed6d6ca2e88509c859d7b (patch)
tree0c92230cd6d29d31f1d8071c0e6876ed21984106 /engines
parentcde643cc17ed60840f51def25e249ff75cf456f2 (diff)
downloadscummvm-rg350-84731ef872ee3e704e0ed6d6ca2e88509c859d7b.tar.gz
scummvm-rg350-84731ef872ee3e704e0ed6d6ca2e88509c859d7b.tar.bz2
scummvm-rg350-84731ef872ee3e704e0ed6d6ca2e88509c859d7b.zip
PEGASUS: Add the EnergyMonitor class
Diffstat (limited to 'engines')
-rwxr-xr-xengines/pegasus/constants.h127
-rwxr-xr-xengines/pegasus/energymonitor.cpp291
-rwxr-xr-xengines/pegasus/energymonitor.h111
-rw-r--r--engines/pegasus/module.mk1
-rw-r--r--engines/pegasus/pegasus.cpp22
-rw-r--r--engines/pegasus/pegasus.h15
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