aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Hoops2011-10-23 22:50:54 -0400
committerMatthew Hoops2011-10-23 22:50:54 -0400
commitb3059e75e2597671abe501e62e73138f0825976b (patch)
tree5983816c402991c667c3438c6387c9af18b6b839
parent841f96868aed34a0edc02c4b32d66849cd9f350c (diff)
downloadscummvm-rg350-b3059e75e2597671abe501e62e73138f0825976b.tar.gz
scummvm-rg350-b3059e75e2597671abe501e62e73138f0825976b.tar.bz2
scummvm-rg350-b3059e75e2597671abe501e62e73138f0825976b.zip
PEGASUS: Add the space junk stuff
-rw-r--r--engines/pegasus/module.mk1
-rwxr-xr-xengines/pegasus/neighborhood/mars/mars.cpp131
-rwxr-xr-xengines/pegasus/neighborhood/mars/mars.h7
-rwxr-xr-xengines/pegasus/neighborhood/mars/spacejunk.cpp213
-rwxr-xr-xengines/pegasus/neighborhood/mars/spacejunk.h76
5 files changed, 424 insertions, 4 deletions
diff --git a/engines/pegasus/module.mk b/engines/pegasus/module.mk
index 904bc1fe25..aca065ad97 100644
--- a/engines/pegasus/module.mk
+++ b/engines/pegasus/module.mk
@@ -63,6 +63,7 @@ MODULE_OBJS = \
neighborhood/mars/reactor.o \
neighborhood/mars/shuttleenergymeter.o \
neighborhood/mars/spacechase3d.o \
+ neighborhood/mars/spacejunk.o \
neighborhood/norad/norad.o \
neighborhood/norad/noradelevator.o \
neighborhood/norad/pressuredoor.o \
diff --git a/engines/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp
index 7404e1e580..b5564bb88a 100755
--- a/engines/pegasus/neighborhood/mars/mars.cpp
+++ b/engines/pegasus/neighborhood/mars/mars.cpp
@@ -778,7 +778,7 @@ Mars::Mars(InputHandler *nextHandler, PegasusEngine *owner) : Neighborhood(nextH
_leftShuttleMovie(kNoDisplayElement), _rightShuttleMovie(kNoDisplayElement), _lowerLeftShuttleMovie(kNoDisplayElement),
_lowerRightShuttleMovie(kNoDisplayElement), _centerShuttleMovie(kNoDisplayElement),
_upperLeftShuttleMovie(kNoDisplayElement), _upperRightShuttleMovie(kNoDisplayElement),
- _leftDamageShuttleMovie(kNoDisplayElement), _rightDamageShuttleMovie(kNoDisplayElement) {
+ _leftDamageShuttleMovie(kNoDisplayElement), _rightDamageShuttleMovie(kNoDisplayElement), _explosions(kNoDisplayElement) {
_noAirFuse.setFunctionPtr(&airStageExpiredFunction, this);
setIsItemTaken(kMarsCard);
setIsItemTaken(kAirMask);
@@ -2991,6 +2991,8 @@ void Mars::receiveNotification(Notification *notification, const tNotificationFl
} else if ((flag & kTimeForCanyonChaseFlag) != 0) {
doCanyonChase();
} else if ((flag & kExplosionFinishedFlag) != 0) {
+ _explosions.stop();
+ _explosions.hide();
// TODO
} else if ((flag & kTimeToTransportFlag) != 0) {
// TODO
@@ -3170,7 +3172,8 @@ void Mars::setSoundFXLevel(const uint16 level) {
if (_canyonChaseMovie.isMovieValid())
_canyonChaseMovie.setVolume(level);
- // TODO: Explosions
+ if (_explosions.isMovieValid())
+ _explosions.setVolume(level);
}
void Mars::startMarsTimer(TimeValue time, TimeScale scale, MarsTimerCode code) {
@@ -3181,7 +3184,10 @@ void Mars::startMarsTimer(TimeValue time, TimeScale scale, MarsTimerCode code) {
_utilityFuse.lightFuse();
}
-void Mars::marsTimerExpired(MarsTimerEvent &event) {
+void Mars::marsTimerExpired(MarsTimerEvent &event) {
+ Common::Rect r;
+ uint16 x, y;
+
switch (event.event) {
case kMarsLaunchTubeReached:
_lowerLeftShuttleMovie.setTime(kShuttleLowerLeftTubeTime);
@@ -3205,7 +3211,38 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) {
break;
case kMarsSpaceChaseFinished:
// Player failed to stop the robot in time...
- // TODO
+ _interruptionFilter = kFilterNoInput;
+
+ _rightShuttleMovie.setTime(kShuttleRightTargetLockTime);
+ _rightShuttleMovie.redrawMovieWorld();
+
+ _upperRightShuttleMovie.show();
+ _upperRightShuttleMovie.setTime(kShuttleUpperRightLockedTime);
+ _upperRightShuttleMovie.redrawMovieWorld();
+
+ _rightShuttleMovie.setTime(kShuttleRightGravitonTime);
+ _rightShuttleMovie.redrawMovieWorld();
+ _upperRightShuttleMovie.setTime(kShuttleUpperRightArmedTime);
+ _upperRightShuttleMovie.redrawMovieWorld();
+
+ _vm->delayShell(3, 1);
+
+ x = _vm->getRandomNumber(19);
+ y = _vm->getRandomNumber(19);
+
+ r = Common::Rect(kShuttleWindowMidH - x, kShuttleWindowMidV - y,
+ kShuttleWindowMidH - x + 20, kShuttleWindowMidV - y + 20);
+ showBigExplosion(r, kShuttleAlienShipOrder);
+
+ while (_explosions.isRunning()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ throwAwayMarsShuttle();
+ reinstateMonocleInterface();
+ recallToTSAFailure();
break;
default:
break;
@@ -3214,6 +3251,92 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) {
_interruptionFilter = kFilterAllInput;
}
+void Mars::throwAwayMarsShuttle() {
+ _shuttleInterface1.deallocateSurface();
+ _shuttleInterface1.stopDisplaying();
+ _shuttleInterface2.deallocateSurface();
+ _shuttleInterface2.stopDisplaying();
+ _shuttleInterface3.deallocateSurface();
+ _shuttleInterface3.stopDisplaying();
+ _shuttleInterface4.deallocateSurface();
+ _shuttleInterface4.stopDisplaying();
+
+ _spotSounds.disposeSound();
+
+ _canyonChaseMovie.releaseMovie();
+ _canyonChaseMovie.stopDisplaying();
+ _leftShuttleMovie.releaseMovie();
+ _leftShuttleMovie.stopDisplaying();
+ _rightShuttleMovie.releaseMovie();
+ _rightShuttleMovie.stopDisplaying();
+ _lowerLeftShuttleMovie.releaseMovie();
+ _lowerLeftShuttleMovie.stopDisplaying();
+ _lowerRightShuttleMovie.releaseMovie();
+ _lowerRightShuttleMovie.stopDisplaying();
+ _centerShuttleMovie.releaseMovie();
+ _centerShuttleMovie.stopDisplaying();
+ _upperLeftShuttleMovie.releaseMovie();
+ _upperLeftShuttleMovie.stopDisplaying();
+ _upperRightShuttleMovie.releaseMovie();
+ _upperRightShuttleMovie.stopDisplaying();
+ _leftDamageShuttleMovie.releaseMovie();
+ _leftDamageShuttleMovie.stopDisplaying();
+ _rightDamageShuttleMovie.releaseMovie();
+ _rightDamageShuttleMovie.stopDisplaying();
+
+ // TODO: Some more to do here
+
+ _explosions.releaseMovie();
+ _explosions.stopDisplaying();
+
+ loadLoopSound1("");
+}
+
+void Mars::showBigExplosion(const Common::Rect &r, const tDisplayOrder order) {
+ if (_explosions.isMovieValid()) {
+ _explosions.setDisplayOrder(order);
+
+ Common::Rect r2 = r;
+ int dx = r.width() / 2;
+ int dy = r.height() / 2;
+ r2.left -= dx;
+ r2.right += dx;
+ r2.top -= dy;
+ r2.bottom += dy;
+
+ _explosions.setBounds(r2);
+ _explosions.show();
+ _explosions.stop();
+ _explosions.setSegment(kBigExplosionStart, kBigExplosionStop);
+ _explosions.setTime(kBigExplosionStart);
+ _explosionCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _explosions.start();
+ }
+}
+
+void Mars::hitByJunk() {
+ _leftDamageShuttleMovie.setTime(_leftDamageShuttleMovie.getTime() - 40);
+ playSpotSoundSync(kMarsJunkCollisionIn, kMarsJunkCollisionOut);
+
+ if (_leftDamageShuttleMovie.getTime() == 0) {
+ die(kDeathRanIntoSpaceJunk);
+ } else {
+ TimeValue t = _leftDamageShuttleMovie.getTime() / 40;
+
+ if (t == 1)
+ playSpotSoundSync(kShuttleHullBreachIn, kShuttleHullBreachOut);
+
+ t = _leftShuttleMovie.getTime();
+ _leftShuttleMovie.setTime(kShuttleLeftDamagedTime);
+ _vm->delayShell(1, 3);
+ _leftShuttleMovie.setTime(t);
+ }
+}
+
+void Mars::setUpNextDropTime() {
+ // TODO
+}
+
tAirQuality Mars::getAirQuality(const tRoomID room) {
if ((room >= kMars36 && room <= kMars39) || (room >= kMarsMaze004 && room <= kMarsMaze200))
return kAirQualityVacuum;
diff --git a/engines/pegasus/neighborhood/mars/mars.h b/engines/pegasus/neighborhood/mars/mars.h
index 1b29cdfc1e..f2d7b336e9 100755
--- a/engines/pegasus/neighborhood/mars/mars.h
+++ b/engines/pegasus/neighborhood/mars/mars.h
@@ -312,6 +312,10 @@ public:
void checkAirMask();
+ void showBigExplosion(const Common::Rect &, const tDisplayOrder);
+ void hitByJunk();
+ void setUpNextDropTime();
+
Common::String getBriefingMovie();
Common::String getEnvScanMovie();
uint getNumHints();
@@ -406,6 +410,7 @@ protected:
void doCanyonChase(void);
void startMarsTimer(TimeValue, TimeScale, MarsTimerCode);
void marsTimerExpired(MarsTimerEvent &);
+ void throwAwayMarsShuttle();
// TODO: Space chase functions
@@ -442,6 +447,8 @@ protected:
Movie _leftDamageShuttleMovie;
Movie _rightDamageShuttleMovie;
ShuttleEnergyMeter _shuttleEnergyMeter;
+ ScalingMovie _explosions;
+ NotificationCallBack _explosionCallBack;
// TODO: Space chase variables
};
diff --git a/engines/pegasus/neighborhood/mars/spacejunk.cpp b/engines/pegasus/neighborhood/mars/spacejunk.cpp
new file mode 100755
index 0000000000..8c78db4050
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/spacejunk.cpp
@@ -0,0 +1,213 @@
+/* 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/pegasus.h"
+#include "pegasus/neighborhood/mars/spacejunk.h"
+
+namespace Pegasus {
+
+//const TimeValue kWeaponReboundTime = kTwoSeconds * kJunkTimeScale;
+//const TimeValue kCollisionReboundTime = kOneSecond * kJunkTimeScale;
+const tCoordType kMaxBounceSize = 90;
+const tCoordType kBounceTargetHRange = 640 - kMaxBounceSize - 2;
+const tCoordType kBounceTargetVRange = 480 - kMaxBounceSize - 2;
+
+const float kJunkXTarget = 0;
+const float kJunkYTarget = 0;
+const float kJunkZTarget = kJunkMinDistance;
+
+SpaceJunk *g_spaceJunk = 0;
+
+SpaceJunk::SpaceJunk(const tDisplayElementID id) : ScalingMovie(id) {
+ _timer.setScale(kJunkTimeScale);
+ _bouncing = false;
+ g_spaceJunk = this;
+}
+
+SpaceJunk::~SpaceJunk() {
+ g_spaceJunk = 0;
+}
+
+void SpaceJunk::launchJunk(int16 whichJunk, tCoordType xOrigin, tCoordType yOrigin) {
+ _bouncing = false;
+ TimeValue startTime = whichJunk * 16 * 40;
+ TimeValue stopTime = startTime + 16 * 40;
+
+ _launchPoint = Point3D(convertScreenHToSpaceX(xOrigin, kJunkMaxDistance),
+ convertScreenVToSpaceY(yOrigin, kJunkMaxDistance), kJunkMaxDistance);
+ startIdling();
+ stop();
+ setFlags(0);
+ setSegment(startTime, stopTime);
+ setFlags(kLoopTimeBase);
+ setTime(startTime);
+ start();
+ show();
+ _timer.stop();
+ _timer.setSegment(0, kJunkTravelTime);
+ _timer.setTime(0);
+
+ // Force it to set up correctly from the get-go
+ useIdleTime();
+
+ _timer.start();
+}
+
+void SpaceJunk::setCenter(const tCoordType centerX, const tCoordType centerY) {
+ _center.x = centerX;
+ _center.y = centerY;
+
+ Common::Rect r;
+ getBounds(r);
+ r.moveTo(centerX - (r.width() >> 1), centerY - (r.height() >> 1));
+ setBounds(r);
+}
+
+void SpaceJunk::setScaleSize(const tCoordType size) {
+ Common::Rect r;
+ r.left = _center.x - (size >> 1);
+ r.top = _center.y - (size >> 1);
+ r.right = r.left + size;
+ r.bottom = r.top + size;
+ setBounds(r);
+}
+
+void SpaceJunk::useIdleTime() {
+ if (_bouncing) {
+ TimeValue time = _timer.getTime();
+ Common::Point pt;
+ pt.x = linearInterp(0, _bounceTime, time, _bounceStart.x, _bounceStop.x);
+ pt.y = linearInterp(0, _bounceTime, time, _bounceStart.y, _bounceStop.y);
+ tCoordType size = linearInterp(0, _bounceTime, time, _bounceSizeStart, _bounceSizeStop);
+ setCenter(pt.x, pt.y);
+ setScaleSize(size);
+
+ if (time == _bounceTime) {
+ stop();
+ stopIdling();
+ hide();
+ ((Mars *)g_neighborhood)->setUpNextDropTime();
+ }
+ } else {
+ float t = (float)_timer.getTime() / kJunkTravelTime;
+ linearInterp(_launchPoint, kJunkXTarget, kJunkYTarget, kJunkZTarget, t, _junkPosition);
+
+ Common::Point pt2D;
+ project3DTo2D(_junkPosition, pt2D);
+ setCenter(pt2D.x, pt2D.y);
+ setScaleSize((int)(convertSpaceYToScreenV(_junkPosition.y - kJunkSize / 2, _junkPosition.z) -
+ convertSpaceYToScreenV(_junkPosition.y + kJunkSize / 2, _junkPosition.z)));
+
+ if (t == 1.0) {
+ rebound(kCollisionReboundTime);
+ ((Mars *)g_neighborhood)->hitByJunk();
+ }
+ }
+}
+
+bool SpaceJunk::pointInJunk(const Common::Point &pt) {
+ Common::Rect r;
+ getBounds(r);
+
+ int dx = r.width() / 4;
+ int dy = r.height() / 4;
+
+ r.left += dx;
+ r.right -= dx;
+ r.top += dy;
+ r.top -= dy;
+
+ return r.contains(pt);
+}
+
+void SpaceJunk::rebound(const TimeValue reboundTime) {
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ _bounceStart.x = (bounds.left + bounds.right) >> 1;
+ _bounceStart.y = (bounds.top + bounds.bottom) >> 1;
+
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ switch (vm->getRandomNumber(3)) {
+ case 0:
+ _bounceStop.x = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetHRange - 1);
+ _bounceStop.y = kMaxBounceSize / 2 + 1;
+ break;
+ case 1:
+ _bounceStop.x = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetHRange - 1);
+ _bounceStop.y = 480 - kMaxBounceSize / 2 + 1;
+ break;
+ case 2:
+ _bounceStop.x = kMaxBounceSize / 2 + 1;
+ _bounceStop.y = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetVRange - 1);
+ break;
+ case 3:
+ _bounceStop.x = 640 - kMaxBounceSize / 2 + 1;
+ _bounceStop.y = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetVRange - 1);
+ break;
+ }
+
+ _bounceSizeStart = bounds.width();
+ _bounceSizeStop = MIN(_bounceSizeStart, kMaxBounceSize);
+
+ _timer.stop();
+ _timer.setSegment(0, reboundTime);
+ _bounceTime = reboundTime;
+ _timer.setTime(0);
+ _timer.start();
+
+ _bouncing = true;
+}
+
+void SpaceJunk::hitByEnergyBeam(Common::Point) {
+ rebound(kWeaponReboundTime);
+ setGlowing(true);
+ ((PegasusEngine *)g_engine)->delayShell(1, 3);
+ setGlowing(false);
+}
+
+void SpaceJunk::hitByGravitonCannon(Common::Point impactPoint) {
+ stop();
+ stopIdling();
+ hide();
+
+ Common::Rect r;
+ getBounds(r);
+ r = Common::Rect::center(impactPoint.x, impactPoint.y, r.width(), r.height());
+
+ ((Mars *)g_neighborhood)->showBigExplosion(r, kShuttleJunkOrder);
+ ((Mars *)g_neighborhood)->setUpNextDropTime();
+}
+
+void SpaceJunk::getJunkPosition(Point3D &position) {
+ position = _junkPosition;
+}
+
+bool SpaceJunk::isJunkFlying() {
+ return isIdling();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/spacejunk.h b/engines/pegasus/neighborhood/mars/spacejunk.h
new file mode 100755
index 0000000000..d3315b0bd0
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/spacejunk.h
@@ -0,0 +1,76 @@
+/* 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_NEIGHBORHOOD_MARS_SPACEJUNK_H
+#define PEGASUS_NEIGHBORHOOD_MARS_SPACEJUNK_H
+
+#include "pegasus/neighborhood/mars/spacechase3d.h"
+
+namespace Pegasus {
+
+const tCoordType kJunkMaxScreenSize = 250;
+
+const float kJunkSize = convertScreenVToSpaceY(kShuttleWindowMidV - kJunkMaxScreenSize / 2, kJunkMinDistance) -
+ convertScreenVToSpaceY(kShuttleWindowMidV + kJunkMaxScreenSize / 2, kJunkMinDistance);
+
+class SpaceJunk : public ScalingMovie, public Idler {
+public:
+ SpaceJunk(const tDisplayElementID);
+ virtual ~SpaceJunk();
+
+ void setCenter(const tCoordType, const tCoordType);
+ void setScaleSize(const tCoordType);
+
+ void useIdleTime();
+
+ void launchJunk(int16, tCoordType, tCoordType);
+
+ void getJunkPosition(Point3D &);
+ bool isJunkFlying();
+
+ bool pointInJunk(const Common::Point &);
+
+ void hitByEnergyBeam(Common::Point impactPoint);
+ void hitByGravitonCannon(Common::Point impactPoint);
+
+ bool junkFlying() { return _timer.isRunning(); }
+
+protected:
+ void rebound(const TimeValue);
+
+ TimeBase _timer;
+ Point3D _launchPoint, _junkPosition;
+ Common::Point _center;
+ bool _bouncing;
+ Common::Point _bounceStart, _bounceStop;
+ tCoordType _bounceSizeStart, _bounceSizeStop;
+ TimeValue _bounceTime;
+};
+
+extern SpaceJunk *g_spaceJunk;
+
+} // End of namespace Pegasus
+
+#endif