aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/pegasus/module.mk1
-rwxr-xr-xengines/pegasus/movie.h2
-rwxr-xr-xengines/pegasus/neighborhood/mars/mars.cpp73
-rwxr-xr-xengines/pegasus/neighborhood/mars/mars.h4
-rwxr-xr-xengines/pegasus/neighborhood/mars/robotship.cpp269
-rwxr-xr-xengines/pegasus/neighborhood/mars/robotship.h86
-rwxr-xr-xengines/pegasus/neighborhood/mars/spacechase3d.cpp16
7 files changed, 447 insertions, 4 deletions
diff --git a/engines/pegasus/module.mk b/engines/pegasus/module.mk
index aca065ad97..034ccaa9d5 100644
--- a/engines/pegasus/module.mk
+++ b/engines/pegasus/module.mk
@@ -61,6 +61,7 @@ MODULE_OBJS = \
neighborhood/mars/mars.o \
neighborhood/mars/planetmover.o \
neighborhood/mars/reactor.o \
+ neighborhood/mars/robotship.o \
neighborhood/mars/shuttleenergymeter.o \
neighborhood/mars/spacechase3d.o \
neighborhood/mars/spacejunk.o \
diff --git a/engines/pegasus/movie.h b/engines/pegasus/movie.h
index b248cc19d4..db7b640ba8 100755
--- a/engines/pegasus/movie.h
+++ b/engines/pegasus/movie.h
@@ -84,7 +84,7 @@ public:
void setBounds(const Common::Rect &);
- void setGlowing(const bool);
+ void setGlowing(const bool glowing) { _glowing = glowing; }
protected:
bool _glowing;
diff --git a/engines/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp
index b5564bb88a..b6b9211554 100755
--- a/engines/pegasus/neighborhood/mars/mars.cpp
+++ b/engines/pegasus/neighborhood/mars/mars.cpp
@@ -2993,7 +2993,19 @@ void Mars::receiveNotification(Notification *notification, const tNotificationFl
} else if ((flag & kExplosionFinishedFlag) != 0) {
_explosions.stop();
_explosions.hide();
- // TODO
+ if (g_robotShip->isDead()) {
+ GameState.setMarsFinished(true);
+ _centerShuttleMovie.hide();
+ _upperRightShuttleMovie.show();
+ _upperRightShuttleMovie.setTime(kShuttleUpperRightTargetDestroyedTime);
+ _upperRightShuttleMovie.redrawMovieWorld();
+ _rightDamageShuttleMovie.hide();
+ playMovieSegment(&_rightShuttleMovie, kShuttleRightDestroyedStart, kShuttleRightDestroyedStop);
+ playSpotSoundSync(kShuttleDestroyedIn, kShuttleDestroyedOut);
+ throwAwayMarsShuttle();
+ reinstateMonocleInterface();
+ recallToTSASuccess();
+ }
} else if ((flag & kTimeToTransportFlag) != 0) {
// TODO
}
@@ -3285,7 +3297,8 @@ void Mars::throwAwayMarsShuttle() {
_rightDamageShuttleMovie.stopDisplaying();
// TODO: Some more to do here
-
+ _shuttleEnergyMeter.disposeShuttleEnergyMeter();
+ _robotShip.cleanUpRobotShip();
_explosions.releaseMovie();
_explosions.stopDisplaying();
@@ -3314,6 +3327,28 @@ void Mars::showBigExplosion(const Common::Rect &r, const tDisplayOrder order) {
}
}
+void Mars::showLittleExplosion(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(kLittleExplosionStart, kLittleExplosionStop);
+ _explosions.setTime(kLittleExplosionStart);
+ _explosionCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _explosions.start();
+ }
+}
+
void Mars::hitByJunk() {
_leftDamageShuttleMovie.setTime(_leftDamageShuttleMovie.getTime() - 40);
playSpotSoundSync(kMarsJunkCollisionIn, kMarsJunkCollisionOut);
@@ -3334,7 +3369,39 @@ void Mars::hitByJunk() {
}
void Mars::setUpNextDropTime() {
- // TODO
+ _robotShip.setUpNextDropTime();
+}
+
+void Mars::decreaseRobotShuttleEnergy(const int delta, Common::Point impactPoint) {
+ _rightDamageShuttleMovie.setTime(_rightDamageShuttleMovie.getTime() - 40 * delta);
+ _rightDamageShuttleMovie.redrawMovieWorld();
+
+ if (_rightDamageShuttleMovie.getTime() == 0) {
+ Common::Rect r;
+ _robotShip.getShuttleBounds(r);
+ int size = MAX(r.width(), r.height());
+ r = Common::Rect::center(impactPoint.x, impactPoint.y, size, size);
+ _robotShip.killRobotShip();
+ showBigExplosion(r, kShuttleRobotShipOrder);
+ } else if (delta > 1) {
+ Common::Rect r;
+ _robotShip.getShuttleBounds(r);
+ int size = MIN(r.width(), r.height());
+ r = Common::Rect::center(impactPoint.x, impactPoint.y, size, size);
+ showLittleExplosion(r, kShuttleWeaponBackOrder);
+ TimeValue t = _rightShuttleMovie.getTime();
+ _rightShuttleMovie.setTime(kShuttleRightDamagedTime);
+ _rightShuttleMovie.redrawMovieWorld();
+ _vm->delayShell(1, 3);
+ _rightShuttleMovie.setTime(t);
+ _rightShuttleMovie.redrawMovieWorld();
+ }
+
+ if (_rightDamageShuttleMovie.getTime() <= 40) {
+ GameState.setScoringStoppedRobotsShuttle();
+ if (!GameState.getMarsHitRobotWithCannon())
+ GameState.setScoringMarsGandhi();
+ }
}
tAirQuality Mars::getAirQuality(const tRoomID room) {
diff --git a/engines/pegasus/neighborhood/mars/mars.h b/engines/pegasus/neighborhood/mars/mars.h
index f2d7b336e9..8e199d1bc1 100755
--- a/engines/pegasus/neighborhood/mars/mars.h
+++ b/engines/pegasus/neighborhood/mars/mars.h
@@ -28,6 +28,7 @@
#include "pegasus/neighborhood/neighborhood.h"
#include "pegasus/neighborhood/mars/reactor.h"
+#include "pegasus/neighborhood/mars/robotship.h"
#include "pegasus/neighborhood/mars/shuttleenergymeter.h"
namespace Pegasus {
@@ -313,7 +314,9 @@ public:
void checkAirMask();
void showBigExplosion(const Common::Rect &, const tDisplayOrder);
+ void showLittleExplosion(const Common::Rect &, const tDisplayOrder);
void hitByJunk();
+ void decreaseRobotShuttleEnergy(const int, Common::Point impactPoint);
void setUpNextDropTime();
Common::String getBriefingMovie();
@@ -447,6 +450,7 @@ protected:
Movie _leftDamageShuttleMovie;
Movie _rightDamageShuttleMovie;
ShuttleEnergyMeter _shuttleEnergyMeter;
+ RobotShip _robotShip;
ScalingMovie _explosions;
NotificationCallBack _explosionCallBack;
diff --git a/engines/pegasus/neighborhood/mars/robotship.cpp b/engines/pegasus/neighborhood/mars/robotship.cpp
new file mode 100755
index 0000000000..279bdd8365
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/robotship.cpp
@@ -0,0 +1,269 @@
+/* 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/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/mars/hermite.h"
+#include "pegasus/neighborhood/mars/mars.h"
+#include "pegasus/neighborhood/mars/robotship.h"
+#include "pegasus/neighborhood/mars/spacechase3d.h"
+#include "pegasus/neighborhood/mars/spacejunk.h"
+
+namespace Pegasus {
+
+const TimeScale kRovingScale = kTractorBeamScale;
+const TimeValue kRovingTime = kSixSeconds * kRovingScale;
+const TimeValue kRovingSlop = kThreeSeconds * kRovingScale;
+
+const int kNumSpriteColumns = 15;
+const int kNumSpriteRows = 16;
+
+const tCoordType kInitialLocationLeft = kShuttleWindowLeft - 50;
+const tCoordType kInitialLocationTop = kShuttleWindowTop - 50;
+const tCoordType kInitialLocationWidth = kShuttleWindowWidth + 100;
+const tCoordType kInitialLocationHeight = kShuttleWindowHeight + 100;
+
+const tCoordType kVelocityVectorLength = 100;
+const tCoordType kVelocityVectorSlop = 50;
+
+const tCoordType kRovingLeft = kShuttleWindowLeft + 20;
+const tCoordType kRovingTop = kShuttleWindowTop + 20;
+const tCoordType kRovingWidth = kShuttleWindowMidH - kRovingLeft;
+const tCoordType kRovingHeight = kShuttleWindowMidV - kRovingTop;
+
+RobotShip* g_robotShip = 0;
+
+void timeToDropJunkFunction(FunctionPtr *, void *robotShip) {
+ ((RobotShip *)robotShip)->timeToDropJunk();
+}
+
+RobotShip::RobotShip() : _spritesMovie(kNoDisplayElement) {
+ g_robotShip = this;
+ _shipRange = Common::Rect(kShuttleWindowLeft, kShuttleWindowTop, kShuttleWindowLeft + kShuttleWindowWidth,
+ kShuttleWindowTop + kShuttleWindowHeight);
+ setScale(kRovingScale);
+ _currentLocation.x = 0;
+ _currentLocation.y = 0;
+ _snaring = false;
+ _dropJunkFuse.setFunctionPtr(&timeToDropJunkFunction, (void *)this);
+}
+
+RobotShip::~RobotShip() {
+ g_robotShip = 0;
+}
+
+void RobotShip::initRobotShip() {
+ _spritesMovie.initFromMovieFile("Images/Mars/Ship.movie", true);
+ _spritesMovie.setDisplayOrder(kShuttleRobotShipOrder);
+ _spritesMovie.moveElementTo(kPlanetStartLeft, kPlanetStartTop);
+ _spritesMovie.startDisplaying();
+ _spritesMovie.show();
+
+ Common::Rect r;
+ _spritesMovie.getBounds(r);
+ _shipWidth = r.width();
+ _shipHeight = r.height();
+ _dead = false;
+}
+
+void RobotShip::cleanUpRobotShip() {
+ _dropJunkFuse.stopFuse();
+ _spritesMovie.stopDisplaying();
+ _spritesMovie.releaseMovie();
+}
+
+void RobotShip::startMoving() {
+ if (((PegasusEngine *)g_engine)->getRandomBit()) {
+ _p4.x = kInitialLocationLeft + ((PegasusEngine *)g_engine)->getRandomNumber(kInitialLocationWidth - 1);
+ if (((PegasusEngine *)g_engine)->getRandomBit())
+ _p4.y = kInitialLocationTop;
+ else
+ _p4.y = kInitialLocationTop + kInitialLocationHeight;
+ } else {
+ _p4.y = kInitialLocationTop + ((PegasusEngine *)g_engine)->getRandomNumber(kInitialLocationHeight - 1);
+ if (((PegasusEngine *)g_engine)->getRandomBit())
+ _p4.x = kInitialLocationLeft;
+ else
+ _p4.x = kInitialLocationLeft + kInitialLocationWidth;
+ }
+
+ makeVelocityVector(_p4.x, _p4.y, kShuttleWindowLeft + kShuttleWindowWidth / 2,
+ kShuttleWindowTop + kShuttleWindowHeight / 2, _r4);
+ newDestination();
+ setUpNextDropTime();
+}
+
+void RobotShip::killRobotShip() {
+ cleanUpRobotShip();
+ _dead = true;
+}
+
+void RobotShip::setUpNextDropTime() {
+ if (!isSnared()) {
+ _dropJunkFuse.primeFuse(kJunkDropBaseTime + ((PegasusEngine *)g_engine)->getRandomNumber(kJunkDropSlopTime));
+ _dropJunkFuse.lightFuse();
+ }
+}
+
+void RobotShip::timeToDropJunk() {
+ if (g_spaceJunk) {
+ tCoordType x, y;
+ _spritesMovie.getCenter(x, y);
+ g_spaceJunk->launchJunk(((PegasusEngine *)g_engine)->getRandomNumber(24), x, y);
+ }
+}
+
+void RobotShip::newDestination() {
+ _p1 = _p4;
+ _r1 = _r4;
+
+ _p4.x = kRovingLeft + ((PegasusEngine *)g_engine)->getRandomNumber(kRovingWidth - 1);
+ _p4.y = kRovingTop + ((PegasusEngine *)g_engine)->getRandomNumber(kRovingHeight - 1);
+
+ if (((PegasusEngine *)g_engine)->getRandomNumber(7) < 6) {
+ if (!sameSign(_p4.x - kShuttleWindowMidH, kShuttleWindowMidH - _p1.x)) {
+ if (sign(_p4.x - kShuttleWindowMidH) > 0)
+ _p4.x -= kRovingWidth;
+ else
+ _p4.x += kRovingWidth;
+ }
+ }
+
+ if (((PegasusEngine *)g_engine)->getRandomNumber(7) < 6) {
+ if (!sameSign(_p4.y - kShuttleWindowMidV, kShuttleWindowMidV - _p1.y)) {
+ if (sign(_p4.y - kShuttleWindowMidV) > 0)
+ _p4.y -= kRovingHeight;
+ else
+ _p4.y += kRovingHeight;
+ }
+ }
+
+ makeVelocityVector(_p4.x, _p4.y, kShuttleWindowLeft + kShuttleWindowWidth / 2,
+ kShuttleWindowTop + kShuttleWindowHeight / 2, _r4);
+ stop();
+ _duration = kRovingTime + ((PegasusEngine *)g_engine)->getRandomNumber(kRovingSlop - 1);
+ setSegment(0, _duration);
+ setTime(0);
+ start();
+}
+
+void RobotShip::moveRobotTo(tCoordType x, tCoordType y) {
+ _currentLocation.x = x;
+ _currentLocation.y = y;
+
+ if (_spritesMovie.isMovieValid()) {
+ _spritesMovie.moveElementTo(x - (_shipWidth >> 1), y - (_shipHeight >> 1));
+
+ if (x < _shipRange.left)
+ x = 0;
+ else if (x > _shipRange.right - 1)
+ x = _shipRange.width() - 1;
+ else
+ x -= _shipRange.left;
+
+ if (y < _shipRange.top)
+ y = 0;
+ else if (y > _shipRange.bottom - 1)
+ y = _shipRange.height() - 1;
+ else
+ y -= _shipRange.top;
+
+ x = kNumSpriteColumns * x / _shipRange.width();
+ y = kNumSpriteRows * y / _shipRange.height();
+
+ _spritesMovie.setTime(40 * (x + y * kNumSpriteColumns));
+ }
+}
+
+bool RobotShip::pointInShuttle(Common::Point &pt) {
+ Common::Rect r;
+ _spritesMovie.getBounds(r);
+
+ int dx = r.width() / 4;
+ int dy = r.height() / 6;
+
+ r.left += dx;
+ r.right -= dx;
+ r.top += dy;
+ r.bottom -= dy;
+
+ return r.contains(pt);
+}
+
+void RobotShip::hitByEnergyBeam(Common::Point impactPoint) {
+ ((Mars *)g_neighborhood)->decreaseRobotShuttleEnergy(1, impactPoint);
+ setGlowing(true);
+ ((PegasusEngine *)g_engine)->delayShell(1, 3);
+ setGlowing(false);
+}
+
+void RobotShip::hitByGravitonCannon(Common::Point impactPoint) {
+ GameState.setMarsHitRobotWithCannon(true);
+ ((Mars *)g_neighborhood)->decreaseRobotShuttleEnergy(6, impactPoint);
+}
+
+void RobotShip::snareByTractorBeam() {
+ _dropJunkFuse.stopFuse();
+ stop();
+
+ Common::Point currentV;
+ dHermite(_p1, _p4, _r1, _r4, _lastTime, _duration, currentV);
+
+ _p1 = _currentLocation;
+ _r1 = currentV;
+ _p4.x = kShuttleWindowMidH;
+ _p4.y = kShuttleWindowMidV;
+ _r4.x = 0;
+ _r4.y = 0;
+ _duration = kTractorBeamTime;
+ _snaring = true;
+ setSegment(0, _duration);
+ setTime(0);
+ start();
+}
+
+void RobotShip::timeChanged(const TimeValue) {
+ Common::Point newLocation;
+ hermite(_p1, _p4, _r1, _r4, _lastTime, _duration, newLocation);
+ moveRobotTo(newLocation.x, newLocation.y);
+
+ if (_lastTime == _duration) {
+ if (_snaring)
+ stop();
+ else
+ newDestination();
+ }
+}
+
+void RobotShip::makeVelocityVector(tCoordType x1, tCoordType y1, tCoordType x2, tCoordType y2, Common::Point &vector) {
+ tCoordType length = ((PegasusEngine *)g_engine)->getRandomNumber(kVelocityVectorSlop - 1) + kVelocityVectorLength;
+ vector.x = x2 - x1;
+ vector.y = y2 - y1;
+ float oldLength = sqrt(vector.x * vector.x + vector.y * vector.y);
+ vector.x = (int)(vector.x * length / oldLength);
+ vector.y = (int)(vector.y * length / oldLength);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/robotship.h b/engines/pegasus/neighborhood/mars/robotship.h
new file mode 100755
index 0000000000..7c6d996566
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/robotship.h
@@ -0,0 +1,86 @@
+/* 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_ROBOTSHIP_H
+#define PEGASUS_NEIGHBORHOOD_MARS_ROBOTSHIP_H
+
+#include "pegasus/movie.h"
+
+namespace Pegasus {
+
+const tCoordType kShuttleMovieWidth = 114;
+const tCoordType kShuttleMovieHeight = 42;
+
+class RobotShip : IdlerTimeBase {
+friend void timeToDropJunkFunction(FunctionPtr *, void *);
+
+public:
+ RobotShip();
+ virtual ~RobotShip();
+
+ void initRobotShip();
+ void cleanUpRobotShip();
+
+ void startMoving();
+
+ void killRobotShip();
+
+ bool pointInShuttle(Common::Point&);
+
+ void hitByEnergyBeam(Common::Point impactPoint);
+ void hitByGravitonCannon(Common::Point impactPoint);
+
+ void getShuttleBounds(Common::Rect &r) { _spritesMovie.getBounds(r); }
+
+ void setGlowing(const bool glowing) { _spritesMovie.setGlowing(glowing); }
+
+ void snareByTractorBeam();
+ bool isSnared() { return _snaring && getTime() == _duration; }
+
+ bool isDead() { return _dead; }
+
+ void setUpNextDropTime();
+
+protected:
+ void newDestination();
+ void moveRobotTo(tCoordType, tCoordType);
+ void timeToDropJunk();
+ virtual void timeChanged(const TimeValue);
+ void makeVelocityVector(tCoordType, tCoordType, tCoordType, tCoordType, Common::Point &);
+
+ GlowingMovie _spritesMovie;
+ Common::Rect _shipRange;
+ int _shipWidth, _shipHeight;
+ Common::Point _p1, _p4, _r1, _r4, _currentLocation;
+ FuseFunction _dropJunkFuse;
+ TimeValue _duration;
+ bool _snaring, _dead;
+};
+
+extern RobotShip *g_robotShip;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/spacechase3d.cpp b/engines/pegasus/neighborhood/mars/spacechase3d.cpp
index a15898f573..05f8233763 100755
--- a/engines/pegasus/neighborhood/mars/spacechase3d.cpp
+++ b/engines/pegasus/neighborhood/mars/spacechase3d.cpp
@@ -87,4 +87,20 @@ float linearInterp(const float arg1, const float arg2, const float t) {
return arg1 + (arg2 - arg1) * t;
}
+bool isNegative(int a) {
+ return a < 0;
+}
+
+bool isPositive(int a) {
+ return a > 0;
+}
+
+int sign(int a) {
+ return isNegative(a) ? -1 : isPositive(a) ? 1 : 0;
+}
+
+bool sameSign(int a, int b) {
+ return sign(a) == sign(b);
+}
+
} // End of namespace Pegasus