aboutsummaryrefslogtreecommitdiff
path: root/engines/pegasus/energymonitor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/pegasus/energymonitor.cpp')
-rw-r--r--engines/pegasus/energymonitor.cpp296
1 files changed, 296 insertions, 0 deletions
diff --git a/engines/pegasus/energymonitor.cpp b/engines/pegasus/energymonitor.cpp
new file mode 100644
index 0000000000..8aa77eb341
--- /dev/null
+++ b/engines/pegasus/energymonitor.cpp
@@ -0,0 +1,296 @@
+/* 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/pegasus.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 NotificationFlags 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()) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+ if (vm->getEnergyDeathReason() != -1)
+ vm->die(vm->getEnergyDeathReason());
+ } else {
+ uint32 currentEnergy = kMaxJMPEnergy - currentTime;
+
+ EnergyStage 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;
+
+ vm->setEnergyDeathReason(-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(-(int32)kMaxJMPEnergy / 2);
+
+ // Make sure warning light is hidden...
+ _energyLight.hide();
+ while (getCurrentEnergy() != (int32)kMaxJMPEnergy) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ 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