aboutsummaryrefslogtreecommitdiff
path: root/engines/pegasus/items
diff options
context:
space:
mode:
Diffstat (limited to 'engines/pegasus/items')
-rw-r--r--engines/pegasus/items/autodragger.cpp91
-rw-r--r--engines/pegasus/items/autodragger.h57
-rw-r--r--engines/pegasus/items/biochips/aichip.cpp279
-rw-r--r--engines/pegasus/items/biochips/aichip.h69
-rw-r--r--engines/pegasus/items/biochips/biochipitem.cpp95
-rw-r--r--engines/pegasus/items/biochips/biochipitem.h54
-rw-r--r--engines/pegasus/items/biochips/mapchip.cpp106
-rw-r--r--engines/pegasus/items/biochips/mapchip.h64
-rw-r--r--engines/pegasus/items/biochips/mapimage.cpp443
-rw-r--r--engines/pegasus/items/biochips/mapimage.h84
-rw-r--r--engines/pegasus/items/biochips/opticalchip.cpp190
-rw-r--r--engines/pegasus/items/biochips/opticalchip.h71
-rw-r--r--engines/pegasus/items/biochips/pegasuschip.cpp198
-rw-r--r--engines/pegasus/items/biochips/pegasuschip.h55
-rw-r--r--engines/pegasus/items/biochips/retscanchip.cpp49
-rw-r--r--engines/pegasus/items/biochips/retscanchip.h43
-rw-r--r--engines/pegasus/items/biochips/shieldchip.cpp53
-rw-r--r--engines/pegasus/items/biochips/shieldchip.h46
-rw-r--r--engines/pegasus/items/inventory.cpp175
-rw-r--r--engines/pegasus/items/inventory.h80
-rw-r--r--engines/pegasus/items/inventory/airmask.cpp249
-rw-r--r--engines/pegasus/items/inventory/airmask.h76
-rw-r--r--engines/pegasus/items/inventory/gascanister.cpp46
-rw-r--r--engines/pegasus/items/inventory/gascanister.h44
-rw-r--r--engines/pegasus/items/inventory/inventoryitem.cpp110
-rw-r--r--engines/pegasus/items/inventory/inventoryitem.h67
-rw-r--r--engines/pegasus/items/inventory/keycard.cpp59
-rw-r--r--engines/pegasus/items/inventory/keycard.h48
-rw-r--r--engines/pegasus/items/inventorypicture.cpp370
-rw-r--r--engines/pegasus/items/inventorypicture.h125
-rw-r--r--engines/pegasus/items/item.cpp314
-rw-r--r--engines/pegasus/items/item.h363
-rw-r--r--engines/pegasus/items/itemdragger.cpp193
-rw-r--r--engines/pegasus/items/itemdragger.h96
-rw-r--r--engines/pegasus/items/itemlist.cpp67
-rw-r--r--engines/pegasus/items/itemlist.h59
36 files changed, 4588 insertions, 0 deletions
diff --git a/engines/pegasus/items/autodragger.cpp b/engines/pegasus/items/autodragger.cpp
new file mode 100644
index 0000000000..40bad14a89
--- /dev/null
+++ b/engines/pegasus/items/autodragger.cpp
@@ -0,0 +1,91 @@
+/* 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/elements.h"
+#include "pegasus/items/autodragger.h"
+
+namespace Pegasus {
+
+AutoDragger::AutoDragger() {
+ _draggingElement = NULL;
+ _lastTime = 0;
+ initCallBack(this, kCallBackAtExtremes);
+}
+
+void AutoDragger::autoDrag(DisplayElement *dragElement, const Common::Point &startPoint, const Common::Point &stopPoint,
+ TimeValue dragTime, TimeScale dragScale) {
+ _draggingElement = dragElement;
+
+ if (_draggingElement) {
+ _startLocation = startPoint;
+ _stopLocation = stopPoint;
+ _lastTime = 0;
+ _done = false;
+ _draggingElement->moveElementTo(_startLocation.x, _startLocation.y);
+ setScale(dragScale);
+ setSegment(0, dragTime);
+ setTime(0);
+ scheduleCallBack(kTriggerAtStop, 0, 0);
+ startIdling();
+ start();
+ } else {
+ stopDragging();
+ }
+}
+
+void AutoDragger::stopDragging() {
+ cancelCallBack();
+ stopIdling();
+ _draggingElement = 0;
+ _startLocation = Common::Point();
+ _stopLocation = Common::Point();
+ _lastTime = 0;
+ _done = true;
+}
+
+bool AutoDragger::isDragging() {
+ return isIdling();
+}
+
+void AutoDragger::useIdleTime() {
+ TimeValue thisTime = getTime();
+
+ if (thisTime != _lastTime) {
+ int32 offsetX = (_stopLocation.x - _startLocation.x) * (int32)thisTime / (int32)getDuration();
+ int32 offsetY = (_stopLocation.y - _startLocation.y) * (int32)thisTime / (int32)getDuration();
+ _draggingElement->moveElementTo(_startLocation.x + offsetX, _startLocation.y + offsetY);
+ _lastTime = thisTime;
+ }
+
+ if (_done)
+ stopDragging();
+}
+
+void AutoDragger::callBack() {
+ if (isIdling())
+ _done = true;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/autodragger.h b/engines/pegasus/items/autodragger.h
new file mode 100644
index 0000000000..6783fdf9a3
--- /dev/null
+++ b/engines/pegasus/items/autodragger.h
@@ -0,0 +1,57 @@
+/* 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_ITEMS_AUTODRAGGER_H
+#define PEGASUS_ITEMS_AUTODRAGGER_H
+
+#include "pegasus/timers.h"
+
+namespace Pegasus {
+
+class DisplayElement;
+
+class AutoDragger : private Idler, private TimeBase, private TimeBaseCallBack {
+public:
+ AutoDragger();
+ virtual ~AutoDragger() {}
+
+ void autoDrag(DisplayElement *, const Common::Point &, const Common::Point &, TimeValue, TimeScale);
+ bool isDragging();
+ void stopDragging();
+
+protected:
+ void useIdleTime();
+ void callBack();
+
+ DisplayElement *_draggingElement;
+ Common::Point _startLocation, _stopLocation;
+ TimeValue _lastTime;
+ bool _done;
+};
+
+} // End of namespace Pegasus
+
+#endif
+
diff --git a/engines/pegasus/items/biochips/aichip.cpp b/engines/pegasus/items/biochips/aichip.cpp
new file mode 100644
index 0000000000..cbcfc363e8
--- /dev/null
+++ b/engines/pegasus/items/biochips/aichip.cpp
@@ -0,0 +1,279 @@
+/* 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/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/aichip.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+// indexed by [number of hints][number of solves (0, 1, or 2)][which button to highlight]
+static const ItemState s_highlightState[4][3][7] = {
+ {
+ {kAI000, -1, -1, -1, -1, kAI005, kAI006},
+ {kAI010, -1, -1, -1, -1, kAI015, kAI016},
+ {kAI020, -1, -1, -1, kAI024, -1, -1}
+ },
+ {
+ {kAI100, kAI101, -1, -1, -1, kAI105, kAI106},
+ {kAI110, kAI111, -1, -1, -1, kAI115, kAI116},
+ {kAI120, kAI121, -1, -1, kAI124, kAI125, kAI126}
+ },
+ {
+ {kAI200, kAI201, kAI202, -1, -1, kAI205, kAI206},
+ {kAI210, kAI211, kAI212, -1, -1, kAI215, kAI216},
+ {kAI220, kAI221, kAI222, -1, kAI224, kAI225, kAI226}
+ },
+ {
+ {kAI300, kAI301, kAI302, kAI303, -1, kAI305, kAI306},
+ {kAI310, kAI311, kAI312, kAI313, -1, kAI315, kAI316},
+ {kAI320, kAI321, kAI322, kAI323, kAI324, kAI325, kAI326}
+ }
+};
+
+AIChip *g_AIChip = 0;
+
+AIChip::AIChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction), _briefingSpot(kAIBriefingSpotID), _scanSpot(kAIScanSpotID),
+ _hint1Spot(kAIHint1SpotID), _hint2Spot(kAIHint2SpotID), _hint3Spot(kAIHint3SpotID), _solveSpot(kAISolveSpotID) {
+ _briefingSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 10, kAIMiddleAreaTop + 27, kAIMiddleAreaLeft + 10 + 81, kAIMiddleAreaTop + 27 + 31));
+ _briefingSpot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_briefingSpot);
+
+ _scanSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 100, kAIMiddleAreaTop + 27, kAIMiddleAreaLeft + 100 + 81, kAIMiddleAreaTop + 27 + 31));
+ _scanSpot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_scanSpot);
+
+ _hint1Spot.setArea(Common::Rect(kAIMiddleAreaLeft + 70, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 70 + 21, kAIMiddleAreaTop + 67 + 21));
+ _hint1Spot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_hint1Spot);
+
+ _hint2Spot.setArea(Common::Rect(kAIMiddleAreaLeft + 91, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 91 + 20, kAIMiddleAreaTop + 67 + 21));
+ _hint2Spot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_hint2Spot);
+
+ _hint3Spot.setArea(Common::Rect(kAIMiddleAreaLeft + 111, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 111 + 20, kAIMiddleAreaTop + 67 + 21));
+ _hint3Spot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_hint3Spot);
+
+ _solveSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 131, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 131 + 50, kAIMiddleAreaTop + 67 + 21));
+ _solveSpot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_solveSpot);
+
+ _playingMovie = false;
+ setItemState(kAI000);
+
+ g_AIChip = this;
+}
+
+AIChip::~AIChip() {
+ g_AIChip = NULL;
+
+ g_allHotspots.removeOneHotspot(kAIBriefingSpotID);
+ g_allHotspots.removeOneHotspot(kAIScanSpotID);
+ g_allHotspots.removeOneHotspot(kAIHint1SpotID);
+ g_allHotspots.removeOneHotspot(kAIHint2SpotID);
+ g_allHotspots.removeOneHotspot(kAIHint3SpotID);
+ g_allHotspots.removeOneHotspot(kAISolveSpotID);
+}
+
+void AIChip::select() {
+ BiochipItem::select();
+ setUpAIChip();
+}
+
+void AIChip::takeSharedArea() {
+ setUpAIChip();
+}
+
+void AIChip::setUpAIChip() {
+ if (!_playingMovie) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ uint numSolves;
+ if (GameState.getWalkthroughMode()) {
+ if (vm->canSolve())
+ numSolves = 2;
+ else
+ numSolves = 1;
+ } else {
+ numSolves = 0;
+ }
+
+ setItemState(s_highlightState[vm->getNumHints()][numSolves][0]);
+ }
+}
+
+// Only does something when there are hints or solves available.
+void AIChip::setUpAIChipRude() {
+ if (!_playingMovie) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ uint numSolves;
+ if (GameState.getWalkthroughMode()) {
+ if (vm->canSolve())
+ numSolves = 2;
+ else
+ numSolves = 1;
+ } else {
+ numSolves = 0;
+ }
+
+ uint numHints = vm->getNumHints();
+ if (numSolves == 2 || numHints != 0)
+ setItemState(s_highlightState[numHints][numSolves][0]);
+ }
+}
+
+void AIChip::activateAIHotspots() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+ _briefingSpot.setActive();
+ _scanSpot.setActive();
+
+ switch (vm->getNumHints()) {
+ case 3:
+ _hint3Spot.setActive();
+ // fall through
+ case 2:
+ _hint2Spot.setActive();
+ // fall through
+ case 1:
+ _hint1Spot.setActive();
+ break;
+ }
+
+ if (GameState.getWalkthroughMode() && vm->canSolve())
+ _solveSpot.setActive();
+}
+
+void AIChip::showBriefingClicked() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ _playingMovie = true;
+
+ uint numSolves;
+ if (GameState.getWalkthroughMode()) {
+ if (vm->canSolve())
+ numSolves = 2;
+ else
+ numSolves = 1;
+ } else {
+ numSolves = 0;
+ }
+
+ ItemState newState = s_highlightState[vm->getNumHints()][numSolves][kAIBriefingSpotID - kAIHint1SpotID + 1];
+ if (newState != -1)
+ setItemState(newState);
+}
+
+void AIChip::showEnvScanClicked() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ _playingMovie = true;
+
+ uint numSolves;
+ if (GameState.getWalkthroughMode()) {
+ if (vm->canSolve())
+ numSolves = 2;
+ else
+ numSolves = 1;
+ } else {
+ numSolves = 0;
+ }
+
+ ItemState newState = s_highlightState[vm->getNumHints()][numSolves][kAIScanSpotID - kAIHint1SpotID + 1];
+
+ if (newState != -1)
+ setItemState(newState);
+}
+
+void AIChip::clearClicked() {
+ _playingMovie = false;
+ setUpAIChip();
+}
+
+void AIChip::clickInAIHotspot(HotSpotID id) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ Common::String movieName;
+
+ switch (id) {
+ case kAIBriefingSpotID:
+ movieName = vm->getBriefingMovie();
+ break;
+ case kAIScanSpotID:
+ movieName = vm->getEnvScanMovie();
+ break;
+ case kAIHint1SpotID:
+ movieName = vm->getHintMovie(1);
+ break;
+ case kAIHint2SpotID:
+ movieName = vm->getHintMovie(2);
+ break;
+ case kAIHint3SpotID:
+ movieName = vm->getHintMovie(3);
+ break;
+ case kAISolveSpotID:
+ g_neighborhood->doSolve();
+ break;
+ }
+
+ ItemState state = getItemState();
+
+ if (!movieName.empty()) {
+ _playingMovie = true;
+
+ uint numSolves;
+ if (GameState.getWalkthroughMode()) {
+ if (vm->canSolve())
+ numSolves = 2;
+ else
+ numSolves = 1;
+ } else {
+ numSolves = 0;
+ }
+
+ ItemState newState = s_highlightState[vm->getNumHints()][numSolves][id - kAIHint1SpotID + 1];
+
+ if (newState != -1)
+ setItemState(newState);
+
+ if (g_AIArea) {
+ vm->prepareForAIHint(movieName);
+ g_AIArea->playAIMovie(kRightAreaSignature, movieName, false, kHintInterruption);
+ vm->cleanUpAfterAIHint(movieName);
+ }
+
+ if (newState != -1)
+ setItemState(state);
+
+ _playingMovie = false;
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/aichip.h b/engines/pegasus/items/biochips/aichip.h
new file mode 100644
index 0000000000..7a33953612
--- /dev/null
+++ b/engines/pegasus/items/biochips/aichip.h
@@ -0,0 +1,69 @@
+/* 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_ITEMS_BIOCHIPS_AICHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_AICHIP_H
+
+#include "pegasus/hotspot.h"
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+class AIChip : public BiochipItem {
+public:
+ AIChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~AIChip();
+
+ void select();
+
+ void setUpAIChip();
+
+ // Called to set up the AI chip when the AI chip is the current chip but does not
+ // own the center area.
+ void setUpAIChipRude();
+ void activateAIHotspots();
+ void clickInAIHotspot(HotSpotID);
+
+ void takeSharedArea();
+
+ void showBriefingClicked();
+ void showEnvScanClicked();
+ void clearClicked();
+
+protected:
+ Hotspot _briefingSpot;
+ Hotspot _scanSpot;
+ Hotspot _hint1Spot;
+ Hotspot _hint2Spot;
+ Hotspot _hint3Spot;
+ Hotspot _solveSpot;
+ bool _playingMovie;
+};
+
+extern AIChip *g_AIChip;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/biochipitem.cpp b/engines/pegasus/items/biochips/biochipitem.cpp
new file mode 100644
index 0000000000..5686948937
--- /dev/null
+++ b/engines/pegasus/items/biochips/biochipitem.cpp
@@ -0,0 +1,95 @@
+/* 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 "common/stream.h"
+
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+BiochipItem::BiochipItem(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ Item(id, neighborhood, room, direction) {
+
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ Common::SeekableReadStream *biochipInfo = vm->_resFork->getResource(MKTAG('B', 'i', 'o', 'I'), kItemBaseResID + id);
+ if (biochipInfo) {
+ _biochipInfoPanelTime = biochipInfo->readUint32BE();
+ delete biochipInfo;
+ } else {
+ _biochipInfoPanelTime = 0;
+ }
+
+ Common::SeekableReadStream *rightInfo = vm->_resFork->getResource(MKTAG('R', 'g', 'h', 't'), kItemBaseResID + id);
+ if (!rightInfo)
+ error("Could not find right info for biochip %d", id);
+
+ _rightAreaInfo = readItemState(rightInfo);
+ delete rightInfo;
+
+ setItemState(kNormalItem);
+}
+
+BiochipItem::~BiochipItem() {
+ delete[] _rightAreaInfo.entries;
+}
+
+ItemType BiochipItem::getItemType() {
+ return kBiochipItemType;
+}
+
+TimeValue BiochipItem::getRightAreaTime() const {
+ if (!_rightAreaInfo.entries)
+ return 0xffffffff;
+
+ TimeValue time;
+ ItemState state;
+
+ findItemStateEntryByState(_rightAreaInfo, _itemState, time);
+ if (time == 0xffffffff)
+ getItemStateEntry(_rightAreaInfo, 0, state, time);
+
+ return time;
+}
+
+// Must affect images in right area.
+void BiochipItem::select() {
+ Item::select();
+
+ if (g_AIArea)
+ g_AIArea->setAIAreaToTime(kBiochipSignature, kRightAreaSignature, getRightAreaTime());
+}
+
+void BiochipItem::deselect() {
+ Item::deselect();
+
+ if (g_AIArea)
+ g_AIArea->setAIAreaToTime(kBiochipSignature, kRightAreaSignature, 0xffffffff);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/biochipitem.h b/engines/pegasus/items/biochips/biochipitem.h
new file mode 100644
index 0000000000..2039e80c6f
--- /dev/null
+++ b/engines/pegasus/items/biochips/biochipitem.h
@@ -0,0 +1,54 @@
+/* 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_ITEMS_BIOCHIPS_BIOCHIPITEM_H
+#define PEGASUS_ITEMS_BIOCHIPS_BIOCHIPITEM_H
+
+#include "pegasus/items/item.h"
+
+namespace Pegasus {
+
+class BiochipItem : public Item {
+public:
+ BiochipItem(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~BiochipItem();
+
+ virtual ItemType getItemType();
+
+ TimeValue getPanelTime() const { return _biochipInfoPanelTime; }
+ TimeValue getRightAreaTime() const;
+
+ // Must affect images in right area.
+ virtual void select();
+ virtual void deselect();
+
+protected:
+ TimeValue _biochipInfoPanelTime;
+ ItemStateInfo _rightAreaInfo;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/mapchip.cpp b/engines/pegasus/items/biochips/mapchip.cpp
new file mode 100644
index 0000000000..69050d5193
--- /dev/null
+++ b/engines/pegasus/items/biochips/mapchip.cpp
@@ -0,0 +1,106 @@
+/* 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/ai/ai_area.h"
+#include "pegasus/items/biochips/mapchip.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+MapChip *g_map = 0;
+
+MapChip::MapChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction) {
+ g_map = this;
+ setItemState(kMapUnavailable);
+}
+
+MapChip::~MapChip() {
+ g_map = 0;
+}
+
+void MapChip::writeToStream(Common::WriteStream *stream) {
+ return _image.writeToStream(stream);
+}
+
+void MapChip::readFromStream(Common::ReadStream *stream) {
+ return _image.readFromStream(stream);
+}
+
+void MapChip::select() {
+ BiochipItem::select();
+ moveToMapLocation(GameState.getCurrentNeighborhood(), GameState.getCurrentRoom(), GameState.getCurrentDirection());
+ _image.show();
+}
+
+void MapChip::takeSharedArea() {
+ _image.show();
+}
+
+void MapChip::giveUpSharedArea() {
+ _image.hide();
+}
+
+void MapChip::deselect() {
+ BiochipItem::deselect();
+ _image.unloadImage();
+}
+
+void MapChip::moveToMapLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant dir) {
+ AirQuality airQuality;
+
+ if (g_neighborhood)
+ airQuality = g_neighborhood->getAirQuality(room);
+ else
+ airQuality = kAirQualityGood;
+
+ switch (neighborhood) {
+ case kMarsID:
+ if (airQuality == kAirQualityVacuum) {
+ if (room >= kMars35 && room <= kMars39) {
+ setItemState(kMapEngaged);
+ if (isSelected() && g_AIArea && g_AIArea->getMiddleAreaOwner() == kBiochipSignature)
+ _image.loadGearRoomIfNecessary();
+ } else {
+ setItemState(kMapEngaged);
+ if (isSelected() && g_AIArea && g_AIArea->getMiddleAreaOwner() == kBiochipSignature)
+ _image.loadMazeIfNecessary();
+ }
+
+ _image.moveToMapLocation(neighborhood, room, dir);
+ } else {
+ _image.unloadImage();
+ setItemState(kMapUnavailable);
+ }
+ break;
+ default:
+ _image.unloadImage();
+ setItemState(kMapUnavailable);
+ break;
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/mapchip.h b/engines/pegasus/items/biochips/mapchip.h
new file mode 100644
index 0000000000..6690090aa4
--- /dev/null
+++ b/engines/pegasus/items/biochips/mapchip.h
@@ -0,0 +1,64 @@
+/* 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_ITEMS_BIOCHIPS_MAPCHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_MAPCHIP_H
+
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/items/biochips/mapimage.h"
+
+namespace Common {
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+class MapChip : public BiochipItem {
+public:
+ MapChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~MapChip();
+
+ void select();
+ void deselect();
+ void takeSharedArea();
+ void giveUpSharedArea();
+
+ void moveToMapLocation(const NeighborhoodID, const RoomID, const DirectionConstant);
+
+ void writeToStream(Common::WriteStream *);
+ void readFromStream(Common::ReadStream *);
+
+ bool beenToMaze() { return _image.anyFlagSet(); }
+
+protected:
+ MapImage _image;
+};
+
+extern MapChip *g_map;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/mapimage.cpp b/engines/pegasus/items/biochips/mapimage.cpp
new file mode 100644
index 0000000000..9f4170d063
--- /dev/null
+++ b/engines/pegasus/items/biochips/mapimage.cpp
@@ -0,0 +1,443 @@
+/* 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/items/biochips/mapimage.h"
+
+namespace Pegasus {
+
+#define FLAG_TO_INDEX(flag) ((flag) >> 2)
+#define INDEX_TO_FLAG(index) ((index) << 2)
+
+#define ROOM_TO_INDEX(room) \
+ (((room) >= kMars35 && (room) <= kMars39) ? ((room) - kMars35) : \
+ (((room) == kMars60) ? (kMars39 - kMars35 + 1) : \
+ ((room) - kMarsMaze004 + kMars39 - kMars35 + 2)))
+
+#define INDEX_TO_ROOM(index) \
+ (((index) <= ROOM_TO_INDEX(kMars39)) ? \
+ (((index) - ROOM_TO_INDEX(kMars35)) + kMars35) : \
+ ((index) <= ROOM_TO_INDEX(kMars60,)) ? kMars60 : \
+ ((((index) - ROOM_TO_INDEX(kMarsMaze004))) + kMarsMaze004))
+
+#define ROOM_TO_FLAG(room, dir) (INDEX_TO_FLAG(ROOM_TO_INDEX(room)) | (dir))
+
+#define FLAG_TO_ROOM(flag) (INDEX_TO_ROOM(FLAG_TO_INDEX(flag)))
+
+#define FLAG_TO_DIRECTION(flag) ((flag) & 3)
+
+static const int kGearRoomFlagLow = ROOM_TO_FLAG(kMars35, kNorth);
+static const int kGearRoomFlagHigh = ROOM_TO_FLAG(kMars39, kWest);
+
+static const int kMazeFlagLow = ROOM_TO_FLAG(kMars60, kNorth);
+static const int kMazeFlagHigh = ROOM_TO_FLAG(kMarsMaze200, kWest);
+
+static const CoordType kGearRoomScreenOffsetX = 49;
+static const CoordType kGearRoomScreenOffsetY = 47;
+
+static const CoordType kGearRoomGridOriginX = 1;
+static const CoordType kGearRoomGridOriginY = 4;
+
+static const CoordType kMazeScreenOffsetX = 16;
+static const CoordType kMazeScreenOffsetY = 20;
+
+static const CoordType kMazeGridOriginX = 6;
+static const CoordType kMazeGridOriginY = 1;
+
+static const CoordType kGridWidth = 4;
+static const CoordType kGridHeight = 4;
+
+static const uint16 kMapOfMazePICTID = 906;
+static const uint16 kMapOfGearRoomPICTID = 907;
+
+static const int s_mapCoords[MapImage::kNumMappingRooms][2] = {
+ /* kMars35 */ { 0, 0 },
+ /* kMars36 */ { 1, 0 },
+ /* kMars37 */ { 2, 0 },
+ /* kMars38 */ { 3, 0 },
+ /* kMars39 */ { 4, 0 },
+ /* kMars60 */ { 19, 9 },
+ /* kMarsMaze004 */ { 18, 9 },
+ /* kMarsMaze005 */ { 18, 10 },
+ /* kMarsMaze006 */ { 17, 10 },
+ /* kMarsMaze007 */ { 16, 10 },
+ /* kMarsMaze008 */ { 15, 10 },
+ /* kMarsMaze009 */ { 14, 10 },
+ /* kMarsMaze010 */ { 14, 9 },
+ /* kMarsMaze011 */ { 14, 8 },
+ /* kMarsMaze012 */ { 14, 7 },
+ /* kMarsMaze015 */ { 16, 7 },
+ /* kMarsMaze016 */ { 14, 11 },
+ /* kMarsMaze017 */ { 14, 12 },
+ /* kMarsMaze018 */ { 15, 12 },
+ /* kMarsMaze019 */ { 16, 12 },
+ /* kMarsMaze020 */ { 16, 13 },
+ /* kMarsMaze021 */ { 16, 14 },
+ /* kMarsMaze022 */ { 16, 15 },
+ /* kMarsMaze023 */ { 17, 15 },
+ /* kMarsMaze024 */ { 18, 15 },
+ /* kMarsMaze025 */ { 18, 14 },
+ /* kMarsMaze026 */ { 18, 13 },
+ /* kMarsMaze027 */ { 18, 12 },
+ /* kMarsMaze028 */ { 18, 11 },
+ /* kMarsMaze031 */ { 19, 14 },
+ /* kMarsMaze032 */ { 20, 14 },
+ /* kMarsMaze033 */ { 20, 13 },
+ /* kMarsMaze034 */ { 20, 12 },
+ /* kMarsMaze035 */ { 20, 11 },
+ /* kMarsMaze036 */ { 21, 11 },
+ /* kMarsMaze037 */ { 15, 15 },
+ /* kMarsMaze038 */ { 14, 15 },
+ /* kMarsMaze039 */ { 13, 15 },
+ /* kMarsMaze042 */ { 10, 15 },
+ /* kMarsMaze043 */ { 9, 15 },
+ /* kMarsMaze044 */ { 8, 15 },
+ /* kMarsMaze045 */ { 7, 15 },
+ /* kMarsMaze046 */ { 6, 15 },
+ /* kMarsMaze047 */ { 5, 15 },
+ /* kMarsMaze049 */ { 13, 14 },
+ /* kMarsMaze050 */ { 12, 14 },
+ /* kMarsMaze051 */ { 11, 14 },
+ /* kMarsMaze052 */ { 10, 14 },
+ /* kMarsMaze053 */ { 10, 13 },
+ /* kMarsMaze054 */ { 9, 13 },
+ /* kMarsMaze055 */ { 8, 13 },
+ /* kMarsMaze056 */ { 8, 12 },
+ /* kMarsMaze057 */ { 7, 12 },
+ /* kMarsMaze058 */ { 12, 13 },
+ /* kMarsMaze059 */ { 12, 12 },
+ /* kMarsMaze060 */ { 12, 11 },
+ /* kMarsMaze061 */ { 12, 10 },
+ /* kMarsMaze063 */ { 12, 9 },
+ /* kMarsMaze064 */ { 12, 8 },
+ /* kMarsMaze065 */ { 12, 7 },
+ /* kMarsMaze066 */ { 13, 7 },
+ /* kMarsMaze067 */ { 15, 7 },
+ /* kMarsMaze068 */ { 17, 7 },
+ /* kMarsMaze069 */ { 18, 7 },
+ /* kMarsMaze070 */ { 19, 7 },
+ /* kMarsMaze071 */ { 20, 7 },
+ /* kMarsMaze072 */ { 20, 6 },
+ /* kMarsMaze074 */ { 20, 5 },
+ /* kMarsMaze076 */ { 20, 4 },
+ /* kMarsMaze078 */ { 20, 3 },
+ /* kMarsMaze079 */ { 20, 2 },
+ /* kMarsMaze081 */ { 20, 2 },
+ /* kMarsMaze083 */ { 20, 0 },
+ /* kMarsMaze084 */ { 19, 0 },
+ /* kMarsMaze085 */ { 18, 0 },
+ /* kMarsMaze086 */ { 17, 0 },
+ /* kMarsMaze087 */ { 16, 0 },
+ /* kMarsMaze088 */ { 15, 0 },
+ /* kMarsMaze089 */ { 14, 0 },
+ /* kMarsMaze090 */ { 13, 0 },
+ /* kMarsMaze091 */ { 12, 0 },
+ /* kMarsMaze092 */ { 11, 0 },
+ /* kMarsMaze093 */ { 10, 0 },
+ /* kMarsMaze098 */ { 10, 1 },
+ /* kMarsMaze099 */ { 8, 2 },
+ /* kMarsMaze100 */ { 9, 2 },
+ /* kMarsMaze101 */ { 10, 2 },
+ /* kMarsMaze104 */ { 13, 2 },
+ /* kMarsMaze105 */ { 13, 3 },
+ /* kMarsMaze106 */ { 13, 4 },
+ /* kMarsMaze107 */ { 13, 5 },
+ /* kMarsMaze108 */ { 14, 5 },
+ /* kMarsMaze111 */ { 15, 5 },
+ /* kMarsMaze113 */ { 16, 5 },
+ /* kMarsMaze114 */ { 17, 5 },
+ /* kMarsMaze115 */ { 18, 5 },
+ /* kMarsMaze116 */ { 18, 4 },
+ /* kMarsMaze117 */ { 18, 3 },
+ /* kMarsMaze118 */ { 19, 3 },
+ /* kMarsMaze119 */ { 18, 2 },
+ /* kMarsMaze120 */ { 17, 2 },
+ /* kMarsMaze121 */ { 16, 2 },
+ /* kMarsMaze122 */ { 15, 2 },
+ /* kMarsMaze123 */ { 15, 1 },
+ /* kMarsMaze124 */ { 12, 4 },
+ /* kMarsMaze125 */ { 11, 4 },
+ /* kMarsMaze126 */ { 10, 4 },
+ /* kMarsMaze127 */ { 10, 5 },
+ /* kMarsMaze128 */ { 10, 6 },
+ /* kMarsMaze129 */ { 9, 6 },
+ /* kMarsMaze130 */ { 8, 6 },
+ /* kMarsMaze131 */ { 7, 6 },
+ /* kMarsMaze132 */ { 7, 7 },
+ /* kMarsMaze133 */ { 7, 8 },
+ /* kMarsMaze136 */ { 7, 11 },
+ /* kMarsMaze137 */ { 6, 11 },
+ /* kMarsMaze138 */ { 5, 11 },
+ /* kMarsMaze139 */ { 5, 12 },
+ /* kMarsMaze140 */ { 4, 12 },
+ /* kMarsMaze141 */ { 5, 13 },
+ /* kMarsMaze142 */ { 5, 14 },
+ /* kMarsMaze143 */ { 4, 14 },
+ /* kMarsMaze144 */ { 3, 14 },
+ /* kMarsMaze145 */ { 3, 13 },
+ /* kMarsMaze146 */ { 2, 13 },
+ /* kMarsMaze147 */ { 1, 13 },
+ /* kMarsMaze148 */ { 1, 14 },
+ /* kMarsMaze149 */ { 1, 15 },
+ /* kMarsMaze152 */ { 1, 12 },
+ /* kMarsMaze153 */ { 1, 11 },
+ /* kMarsMaze154 */ { 1, 10 },
+ /* kMarsMaze155 */ { 1, 9 },
+ /* kMarsMaze156 */ { 1, 8 },
+ /* kMarsMaze157 */ { 2, 10 },
+ /* kMarsMaze159 */ { 2, 8 },
+ /* kMarsMaze160 */ { 2, 7 },
+ /* kMarsMaze161 */ { 2, 6 },
+ /* kMarsMaze162 */ { 3, 10 },
+ /* kMarsMaze163 */ { 3, 9 },
+ /* kMarsMaze164 */ { 3, 8 },
+ /* kMarsMaze165 */ { 4, 8 },
+ /* kMarsMaze166 */ { 5, 8 },
+ /* kMarsMaze167 */ { 6, 8 },
+ /* kMarsMaze168 */ { 3, 6 },
+ /* kMarsMaze169 */ { 4, 6 },
+ /* kMarsMaze170 */ { 5, 6 },
+ /* kMarsMaze171 */ { 5, 5 },
+ /* kMarsMaze172 */ { 5, 4 },
+ /* kMarsMaze173 */ { 4, 4 },
+ /* kMarsMaze174 */ { 3, 4 },
+ /* kMarsMaze175 */ { 3, 5 },
+ /* kMarsMaze177 */ { 8, 4 },
+ /* kMarsMaze178 */ { 8, 3 },
+ /* kMarsMaze179 */ { 7, 4 },
+ /* kMarsMaze180 */ { 6, 4 },
+ /* kMarsMaze181 */ { 6, 3 },
+ /* kMarsMaze182 */ { 6, 2 },
+ /* kMarsMaze183 */ { 6, 1 },
+ /* kMarsMaze184 */ { 6, 0 },
+ /* kMarsMaze187 */ { 3, 0 },
+ /* kMarsMaze188 */ { 2, 0 },
+ /* kMarsMaze189 */ { 1, 0 },
+ /* kMarsMaze190 */ { 1, 1 },
+ /* kMarsMaze191 */ { 1, 2 },
+ /* kMarsMaze192 */ { 5, 2 },
+ /* kMarsMaze193 */ { 4, 2 },
+ /* kMarsMaze194 */ { 3, 2 },
+ /* kMarsMaze195 */ { 3, 1 },
+ /* kMarsMaze198 */ { 1, 3 },
+ /* kMarsMaze199 */ { 1, 4 },
+ /* kMarsMaze200 */ { 0, 4 }
+};
+
+MapImage::MapImage() : DisplayElement(kNoDisplayElement) {
+ _whichArea = kMapNoArea;
+ setBounds(kAIMiddleAreaLeft, kAIMiddleAreaTop, kAIMiddleAreaLeft + kAIMiddleAreaWidth, kAIMiddleAreaTop + kAIMiddleAreaHeight);
+ setDisplayOrder(kAIMiddleAreaOrder + 10);
+ startDisplaying();
+
+ _darkGreen = g_system->getScreenFormat().RGBToColor(64, 150, 10);
+ _lightGreen = g_system->getScreenFormat().RGBToColor(102, 239, 0);
+}
+
+void MapImage::writeToStream(Common::WriteStream *stream) {
+ _mappedRooms.writeToStream(stream);
+}
+
+void MapImage::readFromStream(Common::ReadStream *stream) {
+ _mappedRooms.readFromStream(stream);
+}
+
+void MapImage::loadGearRoomIfNecessary() {
+ if (_whichArea != kMapGearRoom) {
+ _mapImage.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kMapOfGearRoomPICTID);
+
+ Common::Rect bounds;
+ _mapImage.getSurfaceBounds(bounds);
+ _mapMask.allocateSurface(bounds);
+ _whichArea = kMapGearRoom;
+
+ GraphicsManager *gfx = ((PegasusEngine *)g_engine)->_gfx;
+ gfx->setCurSurface(_mapMask.getSurface());
+
+ gfx->getCurSurface()->fillRect(bounds, g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
+
+ for (int i = kGearRoomFlagLow; i <= kGearRoomFlagHigh; i++)
+ if (_mappedRooms.getFlag(i))
+ addFlagToMask(i);
+
+ gfx->setCurSurface(gfx->getWorkArea());
+ show();
+ }
+}
+
+void MapImage::loadMazeIfNecessary() {
+ if (_whichArea != kMapMaze) {
+ _mapImage.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kMapOfMazePICTID);
+
+ Common::Rect bounds;
+ _mapImage.getSurfaceBounds(bounds);
+ _mapMask.allocateSurface(bounds);
+ _whichArea = kMapMaze;
+
+ GraphicsManager *gfx = ((PegasusEngine *)g_engine)->_gfx;
+ gfx->setCurSurface(_mapMask.getSurface());
+
+ gfx->getCurSurface()->fillRect(bounds, g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
+
+ for (int i = kMazeFlagLow; i <= kMazeFlagHigh; i++)
+ if (_mappedRooms.getFlag(i))
+ addFlagToMask(i);
+
+ gfx->setCurSurface(gfx->getWorkArea());
+ show();
+ }
+}
+
+void MapImage::unloadImage() {
+ _mapImage.deallocateSurface();
+ _mapMask.deallocateSurface();
+ hide();
+ _whichArea = kMapNoArea;
+}
+
+void MapImage::moveToMapLocation(const NeighborhoodID, const RoomID room, const DirectionConstant dir) {
+ GraphicsManager *gfx = ((PegasusEngine *)g_engine)->_gfx;
+
+ int flag = ROOM_TO_FLAG(room, dir);
+
+ if (!_mappedRooms.getFlag(flag)) {
+ _mappedRooms.setFlag(flag, true);
+
+ if (_mapMask.isSurfaceValid()) {
+ gfx->setCurSurface(_mapMask.getSurface());
+ addFlagToMask(flag);
+ gfx->setCurSurface(gfx->getWorkArea());
+ }
+ }
+
+ if (isDisplaying())
+ triggerRedraw();
+}
+
+void MapImage::addFlagToMask(const int flag) {
+ Common::Rect r1;
+ getRevealedRects(flag, r1);
+ ((PegasusEngine *)g_engine)->_gfx->getCurSurface()->fillRect(r1, g_system->getScreenFormat().RGBToColor(0, 0, 0));
+}
+
+// This function can even be sensitive to open doors.
+// clone2727 notices that it's not, though
+void MapImage::getRevealedRects(const uint32 flag, Common::Rect &r1) {
+ CoordType gridX, gridY;
+
+ switch (_whichArea) {
+ case kMapMaze:
+ gridX = kMazeGridOriginX;
+ gridY = kMazeGridOriginY;
+ break;
+ case kMapGearRoom:
+ gridX = kGearRoomGridOriginX;
+ gridY = kGearRoomGridOriginY;
+ break;
+ default:
+ return;
+ }
+
+ int index = FLAG_TO_INDEX(flag);
+ gridX += s_mapCoords[index][0] * kGridWidth;
+ gridY += s_mapCoords[index][1] * kGridHeight;
+
+ r1 = Common::Rect(gridX - 1, gridY - 1, gridX + kGridWidth + 1, gridY + kGridHeight + 1);
+}
+
+void MapImage::drawPlayer() {
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface();
+
+ CoordType gridX, gridY;
+
+ switch (_whichArea) {
+ case kMapMaze:
+ gridX = _bounds.left + kMazeScreenOffsetX + kMazeGridOriginX;
+ gridY = _bounds.top + kMazeScreenOffsetY + kMazeGridOriginY;
+ break;
+ case kMapGearRoom:
+ gridX = _bounds.left + kGearRoomScreenOffsetX + kGearRoomGridOriginX;
+ gridY = _bounds.top + kGearRoomScreenOffsetY + kGearRoomGridOriginY;
+ break;
+ default:
+ return;
+ }
+
+ int index = ROOM_TO_INDEX(GameState.getCurrentRoom());
+ gridX += s_mapCoords[index][0] * kGridWidth;
+ gridY += s_mapCoords[index][1] * kGridHeight;
+
+ // This was intended to make little arrows
+ switch (GameState.getCurrentDirection()) {
+ case kNorth:
+ screen->drawLine(gridX + 1, gridY, gridX + 2, gridY, _darkGreen);
+ screen->drawLine(gridX, gridY + 1, gridX + 3, gridY + 1, _darkGreen);
+ screen->drawLine(gridX + 1, gridY + 1, gridX + 2, gridY + 1, _lightGreen);
+ screen->drawLine(gridX, gridY + 2, gridX + 3, gridY + 2, _lightGreen);
+ break;
+ case kSouth:
+ screen->drawLine(gridX + 1, gridY + 3, gridX + 2, gridY + 3, _darkGreen);
+ screen->drawLine(gridX, gridY + 2, gridX + 3, gridY + 2, _darkGreen);
+ screen->drawLine(gridX + 1, gridY + 2, gridX + 2, gridY + 2, _lightGreen);
+ screen->drawLine(gridX, gridY + 1, gridX + 3, gridY + 1, _lightGreen);
+ break;
+ case kEast:
+ screen->drawLine(gridX + 3, gridY + 1, gridX + 3, gridY + 2, _darkGreen);
+ screen->drawLine(gridX + 2, gridY, gridX + 2, gridY + 3, _darkGreen);
+ screen->drawLine(gridX + 2, gridY + 1, gridX + 2, gridY + 2, _lightGreen);
+ screen->drawLine(gridX + 1, gridY, gridX + 1, gridY + 3, _lightGreen);
+ break;
+ case kWest:
+ screen->drawLine(gridX, gridY + 1, gridX, gridY + 2, _darkGreen);
+ screen->drawLine(gridX + 1, gridY, gridX + 1, gridY + 3, _darkGreen);
+ screen->drawLine(gridX + 1, gridY + 1, gridX + 1, gridY + 2, _lightGreen);
+ screen->drawLine(gridX + 2, gridY, gridX + 2, gridY + 3, _lightGreen);
+ break;
+ }
+}
+
+void MapImage::draw(const Common::Rect &) {
+ Common::Rect r1;
+ _mapImage.getSurfaceBounds(r1);
+
+ Common::Rect r2 = r1;
+ switch (_whichArea) {
+ case kMapMaze:
+ r2.moveTo(_bounds.left + kMazeScreenOffsetX, _bounds.top + kMazeScreenOffsetY);
+ break;
+ case kMapGearRoom:
+ r2.moveTo(_bounds.left + kGearRoomScreenOffsetX, _bounds.top + kGearRoomScreenOffsetY);
+ break;
+ default:
+ return;
+ }
+
+ _mapImage.copyToCurrentPortMasked(r1, r2, &_mapMask);
+
+ drawPlayer();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/mapimage.h b/engines/pegasus/items/biochips/mapimage.h
new file mode 100644
index 0000000000..49ad9945ee
--- /dev/null
+++ b/engines/pegasus/items/biochips/mapimage.h
@@ -0,0 +1,84 @@
+/* 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_ITEMS_BIOCHIPS_MAPIMAGE_H
+#define PEGASUS_ITEMS_BIOCHIPS_MAPIMAGE_H
+
+#include "pegasus/elements.h"
+#include "pegasus/surface.h"
+#include "pegasus/util.h"
+#include "pegasus/neighborhood/mars/constants.h"
+
+namespace Common {
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+class MapImage : public DisplayElement {
+public:
+ MapImage();
+ virtual ~MapImage() {}
+
+ void writeToStream(Common::WriteStream *);
+ void readFromStream(Common::ReadStream *);
+
+ void loadGearRoomIfNecessary();
+ void loadMazeIfNecessary();
+ void unloadImage();
+ void moveToMapLocation(const NeighborhoodID, const RoomID, const DirectionConstant);
+
+ void draw(const Common::Rect &);
+
+ bool anyFlagSet() { return _mappedRooms.anyFlagSet(); }
+
+ static const uint32 kNumMappingRooms = (kMars39 - kMars35 + 1) + (kMars60 - kMars60 + 1) +
+ (kMarsMaze200 - kMarsMaze004 + 1);
+ static const uint32 kNumMappingFlags = kNumMappingRooms * 4;
+
+protected:
+ enum MapArea {
+ kMapNoArea,
+ kMapMaze,
+ kMapGearRoom
+ };
+
+ void addFlagToMask(const int flag);
+ void getRevealedRects(const uint32, Common::Rect &);
+ void drawPlayer();
+
+ MapArea _whichArea;
+
+ FlagsArray<byte, kNumMappingFlags> _mappedRooms;
+
+ uint32 _darkGreen, _lightGreen;
+
+ Surface _mapImage, _mapMask;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/opticalchip.cpp b/engines/pegasus/items/biochips/opticalchip.cpp
new file mode 100644
index 0000000000..7b8858edae
--- /dev/null
+++ b/engines/pegasus/items/biochips/opticalchip.cpp
@@ -0,0 +1,190 @@
+/* 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/ai/ai_area.h"
+#include "pegasus/items/biochips/opticalchip.h"
+
+namespace Pegasus {
+
+OpticalChip *g_opticalChip = 0;
+
+OpticalChip::OpticalChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction), _ariesHotspot(kAriesSpotID), _mercuryHotspot(kMercurySpotID),
+ _poseidonHotspot(kPoseidonSpotID) {
+ _ariesHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 60, kAIMiddleAreaTop + 27, kAIMiddleAreaLeft + 60 + 121, kAIMiddleAreaTop + 27 + 20));
+ _ariesHotspot.setHotspotFlags(kOpticalBiochipSpotFlag);
+ g_allHotspots.push_back(&_ariesHotspot);
+
+ _mercuryHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 60, kAIMiddleAreaTop + 47, kAIMiddleAreaLeft + 60 + 121, kAIMiddleAreaTop + 47 + 20));
+ _mercuryHotspot.setHotspotFlags(kOpticalBiochipSpotFlag);
+ g_allHotspots.push_back(&_mercuryHotspot);
+
+ _poseidonHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 60, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 60 + 121, kAIMiddleAreaTop + 67 + 20));
+ _poseidonHotspot.setHotspotFlags(kOpticalBiochipSpotFlag);
+ g_allHotspots.push_back(&_poseidonHotspot);
+
+ setItemState(kOptical000);
+
+ g_opticalChip = this;
+}
+
+OpticalChip::~OpticalChip() {
+ g_allHotspots.removeOneHotspot(kAriesSpotID);
+ g_allHotspots.removeOneHotspot(kMercurySpotID);
+ g_allHotspots.removeOneHotspot(kPoseidonSpotID);
+}
+
+void OpticalChip::writeToStream(Common::WriteStream *stream) {
+ BiochipItem::writeToStream(stream);
+ _opticalFlags.writeToStream(stream);
+}
+
+void OpticalChip::readFromStream(Common::ReadStream *stream) {
+ BiochipItem::readFromStream(stream);
+ _opticalFlags.readFromStream(stream);
+}
+
+void OpticalChip::addAries() {
+ _opticalFlags.setFlag(kOpticalAriesExposed, true);
+ setUpOpticalChip();
+}
+
+void OpticalChip::addMercury() {
+ _opticalFlags.setFlag(kOpticalMercuryExposed, true);
+ setUpOpticalChip();
+}
+
+void OpticalChip::addPoseidon() {
+ _opticalFlags.setFlag(kOpticalPoseidonExposed, true);
+ setUpOpticalChip();
+}
+
+void OpticalChip::setUpOpticalChip() {
+ if (_opticalFlags.getFlag(kOpticalAriesExposed)) {
+ if (_opticalFlags.getFlag(kOpticalMercuryExposed)) {
+ if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
+ setItemState(kOptical111);
+ else
+ setItemState(kOptical011);
+ } else {
+ if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
+ setItemState(kOptical101);
+ else
+ setItemState(kOptical001);
+ }
+ } else {
+ if (_opticalFlags.getFlag(kOpticalMercuryExposed)) {
+ if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
+ setItemState(kOptical110);
+ else
+ setItemState(kOptical010);
+ } else {
+ if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
+ setItemState(kOptical100);
+ else
+ setItemState(kOptical000);
+ }
+ }
+}
+
+void OpticalChip::activateOpticalHotspots() {
+ if (_opticalFlags.getFlag(kOpticalAriesExposed))
+ _ariesHotspot.setActive();
+ if (_opticalFlags.getFlag(kOpticalMercuryExposed))
+ _mercuryHotspot.setActive();
+ if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
+ _poseidonHotspot.setActive();
+}
+
+void OpticalChip::clickInOpticalHotspot(HotSpotID id) {
+ playOpMemMovie(id);
+}
+
+void OpticalChip::playOpMemMovie(HotSpotID id) {
+ Common::String movieName;
+ switch (id) {
+ case kAriesSpotID:
+ movieName = "Images/AI/Globals/OMAI";
+ break;
+ case kMercurySpotID:
+ movieName = "Images/AI/Globals/OMMI";
+ break;
+ case kPoseidonSpotID:
+ movieName = "Images/AI/Globals/OMPI";
+ break;
+ }
+
+ ItemState state = getItemState(), newState;
+ switch (state) {
+ case kOptical001:
+ newState = kOptical002;
+ break;
+ case kOptical010:
+ newState = kOptical020;
+ break;
+ case kOptical011:
+ if (id == kAriesSpotID)
+ newState = kOptical012;
+ else
+ newState = kOptical021;
+ break;
+ case kOptical100:
+ newState = kOptical200;
+ break;
+ case kOptical101:
+ if (id == kAriesSpotID)
+ newState = kOptical102;
+ else
+ newState = kOptical201;
+ break;
+ case kOptical110:
+ if (id == kMercurySpotID)
+ newState = kOptical120;
+ else
+ newState = kOptical210;
+ break;
+ case kOptical111:
+ if (id == kAriesSpotID)
+ newState = kOptical112;
+ else if (id == kMercurySpotID)
+ newState = kOptical121;
+ else
+ newState = kOptical211;
+ break;
+ case kOptical000: // Can never happen.
+ default:
+ error("Invalid optical chip state");
+ }
+
+ setItemState(newState);
+
+ if (g_AIArea)
+ g_AIArea->playAIMovie(kRightAreaSignature, movieName, false, kOpticalInterruption);
+
+ setItemState(state);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/opticalchip.h b/engines/pegasus/items/biochips/opticalchip.h
new file mode 100644
index 0000000000..2f66f73d3a
--- /dev/null
+++ b/engines/pegasus/items/biochips/opticalchip.h
@@ -0,0 +1,71 @@
+/* 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_ITEMS_BIOCHIPS_OPTICALCHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_OPTICALCHIP_H
+
+#include "pegasus/hotspot.h"
+#include "pegasus/util.h"
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+class OpticalChip : public BiochipItem {
+public:
+ OpticalChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~OpticalChip();
+
+ virtual void writeToStream(Common::WriteStream *);
+ virtual void readFromStream(Common::ReadStream *);
+
+ void addAries();
+ void addMercury();
+ void addPoseidon();
+
+ void activateOpticalHotspots();
+ void clickInOpticalHotspot(HotSpotID);
+ void playOpMemMovie(HotSpotID);
+
+protected:
+ enum {
+ kOpticalAriesExposed,
+ kOpticalMercuryExposed,
+ kOpticalPoseidonExposed,
+ kNumOpticalChipFlags
+ };
+
+ void setUpOpticalChip();
+
+ FlagsArray<byte, kNumOpticalChipFlags> _opticalFlags;
+ Hotspot _ariesHotspot;
+ Hotspot _mercuryHotspot;
+ Hotspot _poseidonHotspot;
+};
+
+extern OpticalChip *g_opticalChip;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/pegasuschip.cpp b/engines/pegasus/items/biochips/pegasuschip.cpp
new file mode 100644
index 0000000000..fa551fce30
--- /dev/null
+++ b/engines/pegasus/items/biochips/pegasuschip.cpp
@@ -0,0 +1,198 @@
+/* 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/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/items/biochips/pegasuschip.h"
+#include "pegasus/neighborhood/tsa/fulltsa.h"
+#include "pegasus/neighborhood/tsa/tinytsa.h"
+
+namespace Pegasus {
+
+PegasusChip::PegasusChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction), _recallSpot(kPegasusRecallSpotID) {
+ _recallSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 116, kAIMiddleAreaTop + 63, kAIMiddleAreaLeft + 184, kAIMiddleAreaTop + 91));
+ _recallSpot.setHotspotFlags(kPegasusBiochipSpotFlag);
+ g_allHotspots.push_back(&_recallSpot);
+ setItemState(kPegasusTSA00);
+}
+
+PegasusChip::~PegasusChip() {
+ g_allHotspots.removeOneHotspot(kPegasusRecallSpotID);
+}
+
+void PegasusChip::select() {
+ BiochipItem::select();
+ setUpPegasusChip();
+}
+
+void PegasusChip::setUpPegasusChip() {
+ switch (GameState.getCurrentNeighborhood()) {
+ case kCaldoriaID:
+ setItemState(kPegasusCaldoria);
+ break;
+ case kFullTSAID:
+ case kFinalTSAID:
+ case kTinyTSAID:
+ setItemState(kPegasusTSA10);
+ break;
+ case kPrehistoricID:
+ if (((PegasusEngine *)g_engine)->playerHasItemID(kHistoricalLog))
+ setItemState(kPegasusPrehistoric00);
+ else
+ setItemState(kPegasusPrehistoric10);
+ break;
+ case kMarsID:
+ if (GameState.getMarsFinished())
+ setItemState(kPegasusMars00);
+ else
+ setItemState(kPegasusMars10);
+ break;
+ case kWSCID:
+ if (GameState.getWSCFinished())
+ setItemState(kPegasusWSC00);
+ else
+ setItemState(kPegasusWSC10);
+ break;
+ case kNoradAlphaID:
+ case kNoradDeltaID:
+ if (GameState.getNoradFinished())
+ setItemState(kPegasusNorad00);
+ else
+ setItemState(kPegasusNorad10);
+ break;
+ }
+}
+
+// Only does something if the chip should be announcing that the time zone is finished...
+void PegasusChip::setUpPegasusChipRude() {
+ switch (GameState.getCurrentNeighborhood()) {
+ case kPrehistoricID:
+ if (((PegasusEngine *)g_engine)->playerHasItemID(kHistoricalLog))
+ setItemState(kPegasusPrehistoric00);
+ break;
+ case kMarsID:
+ if (GameState.getMarsFinished())
+ setItemState(kPegasusMars00);
+ break;
+ case kWSCID:
+ if (GameState.getWSCFinished())
+ setItemState(kPegasusWSC00);
+ break;
+ case kNoradAlphaID:
+ case kNoradDeltaID:
+ if (GameState.getNoradFinished())
+ setItemState(kPegasusNorad00);
+ break;
+ }
+}
+
+void PegasusChip::activatePegasusHotspots() {
+ switch (GameState.getCurrentNeighborhood()) {
+ case kPrehistoricID:
+ // WORKAROUND: Don't allow the player to recall if they don't have
+ // the historical log. Otherwise, gameplay is broken when returning
+ // to the TSA.
+ if (!((PegasusEngine *)g_engine)->playerHasItemID(kHistoricalLog))
+ return;
+ // fall through
+ case kMarsID:
+ case kWSCID:
+ case kNoradAlphaID:
+ case kNoradDeltaID:
+ _recallSpot.setActive();
+ break;
+ }
+}
+
+void PegasusChip::clickInPegasusHotspot() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ ItemState thisState = getItemState();
+ ItemState hiliteState;
+
+ switch (thisState) {
+ case kPegasusPrehistoric00:
+ hiliteState = kPegasusPrehistoric01;
+ break;
+ case kPegasusPrehistoric10:
+ hiliteState = kPegasusPrehistoric11;
+ break;
+ case kPegasusMars00:
+ hiliteState = kPegasusMars01;
+ break;
+ case kPegasusMars10:
+ hiliteState = kPegasusMars11;
+ break;
+ case kPegasusNorad00:
+ hiliteState = kPegasusNorad01;
+ break;
+ case kPegasusNorad10:
+ hiliteState = kPegasusNorad11;
+ break;
+ case kPegasusWSC00:
+ hiliteState = kPegasusWSC01;
+ break;
+ case kPegasusWSC10:
+ hiliteState = kPegasusWSC11;
+ break;
+ default:
+ error("Invalid pegasus chip state");
+ }
+
+ // WORKAROUND: The original called setItemState() here. However,
+ // since we're overriding select() to call setUpPegasusChip(),
+ // the highlighted frame is never displayed! So, we're manually
+ // setting the state and selecting the item. Also of note is that
+ // setItemState() for this class is effectively useless since it
+ // always gets overriden in the select() function. The only reason
+ // that this doesn't end in infinite recursion is because setItemState()
+ // has a check against the current state to make sure you don't call
+ // select() again. </rant>
+ _itemState = hiliteState;
+ BiochipItem::select();
+
+ uint32 time = g_system->getMillis();
+ while (g_system->getMillis() < time + 500) {
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ setItemState(thisState);
+
+ if (!((Neighborhood *)g_neighborhood)->okayToJump())
+ return;
+
+ if (g_energyMonitor)
+ g_energyMonitor->stopEnergyDraining();
+
+ if (GameState.getTSAState() == kPlayerWentToPrehistoric || GameState.allTimeZonesFinished())
+ vm->jumpToNewEnvironment(kFullTSAID, kTSA37, kNorth);
+ else
+ vm->jumpToNewEnvironment(kTinyTSAID, kTinyTSA37, kNorth);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/pegasuschip.h b/engines/pegasus/items/biochips/pegasuschip.h
new file mode 100644
index 0000000000..7597424821
--- /dev/null
+++ b/engines/pegasus/items/biochips/pegasuschip.h
@@ -0,0 +1,55 @@
+/* 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_ITEMS_BIOCHIPS_PEGASUSCHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_PEGASUSCHIP_H
+
+#include "pegasus/hotspot.h"
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+class PegasusChip : public BiochipItem {
+public:
+ PegasusChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~PegasusChip();
+
+ void select();
+
+ void setUpPegasusChip();
+
+ // Called to set up the Pegasus chip when the Pegasus chip is the current chip but does not
+ // own the center area.
+ void setUpPegasusChipRude();
+ void activatePegasusHotspots();
+ void clickInPegasusHotspot();
+
+protected:
+ Hotspot _recallSpot;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/retscanchip.cpp b/engines/pegasus/items/biochips/retscanchip.cpp
new file mode 100644
index 0000000000..84b74a63d2
--- /dev/null
+++ b/engines/pegasus/items/biochips/retscanchip.cpp
@@ -0,0 +1,49 @@
+/* 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/ai/ai_area.h"
+#include "pegasus/items/biochips/retscanchip.h"
+
+namespace Pegasus {
+
+RetScanChip::RetScanChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction) {
+}
+
+void RetScanChip::searchForLaser() {
+ ItemExtraEntry entry;
+ findItemExtra(kRetinalScanSearching, entry);
+
+ if (g_AIArea)
+ g_AIArea->playAIAreaSequence(kBiochipSignature, kMiddleAreaSignature, entry.extraStart, entry.extraStop);
+
+ findItemExtra(kRetinalScanActivated, entry);
+ if (g_AIArea)
+ g_AIArea->playAIAreaSequence(kBiochipSignature, kRightAreaSignature, entry.extraStart, entry.extraStop);
+
+ setItemState(kRetinalSimulating);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/retscanchip.h b/engines/pegasus/items/biochips/retscanchip.h
new file mode 100644
index 0000000000..153e6cd071
--- /dev/null
+++ b/engines/pegasus/items/biochips/retscanchip.h
@@ -0,0 +1,43 @@
+/* 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_ITEMS_BIOCHIPS_RETSCANCHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_RETSCANCHIP_H
+
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+class RetScanChip : public BiochipItem {
+public:
+ RetScanChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~RetScanChip() {}
+
+ void searchForLaser();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/shieldchip.cpp b/engines/pegasus/items/biochips/shieldchip.cpp
new file mode 100644
index 0000000000..58cbfcc4ec
--- /dev/null
+++ b/engines/pegasus/items/biochips/shieldchip.cpp
@@ -0,0 +1,53 @@
+/* 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/items/biochips/shieldchip.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+ShieldChip *g_shield = 0;
+
+ShieldChip::ShieldChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction) {
+ g_shield = this;
+}
+
+void ShieldChip::select() {
+ BiochipItem::select();
+ GameState.setShieldOn(true);
+ if (g_neighborhood)
+ g_neighborhood->shieldOn();
+}
+
+void ShieldChip::deselect() {
+ BiochipItem::deselect();
+ GameState.setShieldOn(false);
+ if (g_neighborhood)
+ g_neighborhood->shieldOff();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/shieldchip.h b/engines/pegasus/items/biochips/shieldchip.h
new file mode 100644
index 0000000000..69c6369236
--- /dev/null
+++ b/engines/pegasus/items/biochips/shieldchip.h
@@ -0,0 +1,46 @@
+/* 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_ITEMS_BIOCHIPS_SHIELDCHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_SHIELDCHIP_H
+
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+class ShieldChip : public BiochipItem {
+public:
+ ShieldChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~ShieldChip() {}
+
+ void select();
+ void deselect();
+};
+
+extern ShieldChip *g_shield;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventory.cpp b/engines/pegasus/items/inventory.cpp
new file mode 100644
index 0000000000..57923b105d
--- /dev/null
+++ b/engines/pegasus/items/inventory.cpp
@@ -0,0 +1,175 @@
+/* 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/constants.h"
+#include "pegasus/items/item.h"
+#include "pegasus/items/inventory.h"
+
+namespace Pegasus {
+
+Inventory::Inventory() {
+ _weightLimit = 100;
+ _ownerID = kNoActorID;
+ _referenceCount = 0;
+}
+
+Inventory::~Inventory() {
+}
+
+void Inventory::setWeightLimit(WeightType limit) {
+ _weightLimit = limit;
+ // *** What to do if the new weight limit is greater than the current weight?
+}
+
+WeightType Inventory::getWeight() {
+ WeightType result = 0;
+
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++)
+ result += (*it)->getItemWeight();
+
+ return result;
+}
+
+// If the item already belongs, just return kInventoryOK.
+InventoryResult Inventory::addItem(Item *item) {
+ if (itemInInventory(item))
+ return kInventoryOK;
+
+ if (getWeight() + item->getItemWeight() > _weightLimit)
+ return kTooMuchWeight;
+
+ _inventoryList.push_back(item);
+ item->setItemOwner(_ownerID);
+
+ ++_referenceCount;
+ return kInventoryOK;
+}
+
+InventoryResult Inventory::removeItem(Item *item) {
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++) {
+ if (*it == item) {
+ _inventoryList.erase(it);
+ item->setItemOwner(kNoActorID);
+
+ ++_referenceCount;
+ return kInventoryOK;
+ }
+ }
+
+ return kItemNotInInventory;
+}
+
+InventoryResult Inventory::removeItem(ItemID id) {
+ Item *item = findItemByID(id);
+
+ if (item) {
+ _inventoryList.remove(item);
+ item->setItemOwner(kNoActorID);
+
+ ++_referenceCount;
+ return kInventoryOK;
+ }
+
+ return kItemNotInInventory;
+}
+
+void Inventory::removeAllItems() {
+ _inventoryList.clear();
+ ++_referenceCount;
+}
+
+bool Inventory::itemInInventory(Item *item) {
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++)
+ if (*it == item)
+ return true;
+
+ return false;
+}
+
+bool Inventory::itemInInventory(ItemID id) {
+ return findItemByID(id) != NULL;
+}
+
+Item *Inventory::getItemAt(int32 index) {
+ int32 i = 0;
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++, i++)
+ if (i == index)
+ return *it;
+
+ return 0;
+}
+
+ItemID Inventory::getItemIDAt(int32 index) {
+ Item *item = getItemAt(index);
+
+ if (item)
+ return item->getObjectID();
+
+ return kNoItemID;
+}
+
+Item *Inventory::findItemByID(ItemID id) {
+ return _inventoryList.findItemByID(id);
+}
+
+// Return -1 if not found.
+
+int32 Inventory::findIndexOf(Item *item) {
+ uint32 i = 0;
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++, i++)
+ if (*it == item)
+ return i;
+
+ return -1;
+}
+
+// Return -1 if not found.
+
+int32 Inventory::findIndexOf(ItemID id) {
+ uint32 i = 0;
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++, i++)
+ if ((*it)->getObjectID() == id)
+ return i;
+
+ return -1;
+}
+
+WeightType Inventory::getWeightLimit() {
+ return _weightLimit;
+}
+
+int32 Inventory::getNumItems() {
+ return _inventoryList.size();
+}
+
+void Inventory::setOwnerID(const ActorID id) {
+ _ownerID = id;
+}
+
+ActorID Inventory::getOwnerID() const {
+ return _ownerID;
+}
+
+} // End of namespae Pegasus
diff --git a/engines/pegasus/items/inventory.h b/engines/pegasus/items/inventory.h
new file mode 100644
index 0000000000..796ec49556
--- /dev/null
+++ b/engines/pegasus/items/inventory.h
@@ -0,0 +1,80 @@
+/* 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_ITEMS_INVENTORY_H
+#define PEGASUS_ITEMS_INVENTORY_H
+
+#include "pegasus/types.h"
+#include "pegasus/items/itemlist.h"
+
+namespace Pegasus {
+
+class Item;
+
+// Inventories have a "current item". This item is the default item the player can
+// use. In a text adventure system, the current item would be "it", as in
+// "Hit the troll with it," where "it" would refer to some weapon which is the current
+// item. In a graphic adventure, the current item would be the item the user selects
+// to use with the mouse or other pointing device.
+
+class Inventory {
+public:
+ Inventory();
+ virtual ~Inventory();
+
+ WeightType getWeightLimit();
+ void setWeightLimit(WeightType limit);
+ WeightType getWeight();
+
+ virtual InventoryResult addItem(Item *item);
+ virtual InventoryResult removeItem(Item *item);
+ virtual InventoryResult removeItem(ItemID id);
+ virtual bool itemInInventory(Item *item);
+ virtual bool itemInInventory(ItemID id);
+ virtual Item *getItemAt(int32 index);
+ virtual ItemID getItemIDAt(int32 index);
+ virtual Item *findItemByID(ItemID id);
+ virtual int32 findIndexOf(Item *item);
+ virtual int32 findIndexOf(ItemID id);
+ int32 getNumItems();
+ virtual void removeAllItems();
+
+ void setOwnerID(const ActorID id);
+ ActorID getOwnerID() const;
+
+ uint32 getReferenceCount() { return _referenceCount; }
+
+protected:
+ WeightType _weightLimit;
+ ActorID _ownerID;
+ ItemList _inventoryList;
+
+private:
+ uint32 _referenceCount;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventory/airmask.cpp b/engines/pegasus/items/inventory/airmask.cpp
new file mode 100644
index 0000000000..c65dd36102
--- /dev/null
+++ b/engines/pegasus/items/inventory/airmask.cpp
@@ -0,0 +1,249 @@
+/* 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/ai/ai_area.h"
+#include "pegasus/items/inventory/airmask.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+AirMask *g_airMask = 0;
+
+// Based on full == 100, which is scale used by GetAirLeft().
+static const TimeValue kOxygenLowThreshold = 25;
+
+void AirMask::airMaskTimerExpired() {
+ if (g_neighborhood)
+ g_neighborhood->checkAirMask();
+}
+
+AirMask::AirMask(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ InventoryItem(id, neighborhood, room, direction), _toggleSpot(kAirMaskToggleSpotID) {
+ g_airMask = this;
+ _toggleSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 10, kAIMiddleAreaTop + 17, kAIMiddleAreaLeft + 110, kAIMiddleAreaTop + 57));
+ _toggleSpot.setHotspotFlags(kAirMaskSpotFlag);
+ g_allHotspots.push_back(&_toggleSpot);
+ setItemState(kAirMaskEmptyOff);
+ _oxygenTimer.primeFuse(0);
+ _oxygenTimer.setFunctor(new Common::Functor0Mem<void, AirMask>(this, &AirMask::airMaskTimerExpired));
+}
+
+AirMask::~AirMask() {
+ g_allHotspots.removeOneHotspot(kAirMaskToggleSpotID);
+ g_airMask = 0;
+}
+
+void AirMask::writeToStream(Common::WriteStream *stream) {
+ InventoryItem::writeToStream(stream);
+ stream->writeUint32BE(_oxygenTimer.getTimeRemaining());
+}
+
+void AirMask::readFromStream(Common::ReadStream *stream) {
+ _oxygenTimer.stopFuse();
+ InventoryItem::readFromStream(stream);
+ _oxygenTimer.primeFuse(stream->readUint32BE());
+}
+
+void AirMask::putMaskOn() {
+ AirQuality airQuality;
+
+ if (g_neighborhood)
+ airQuality = g_neighborhood->getAirQuality(GameState.getCurrentRoom());
+ else
+ airQuality = kAirQualityGood;
+
+ uint airLevel = getAirLeft();
+ ItemState newState = getItemState();
+ ItemState oldState = newState;
+
+ if (airLevel == 0) {
+ newState = kAirMaskEmptyFilter;
+ } else if (airLevel <= kOxygenLowThreshold) {
+ if (airQuality == kAirQualityVacuum)
+ newState = kAirMaskLowOn;
+ else
+ newState = kAirMaskLowFilter;
+ } else {
+ if (airQuality == kAirQualityVacuum)
+ newState = kAirMaskFullOn;
+ else
+ newState = kAirMaskFullFilter;
+ }
+
+ if (newState != oldState)
+ setItemState(newState);
+}
+
+void AirMask::takeMaskOff() {
+ uint airLevel = getAirLeft();
+ ItemState newState = getItemState();
+ ItemState oldState = newState;
+
+ if (airLevel == 0)
+ newState = kAirMaskEmptyOff;
+ else if (airLevel <= kOxygenLowThreshold)
+ newState = kAirMaskLowOff;
+ else
+ newState = kAirMaskFullOff;
+
+ if (newState != oldState)
+ setItemState(newState);
+}
+
+void AirMask::toggleItemState() {
+ if (isAirMaskInUse())
+ takeMaskOff();
+ else
+ putMaskOn();
+}
+
+void AirMask::airQualityChanged() {
+ if (isAirMaskInUse())
+ putMaskOn();
+ else
+ takeMaskOff();
+}
+
+void AirMask::setItemState(const ItemState newState) {
+ if (newState != getItemState()) {
+ InventoryItem::setItemState(newState);
+
+ switch (newState) {
+ case kAirMaskFullOn:
+ case kAirMaskLowOn:
+ if (!_oxygenTimer.isFuseLit()) {
+ _oxygenTimer.lightFuse();
+ startIdling();
+ }
+ break;
+ default:
+ if (_oxygenTimer.isFuseLit()) {
+ _oxygenTimer.stopFuse();
+ stopIdling();
+ }
+ break;
+ }
+
+ if (g_neighborhood)
+ g_neighborhood->checkAirMask();
+
+ g_AIArea->checkMiddleArea();
+ }
+}
+
+void AirMask::useIdleTime() {
+ if (getAirLeft() == 0)
+ setItemState(kAirMaskEmptyOff);
+ else if (getAirLeft() <= kOxygenLowThreshold)
+ setItemState(kAirMaskLowOn);
+}
+
+void AirMask::refillAirMask() {
+ switch (getItemState()) {
+ case kAirMaskEmptyOff:
+ case kAirMaskLowOff:
+ setItemState(kAirMaskFullOff);
+ break;
+ case kAirMaskEmptyFilter:
+ case kAirMaskLowFilter:
+ setItemState(kAirMaskFullFilter);
+ break;
+ case kAirMaskLowOn:
+ setItemState(kAirMaskFullOn);
+ break;
+ }
+
+ if (_oxygenTimer.isFuseLit()) {
+ _oxygenTimer.stopFuse();
+ _oxygenTimer.primeFuse(kOxyMaskFullTime);
+ _oxygenTimer.lightFuse();
+ } else {
+ _oxygenTimer.primeFuse(kOxyMaskFullTime);
+ }
+}
+
+// Doesn't return 0 until the timer is actually at 0.
+uint AirMask::getAirLeft() {
+ return CLIP<int>(((_oxygenTimer.getTimeRemaining() * 100) + kOxyMaskFullTime - 1) / kOxyMaskFullTime, 0, 100);
+}
+
+bool AirMask::isAirMaskInUse() {
+ switch (getItemState()) {
+ case kAirMaskEmptyOff:
+ case kAirMaskLowOff:
+ case kAirMaskFullOff:
+ return false;
+ break;
+ default:
+ return true;
+ break;
+ }
+}
+
+bool AirMask::isAirMaskOn() {
+ switch (getItemState()) {
+ case kAirMaskLowOn:
+ case kAirMaskFullOn:
+ return true;
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+bool AirMask::isAirFilterOn() {
+ switch (getItemState()) {
+ case kAirMaskEmptyFilter:
+ case kAirMaskLowFilter:
+ case kAirMaskFullFilter:
+ return true;
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+void AirMask::addedToInventory() {
+ GameState.setMarsMaskOnFiller(false);
+}
+
+void AirMask::removedFromInventory() {
+ if (isAirMaskInUse())
+ toggleItemState();
+}
+
+void AirMask::activateAirMaskHotspots() {
+ _toggleSpot.setActive();
+}
+
+void AirMask::clickInAirMaskHotspot() {
+ toggleItemState();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/inventory/airmask.h b/engines/pegasus/items/inventory/airmask.h
new file mode 100644
index 0000000000..6a2d708a6c
--- /dev/null
+++ b/engines/pegasus/items/inventory/airmask.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_ITEMS_INVENTORY_AIRMASK_H
+#define PEGASUS_ITEMS_INVENTORY_AIRMASK_H
+
+#include "pegasus/hotspot.h"
+#include "pegasus/timers.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+class AirMask : public InventoryItem, private Idler {
+public:
+ AirMask(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~AirMask();
+
+ virtual void writeToStream(Common::WriteStream *);
+ virtual void readFromStream(Common::ReadStream *);
+
+ virtual void setItemState(const ItemState);
+ void putMaskOn();
+ void takeMaskOff();
+ void toggleItemState();
+ void airQualityChanged();
+
+ bool isAirMaskInUse();
+ bool isAirMaskOn();
+ bool isAirFilterOn();
+
+ void refillAirMask();
+
+ // Returns a percentage
+ uint getAirLeft();
+
+ void activateAirMaskHotspots();
+ void clickInAirMaskHotspot();
+
+protected:
+ void airMaskTimerExpired();
+
+ virtual void removedFromInventory();
+ virtual void addedToInventory();
+ void useIdleTime();
+
+ Hotspot _toggleSpot;
+ FuseFunction _oxygenTimer;
+};
+
+extern AirMask *g_airMask;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventory/gascanister.cpp b/engines/pegasus/items/inventory/gascanister.cpp
new file mode 100644
index 0000000000..bf63cc6542
--- /dev/null
+++ b/engines/pegasus/items/inventory/gascanister.cpp
@@ -0,0 +1,46 @@
+/* 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/ai/ai_area.h"
+#include "pegasus/items/inventory/gascanister.h"
+
+namespace Pegasus {
+
+GasCanister::GasCanister(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ InventoryItem(id, neighborhood, room, direction) {
+}
+
+void GasCanister::select() {
+ InventoryItem::select();
+ takeSharedArea();
+}
+
+void GasCanister::takeSharedArea() {
+ ItemExtraEntry entry;
+ findItemExtra(kGasCanLoop, entry);
+ g_AIArea->loopAIAreaSequence(kInventorySignature, kMiddleAreaSignature, entry.extraStart, entry.extraStop);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/inventory/gascanister.h b/engines/pegasus/items/inventory/gascanister.h
new file mode 100644
index 0000000000..7d4d8193f5
--- /dev/null
+++ b/engines/pegasus/items/inventory/gascanister.h
@@ -0,0 +1,44 @@
+/* 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_ITEMS_INVENTORY_GASCANISTER_H
+#define PEGASUS_ITEMS_INVENTORY_GASCANISTER_H
+
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+class GasCanister : public InventoryItem {
+public:
+ GasCanister(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~GasCanister() {}
+
+ void select();
+ void takeSharedArea();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventory/inventoryitem.cpp b/engines/pegasus/items/inventory/inventoryitem.cpp
new file mode 100644
index 0000000000..4399708879
--- /dev/null
+++ b/engines/pegasus/items/inventory/inventoryitem.cpp
@@ -0,0 +1,110 @@
+/* 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 "common/stream.h"
+
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+InventoryItem::InventoryItem(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ Item(id, neighborhood, room, direction) {
+
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ Common::SeekableReadStream *leftInfo = vm->_resFork->getResource(MKTAG('L', 'e', 'f', 't'), kItemBaseResID + id);
+ if (leftInfo) {
+ _leftAreaInfo = readItemState(leftInfo);
+ delete leftInfo;
+ } else {
+ _leftAreaInfo.numEntries = 0;
+ _leftAreaInfo.entries = 0;
+ }
+
+ Common::SeekableReadStream *inventoryInfo = vm->_resFork->getResource(MKTAG('I', 'n', 'v', 'I'), kItemBaseResID + id);
+ if (inventoryInfo) {
+ _inventoryInfo.panelStart = inventoryInfo->readUint32BE();
+ _inventoryInfo.panelStop = inventoryInfo->readUint32BE();
+ delete inventoryInfo;
+ } else {
+ _inventoryInfo.panelStart = _inventoryInfo.panelStop = 0;
+ }
+
+ _itemAnimationTime = 0;
+}
+
+InventoryItem::~InventoryItem() {
+ delete[] _leftAreaInfo.entries;
+}
+
+ItemType InventoryItem::getItemType() {
+ return kInventoryItemType;
+}
+
+TimeValue InventoryItem::getLeftAreaTime() const {
+ if (!_leftAreaInfo.entries)
+ return 0xffffffff;
+
+ TimeValue time;
+ ItemState state;
+
+ findItemStateEntryByState(_leftAreaInfo, _itemState, time);
+ if (time == 0xffffffff)
+ getItemStateEntry(_leftAreaInfo, 0, state, time);
+
+ return time;
+}
+
+void InventoryItem::setAnimationTime(const TimeValue time) {
+ _itemAnimationTime = time;
+}
+
+TimeValue InventoryItem::getAnimationTime() const {
+ return _itemAnimationTime;
+}
+
+// Must affect images in left area.
+void InventoryItem::select() {
+ Item::select();
+
+ if (g_AIArea)
+ g_AIArea->setAIAreaToTime(kInventorySignature, kLeftAreaSignature, getLeftAreaTime());
+}
+
+void InventoryItem::deselect() {
+ Item::deselect();
+
+ if (g_AIArea)
+ g_AIArea->setAIAreaToTime(kInventorySignature, kLeftAreaSignature, 0xffffffff);
+}
+
+void InventoryItem::getPanelTimes(TimeValue &start, TimeValue &stop) const {
+ start = _inventoryInfo.panelStart;
+ stop = _inventoryInfo.panelStop;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/inventory/inventoryitem.h b/engines/pegasus/items/inventory/inventoryitem.h
new file mode 100644
index 0000000000..9d78113014
--- /dev/null
+++ b/engines/pegasus/items/inventory/inventoryitem.h
@@ -0,0 +1,67 @@
+/* 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_ITEMS_INVENTORY_INVENTORYITEM_H
+#define PEGASUS_ITEMS_INVENTORY_INVENTORYITEM_H
+
+#include "pegasus/items/item.h"
+
+namespace Pegasus {
+
+// JMPInventoryInfo contains the resource data used by InventoryItems.
+
+struct JMPInventoryInfo {
+ TimeValue panelStart;
+ TimeValue panelStop;
+};
+
+class InventoryItem : public Item {
+public:
+ InventoryItem(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~InventoryItem();
+
+ virtual ItemType getItemType();
+
+ void getPanelTimes(TimeValue &, TimeValue &) const;
+ TimeValue getLeftAreaTime() const;
+
+ void setAnimationTime(const TimeValue);
+ TimeValue getAnimationTime() const;
+
+ virtual void toggleItemState() {}
+
+ // Must affect images in left area.
+ virtual void select();
+ virtual void deselect();
+
+protected:
+ JMPInventoryInfo _inventoryInfo;
+ ItemStateInfo _leftAreaInfo;
+ TimeValue _itemAnimationTime;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventory/keycard.cpp b/engines/pegasus/items/inventory/keycard.cpp
new file mode 100644
index 0000000000..c818b6675b
--- /dev/null
+++ b/engines/pegasus/items/inventory/keycard.cpp
@@ -0,0 +1,59 @@
+/* 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/items/inventory/keycard.h"
+
+namespace Pegasus {
+
+KeyCard::KeyCard(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ InventoryItem(id, neighborhood, room, direction) {
+ setItemState(kFlashlightOff);
+}
+
+void KeyCard::toggleItemState() {
+ if (getItemState() == kFlashlightOff)
+ setItemState(kFlashlightOn);
+ else
+ setItemState(kFlashlightOff);
+}
+
+void KeyCard::setItemState(const ItemState newState) {
+ if (newState != getItemState()) {
+ InventoryItem::setItemState(newState);
+ ((PegasusEngine *)g_engine)->checkFlashlight();
+ }
+}
+
+bool KeyCard::isFlashlightOn() {
+ return getItemState() == kFlashlightOn;
+}
+
+void KeyCard::removedFromInventory() {
+ if (isFlashlightOn())
+ setItemState(kFlashlightOff);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/inventory/keycard.h b/engines/pegasus/items/inventory/keycard.h
new file mode 100644
index 0000000000..846f40e6e5
--- /dev/null
+++ b/engines/pegasus/items/inventory/keycard.h
@@ -0,0 +1,48 @@
+/* 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_ITEMS_INVENTORY_KEYCARD_H
+#define PEGASUS_ITEMS_INVENTORY_KEYCARD_H
+
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+class KeyCard : public InventoryItem {
+public:
+ KeyCard(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~KeyCard() {}
+
+ virtual void toggleItemState();
+ virtual void setItemState(const ItemState);
+ bool isFlashlightOn();
+
+protected:
+ virtual void removedFromInventory();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventorypicture.cpp b/engines/pegasus/items/inventorypicture.cpp
new file mode 100644
index 0000000000..fc812faae2
--- /dev/null
+++ b/engines/pegasus/items/inventorypicture.cpp
@@ -0,0 +1,370 @@
+/* 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/transition.h"
+#include "pegasus/items/inventorypicture.h"
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+InventoryPicture::InventoryPicture(const DisplayElementID id, InputHandler *nextHandler, Inventory *inventory) :
+ InputHandler(nextHandler), Picture(id), _panelMovie(kNoDisplayElement){
+ _inventory = inventory;
+ _lastReferenceCount = 0xffffffff;
+
+ if (_inventory->getNumItems() > 0) {
+ _currentItemIndex = 0;
+ _currentItem = (Item *)_inventory->getItemAt(0);
+ } else {
+ _currentItemIndex = -1;
+ _currentItem = 0;
+ }
+
+ _active = false;
+ _shouldDrawHighlight = true;
+ _itemsPerRow = 1;
+ _numberOfRows = 1;
+ _itemWidth = 0;
+ _itemHeight = 0;
+ _itemX = 0;
+ _itemY = 0;
+}
+
+void InventoryPicture::initInventoryImage(Transition *transition) {
+ initFromPICTFile(_pictName, true);
+ _panelMovie.shareSurface(this);
+ _panelMovie.initFromMovieFile(_movieName);
+ _panelMovie.getBounds(_highlightBounds);
+ _panelMovie.setTriggeredElement(transition);
+ _highlightImage.initFromPICTFile(_highlightName, true);
+}
+
+void InventoryPicture::throwAwayInventoryImage() {
+ if (isSurfaceValid()) {
+ _panelMovie.releaseMovie();
+ _highlightImage.deallocateSurface();
+ deallocateSurface();
+ }
+}
+
+void InventoryPicture::getItemXY(uint32 index, CoordType &x, CoordType &y) {
+ x = (index % _itemsPerRow) * _itemWidth + _itemX;
+ y = (index / _itemsPerRow) * _itemHeight + _itemY;
+}
+
+void InventoryPicture::drawItemHighlight(const Common::Rect &r) {
+ if (_highlightImage.isSurfaceValid()) {
+ Common::Rect r2 = _highlightBounds;
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ r2.translate(bounds.left, bounds.top);
+ r2 = r2.findIntersectingRect(r);
+ if (!r2.isEmpty()) {
+ Common::Rect r1 = r2;
+ r1.translate(-bounds.left - _highlightBounds.left, -bounds.top - _highlightBounds.top);
+ _highlightImage.drawImage(r1, r2);
+ }
+ }
+}
+
+void InventoryPicture::draw(const Common::Rect &r) {
+ Picture::draw(r);
+ if (_inventory->getNumItems() != 0 && _shouldDrawHighlight)
+ drawItemHighlight(r);
+}
+
+// Assumes index >= 0.
+void InventoryPicture::setCurrentItemIndex(int32 index) {
+ if (index >= _inventory->getNumItems())
+ index = _inventory->getNumItems() - 1;
+
+ Item *currentItem = 0;
+ if (index >= 0)
+ currentItem = (Item *)_inventory->getItemAt(index);
+
+ if (currentItem != _currentItem) {
+ if (_currentItem) {
+ if (_currentItem->isSelected())
+ _currentItem->deselect();
+
+ if (_active)
+ unhighlightCurrentItem();
+ }
+
+ _currentItemIndex = index;
+ _currentItem = currentItem;
+ if (_currentItem) {
+ _currentItem->select();
+
+ if (_active)
+ highlightCurrentItem();
+ }
+
+ if (_active)
+ triggerRedraw();
+ }
+}
+
+void InventoryPicture::setCurrentItemID(ItemID id) {
+ int32 index = _inventory->findIndexOf(id);
+ if (index >= 0)
+ setCurrentItemIndex(index);
+}
+
+InventoryResult InventoryPicture::addInventoryItem(Item *item) {
+ InventoryResult result = _inventory->addItem(item);
+
+ if (result == kInventoryOK)
+ setCurrentItemIndex(_inventory->findIndexOf(item));
+
+ return result;
+}
+
+InventoryResult InventoryPicture::removeInventoryItem(Item *item) {
+ InventoryResult result = _inventory->removeItem(item);
+
+ if (result == kInventoryOK)
+ setCurrentItemIndex(getCurrentItemIndex());
+
+ return result;
+}
+
+void InventoryPicture::removeAllItems() {
+ _inventory->removeAllItems();
+ setCurrentItemIndex(0);
+}
+
+bool InventoryPicture::itemInInventory(Item *item) {
+ return _inventory->itemInInventory(item);
+}
+
+bool InventoryPicture::itemInInventory(const ItemID id) {
+ return _inventory->itemInInventory(id);
+}
+
+void InventoryPicture::panelUp() {
+ allowInput(true);
+}
+
+// Must ensure that the picture matches the _inventory member variable.
+void InventoryPicture::activateInventoryPicture() {
+ if (_active)
+ return;
+
+ allowInput(false);
+
+ if (_lastReferenceCount != _inventory->getReferenceCount()) {
+ uint32 numItems = _inventory->getNumItems();
+
+ CoordType x, y;
+ getItemXY(0, x, y);
+ _panelMovie.moveMovieBoxTo(x, y);
+ _panelMovie.show();
+
+ for (uint32 i = 0; i < numItems; i++) {
+ Item *item = (Item *)_inventory->getItemAt(i);
+ if (item == _currentItem)
+ item->select();
+
+ getItemXY(i, x, y);
+ _panelMovie.moveMovieBoxTo(x, y);
+ _panelMovie.setTime(getItemPanelTime(item));
+ _panelMovie.redrawMovieWorld();
+ }
+
+ uint32 numSlots = _itemsPerRow * _numberOfRows;
+
+ for (uint32 i = numItems; i < numSlots; i++) {
+ getItemXY(i, x, y);
+ _panelMovie.moveMovieBoxTo(x, y);
+ _panelMovie.setTime(0);
+ _panelMovie.redrawMovieWorld();
+ }
+
+ _lastReferenceCount = _inventory->getReferenceCount();
+ }
+
+ show(); // *** Do we really need this?
+ if (_currentItem)
+ highlightCurrentItem();
+
+ _active = true;
+}
+
+void InventoryPicture::deactivateInventoryPicture() {
+ if (!_active)
+ return;
+
+ _active = false;
+ allowInput(false);
+ _panelMovie.hide();
+ hide();
+
+ if (_inventory->getNumItems() != 0)
+ if (!_currentItem->isActive())
+ _currentItem->activate();
+}
+
+void InventoryPicture::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ if (_active) {
+ if (input.upButtonDown()) {
+ if (_currentItemIndex - _itemsPerRow >= 0)
+ setCurrentItemIndex(_currentItemIndex - _itemsPerRow);
+ } else if (input.downButtonDown()) {
+ if (_currentItemIndex + _itemsPerRow < _inventory->getNumItems())
+ setCurrentItemIndex(_currentItemIndex + _itemsPerRow);
+ } else if (input.leftButtonDown()) {
+ if ((_currentItemIndex % _itemsPerRow) != 0)
+ setCurrentItemIndex(_currentItemIndex - 1);
+ } else if (input.rightButtonDown()) {
+ if (((_currentItemIndex + 1) % _itemsPerRow) != 0 && _currentItemIndex + 1 < _inventory->getNumItems())
+ setCurrentItemIndex(_currentItemIndex + 1);
+ }
+ }
+
+ InputHandler::handleInput(input, cursorSpot);
+}
+
+void InventoryPicture::highlightCurrentItem() {
+ CoordType x, y;
+ getItemXY(_currentItemIndex, x, y);
+ _highlightBounds.moveTo(x, y);
+}
+
+InventoryItemsPicture::InventoryItemsPicture(const DisplayElementID id, InputHandler *nextHandler, Inventory *inventory) :
+ InventoryPicture(id, nextHandler, inventory) {
+ _pictName = "Images/Items/Inventory/Inventory Panel";
+ _movieName = "Images/Items/Inventory/Inventory Panel Movie";
+ _highlightName = "Images/Items/Inventory/Inventory Hilite";
+
+ _itemsPerRow = 3;
+ _numberOfRows = 3;
+ _itemWidth = 88;
+ _itemHeight = 64;
+ _itemX = 8;
+ _itemY = 26;
+ _isLooping = true;
+}
+
+void InventoryItemsPicture::loopCurrentItem() {
+ if (_isLooping) {
+ CoordType x, y;
+ getItemXY(_currentItemIndex, x, y);
+ _panelMovie.moveMovieBoxTo(x, y);
+ _highlightBounds.moveTo(x, y);
+
+ TimeValue start, stop;
+ ((InventoryItem *)_currentItem)->getPanelTimes(start, stop);
+ _panelMovie.stop();
+ _panelMovie.setFlags(0);
+ _panelMovie.setSegment(start, stop);
+ _panelMovie.setFlags(kLoopTimeBase);
+ _panelMovie.setTime(((InventoryItem *)_currentItem)->getAnimationTime());
+ _panelMovie.start();
+ }
+}
+
+void InventoryItemsPicture::highlightCurrentItem() {
+ InventoryPicture::highlightCurrentItem();
+ loopCurrentItem();
+}
+
+void InventoryItemsPicture::unhighlightCurrentItem() {
+ InventoryPicture::unhighlightCurrentItem();
+ _panelMovie.stop();
+ _panelMovie.setFlags(0);
+ ((InventoryItem *)_currentItem)->setAnimationTime(_panelMovie.getTime());
+}
+
+TimeValue InventoryItemsPicture::getItemPanelTime(Item *item) {
+ TimeValue start, stop;
+ ((InventoryItem *)item)->getPanelTimes(start, stop);
+ ((InventoryItem *)item)->setAnimationTime(start);
+ return start;
+}
+
+void InventoryItemsPicture::deactivateInventoryPicture() {
+ if (_active) {
+ InventoryPicture::deactivateInventoryPicture();
+ _panelMovie.stop();
+ _panelMovie.setFlags(0);
+ _panelMovie.setSegment(0, _panelMovie.getDuration());
+ _isLooping = true;
+ }
+}
+
+void InventoryItemsPicture::playEndMessage(DisplayElement *pushElement) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ Movie endMessage(0);
+
+ _shouldDrawHighlight = false;
+ endMessage.shareSurface(this);
+ endMessage.initFromMovieFile("Images/Caldoria/A56 Congrats");
+ endMessage.moveMovieBoxTo(kFinalMessageLeft - kInventoryPushLeft, kFinalMessageTop - kInventoryPushTop);
+ endMessage.setTriggeredElement(pushElement);
+ endMessage.start();
+
+ while (endMessage.isRunning()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ endMessage.stop();
+}
+
+BiochipPicture::BiochipPicture(const DisplayElementID id, InputHandler *nextHandler, Inventory *inventory) :
+ InventoryPicture(id, nextHandler, inventory) {
+ _pictName = "Images/Items/Biochips/Biochip Panel";
+ _movieName = "Images/Items/Biochips/Biochip Panel Movie";
+ _highlightName = "Images/Items/Biochips/BioChip Hilite";
+
+ _itemsPerRow = 4;
+ _numberOfRows = 2;
+ _itemWidth = 46;
+ _itemHeight = 46;
+ _itemX = 4;
+ _itemY = 24;
+}
+
+void BiochipPicture::unhighlightCurrentItem() {
+ InventoryPicture::unhighlightCurrentItem();
+ CoordType x, y;
+ getItemXY(_currentItemIndex, x, y);
+ _panelMovie.show();
+ _panelMovie.moveMovieBoxTo(x, y);
+ _panelMovie.setTime(getItemPanelTime(_currentItem));
+ _panelMovie.redrawMovieWorld();
+}
+
+TimeValue BiochipPicture::getItemPanelTime(Item *item) {
+ return ((BiochipItem *)item)->getPanelTime();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/inventorypicture.h b/engines/pegasus/items/inventorypicture.h
new file mode 100644
index 0000000000..88a4a4ba75
--- /dev/null
+++ b/engines/pegasus/items/inventorypicture.h
@@ -0,0 +1,125 @@
+/* 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_ITEMS_INVENTORYPICTURE_H
+#define PEGASUS_ITEMS_INVENTORYPICTURE_H
+
+#include "pegasus/input.h"
+#include "pegasus/movie.h"
+#include "pegasus/surface.h"
+
+namespace Pegasus {
+
+class Inventory;
+class Item;
+class Input;
+class Transition;
+
+class InventoryPicture : public InputHandler, public Picture {
+public:
+ InventoryPicture(const DisplayElementID, InputHandler *, Inventory *);
+ virtual ~InventoryPicture() {}
+
+ void initInventoryImage(Transition *);
+ void throwAwayInventoryImage();
+
+ void panelUp();
+ void activateInventoryPicture();
+ void deactivateInventoryPicture();
+ void handleInput(const Input &, const Hotspot *);
+ bool wantsCursor() { return false; }
+
+ InventoryResult addInventoryItem(Item *);
+ InventoryResult removeInventoryItem(Item *);
+ void removeAllItems();
+ Item *getCurrentItem() { return _currentItem; }
+ void setCurrentItemIndex(int32);
+ void setCurrentItemID(ItemID);
+ int32 getCurrentItemIndex() { return _currentItemIndex; }
+ bool itemInInventory(Item *);
+ bool itemInInventory(const ItemID);
+
+protected:
+ void getItemXY(uint32, CoordType &, CoordType &);
+ void draw(const Common::Rect &);
+ void drawItemHighlight(const Common::Rect &);
+ virtual void highlightCurrentItem();
+ virtual void unhighlightCurrentItem() {}
+ virtual TimeValue getItemPanelTime(Item *) = 0;
+
+ Inventory *_inventory;
+ uint32 _lastReferenceCount;
+ Frame _highlightImage;
+ Movie _panelMovie;
+ int32 _currentItemIndex;
+ Item *_currentItem;
+ Common::Rect _highlightBounds;
+ bool _active, _shouldDrawHighlight;
+
+ Common::String _pictName;
+ Common::String _movieName;
+ Common::String _highlightName;
+ uint16 _itemsPerRow;
+ uint16 _numberOfRows;
+ uint16 _itemWidth;
+ uint16 _itemHeight;
+ uint16 _itemX;
+ uint16 _itemY;
+};
+
+class InventoryItemsPicture : public InventoryPicture {
+public:
+ InventoryItemsPicture(const DisplayElementID, InputHandler *, Inventory *);
+ virtual ~InventoryItemsPicture() {}
+
+ void deactivateInventoryPicture();
+
+ void disableLooping() { _isLooping = false; }
+
+ void playEndMessage(DisplayElement *);
+
+protected:
+ virtual void highlightCurrentItem();
+ virtual void unhighlightCurrentItem();
+ virtual TimeValue getItemPanelTime(Item *);
+ void loopCurrentItem();
+
+ InputHandler *_previousHandler;
+ bool _isLooping;
+};
+
+class BiochipPicture : public InventoryPicture {
+public:
+ BiochipPicture(const DisplayElementID, InputHandler *, Inventory *);
+ virtual ~BiochipPicture() {}
+
+protected:
+ virtual void unhighlightCurrentItem();
+ virtual TimeValue getItemPanelTime(Item *);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/item.cpp b/engines/pegasus/items/item.cpp
new file mode 100644
index 0000000000..8089f2b93d
--- /dev/null
+++ b/engines/pegasus/items/item.cpp
@@ -0,0 +1,314 @@
+/* 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 "common/error.h"
+#include "common/stream.h"
+
+#include "pegasus/constants.h"
+#include "pegasus/elements.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/surface.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/item.h"
+#include "pegasus/items/itemlist.h"
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+Item::Item(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) : IDObject(id) {
+ _itemNeighborhood = neighborhood;
+ _itemRoom = room;
+ _itemDirection = direction;
+ _itemWeight = 1;
+ _itemOwnerID = kNoActorID;
+ _itemState = 0;
+
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ Common::SeekableReadStream *info = vm->_resFork->getResource(kItemInfoResType, kItemBaseResID + id);
+ if (info) {
+ _itemInfo.infoLeftTime = info->readUint32BE();
+ _itemInfo.infoRightStart = info->readUint32BE();
+ _itemInfo.infoRightStop = info->readUint32BE();
+ _itemInfo.dragSpriteNormalID = info->readUint16BE();
+ _itemInfo.dragSpriteUsedID = info->readUint16BE();
+
+ if (vm->isDemo()) {
+ // Adjust info right times to account for the stuff that was chopped out of the
+ // info right movies.
+ // Assumes time scale of 600.
+
+ // Gap times in seconds
+ static const TimeValue kGap1 = 24;
+ static const TimeValue kGap2 = 34;
+ static const TimeValue kGap3 = 4;
+ static const TimeValue kGap4 = 4;
+
+ static const TimeValue kGapForGroup1 = kGap1;
+ static const TimeValue kGapForGroup2 = kGapForGroup1 + kGap2;
+ static const TimeValue kGapForGroup3 = kGapForGroup2 + kGap3;
+ static const TimeValue kGapForGroup4 = kGapForGroup3 + kGap4;
+
+ switch (id) {
+ case kHistoricalLog:
+ case kJourneymanKey:
+ case kKeyCard:
+ _itemInfo.infoRightStart -= 600 * kGapForGroup1;
+ _itemInfo.infoRightStop -= 600 * kGapForGroup1;
+ break;
+ case kAIBiochip:
+ _itemInfo.infoRightStart -= 600 * kGapForGroup2;
+ _itemInfo.infoRightStop -= 600 * kGapForGroup2;
+ break;
+ case kMapBiochip:
+ _itemInfo.infoRightStart -= 600 * kGapForGroup3;
+ _itemInfo.infoRightStop -= 600 * kGapForGroup3;
+ break;
+ case kPegasusBiochip:
+ _itemInfo.infoRightStart -= 600 * kGapForGroup4;
+ _itemInfo.infoRightStop -= 600 * kGapForGroup4;
+ break;
+ }
+ }
+
+ delete info;
+ } else {
+ memset(&_itemInfo, 0, sizeof(_itemInfo));
+ }
+
+ Common::SeekableReadStream *middleAreaInfo = vm->_resFork->getResource(kMiddleAreaInfoResType, kItemBaseResID + id);
+ if (middleAreaInfo) {
+ _sharedAreaInfo = readItemState(middleAreaInfo);
+ delete middleAreaInfo;
+ } else {
+ // Only kArgonPickup does not have this
+ memset(&_sharedAreaInfo, 0, sizeof(_sharedAreaInfo));
+ }
+
+ Common::SeekableReadStream *extraInfo = vm->_resFork->getResource(kItemExtraInfoResType, kItemBaseResID + id);
+ if (!extraInfo)
+ error("Extra info not found for item %d", id);
+
+ _itemExtras.numEntries = extraInfo->readUint16BE();
+ _itemExtras.entries = new ItemExtraEntry[_itemExtras.numEntries];
+ for (uint16 i = 0; i < _itemExtras.numEntries; i++) {
+ _itemExtras.entries[i].extraID = extraInfo->readUint32BE();
+ _itemExtras.entries[i].extraArea = extraInfo->readUint16BE();
+ _itemExtras.entries[i].extraStart = extraInfo->readUint32BE();
+ _itemExtras.entries[i].extraStop = extraInfo->readUint32BE();
+ }
+
+ delete extraInfo;
+
+ g_allItems.push_back(this);
+}
+
+Item::~Item() {
+ delete[] _sharedAreaInfo.entries;
+ delete[] _itemExtras.entries;
+}
+
+void Item::writeToStream(Common::WriteStream *stream) {
+ stream->writeUint16BE(_itemNeighborhood);
+ stream->writeUint16BE(_itemRoom);
+ stream->writeByte(_itemDirection);
+ stream->writeUint16BE(_itemOwnerID);
+ stream->writeUint16BE(_itemState);
+}
+
+void Item::readFromStream(Common::ReadStream *stream) {
+ _itemNeighborhood = stream->readUint16BE();
+ _itemRoom = stream->readUint16BE();
+ _itemDirection = stream->readByte();
+ _itemOwnerID = stream->readUint16BE();
+ _itemState = stream->readUint16BE();
+}
+
+ActorID Item::getItemOwner() const {
+ return _itemOwnerID;
+}
+
+void Item::setItemOwner(const ActorID owner) {
+ _itemOwnerID = owner;
+
+ if (owner == kNoActorID) {
+ if (isSelected())
+ deselect();
+ removedFromInventory();
+ } else {
+ addedToInventory();
+ }
+}
+
+WeightType Item::getItemWeight() {
+ return _itemWeight;
+}
+
+ItemState Item::getItemState() const {
+ return _itemState;
+}
+
+void Item::setItemState(const ItemState state) {
+ if (state != _itemState) {
+ _itemState = state;
+
+ if (getItemType() == kInventoryItemType && ((PegasusEngine *)g_engine)->getCurrentInventoryItem() == (InventoryItem *)this)
+ select();
+ else if (getItemType() == kBiochipItemType && ((PegasusEngine *)g_engine)->getCurrentBiochip() == (BiochipItem *)this)
+ select();
+ }
+}
+
+void Item::getItemRoom(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction) const {
+ neighborhood = _itemNeighborhood;
+ room = _itemRoom;
+ direction = _itemDirection;
+}
+
+void Item::setItemRoom(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) {
+ _itemNeighborhood = neighborhood;
+ _itemRoom = room;
+ _itemDirection = direction;
+
+ if (neighborhood == kNoNeighborhoodID)
+ pickedUp();
+ else
+ dropped();
+}
+
+NeighborhoodID Item::getItemNeighborhood() const {
+ return _itemNeighborhood;
+}
+
+TimeValue Item::getSharedAreaTime() const {
+ if (!_sharedAreaInfo.entries)
+ return 0xffffffff;
+
+ TimeValue time;
+ ItemState state;
+
+ findItemStateEntryByState(_sharedAreaInfo, _itemState, time);
+ if (time == 0xffffffff)
+ getItemStateEntry(_sharedAreaInfo, 0, state, time);
+
+ return time;
+}
+
+// Must affect images in shared area.
+void Item::select() {
+ _isSelected = true;
+
+ if (g_AIArea) {
+ if (getItemType() == kInventoryItemType)
+ g_AIArea->setAIAreaToTime(kInventorySignature, kMiddleAreaSignature, getSharedAreaTime());
+ else
+ g_AIArea->setAIAreaToTime(kBiochipSignature, kMiddleAreaSignature, getSharedAreaTime());
+ }
+}
+
+void Item::deselect() {
+ _isActive = false;
+ _isSelected = false;
+
+ if (g_AIArea) {
+ if (getItemType() == kInventoryItemType)
+ g_AIArea->setAIAreaToTime(kInventorySignature, kMiddleAreaSignature, 0xffffffff);
+ else
+ g_AIArea->setAIAreaToTime(kBiochipSignature, kMiddleAreaSignature, 0xffffffff);
+ }
+}
+
+void Item::getItemStateEntry(ItemStateInfo info, uint32 index, ItemState &state, TimeValue &time) {
+ if (index < info.numEntries) {
+ state = info.entries[index].itemState;
+ time = info.entries[index].itemTime;
+ } else {
+ state = kNoItemState;
+ time = 0xffffffff;
+ }
+}
+
+void Item::findItemStateEntryByState(ItemStateInfo info, ItemState state, TimeValue &time) {
+ for (uint16 i = 0; i < info.numEntries; i++) {
+ if (info.entries[i].itemState == state) {
+ time = info.entries[i].itemTime;
+ return;
+ }
+ }
+
+ time = 0xffffffff;
+}
+
+ItemStateInfo Item::readItemState(Common::SeekableReadStream *stream) {
+ ItemStateInfo info;
+
+ info.numEntries = stream->readUint16BE();
+ info.entries = new ItemStateEntry[info.numEntries];
+ for (uint16 i = 0; i < info.numEntries; i++) {
+ info.entries[i].itemState = stream->readSint16BE();
+ info.entries[i].itemTime = stream->readUint32BE();
+ }
+
+ return info;
+}
+
+Sprite *Item::getDragSprite(const DisplayElementID id) const {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+ Sprite *result = new Sprite(id);
+ SpriteFrame *frame = new SpriteFrame();
+
+ frame->initFromPICTResource(vm->_resFork, _itemInfo.dragSpriteNormalID, true);
+ result->addFrame(frame, 0, 0);
+
+ if (_itemInfo.dragSpriteNormalID != _itemInfo.dragSpriteUsedID) {
+ frame = new SpriteFrame();
+ frame->initFromPICTResource(vm->_resFork, _itemInfo.dragSpriteUsedID, true);
+ }
+
+ result->addFrame(frame, 0, 0);
+ result->setCurrentFrameIndex(0);
+ return result;
+}
+
+TimeValue Item::getInfoLeftTime() const {
+ return _itemInfo.infoLeftTime;
+}
+
+void Item::getInfoRightTimes(TimeValue &start, TimeValue &stop) const {
+ start = _itemInfo.infoRightStart;
+ stop = _itemInfo.infoRightStop;
+}
+
+void Item::findItemExtra(const uint32 extraID, ItemExtraEntry &entry) {
+ for (uint32 i = 0; i < _itemExtras.numEntries; i++) {
+ if (_itemExtras.entries[i].extraID == extraID) {
+ entry = _itemExtras.entries[i];
+ return;
+ }
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/item.h b/engines/pegasus/items/item.h
new file mode 100644
index 0000000000..a1451b2a58
--- /dev/null
+++ b/engines/pegasus/items/item.h
@@ -0,0 +1,363 @@
+/* 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_ITEMS_ITEM_H
+#define PEGASUS_ITEMS_ITEM_H
+
+#include "common/endian.h"
+
+#include "pegasus/types.h"
+#include "pegasus/util.h"
+
+namespace Common {
+ class Error;
+ class ReadStream;
+ class WriteStream;
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+// JMPItemInfo contains resource data used by all Items.
+
+struct JMPItemInfo {
+ TimeValue infoLeftTime;
+ TimeValue infoRightStart;
+ TimeValue infoRightStop;
+ uint32 dragSpriteNormalID;
+ uint32 dragSpriteUsedID;
+};
+
+// ItemStateEntry contains a single state/TimeValue pair. The TimeValue is
+// the time value to set the shared area movie that corresponds with the given
+// state of an inventory item.
+
+struct ItemStateEntry {
+ ItemState itemState;
+ TimeValue itemTime;
+};
+
+struct ItemStateInfo {
+ uint16 numEntries; // For easy ResEdit access
+ ItemStateEntry *entries;
+};
+
+// ItemExtraEntry
+
+static const short kLeftAreaExtra = 0;
+static const short kMiddleAreaExtra = 1;
+static const short kRightAreaExtra = 2;
+
+struct ItemExtraEntry {
+ uint32 extraID;
+ uint16 extraArea;
+ TimeValue extraStart;
+ TimeValue extraStop;
+};
+
+struct ItemExtraInfo {
+ uint16 numEntries; // For easy ResEdit access
+ ItemExtraEntry *entries;
+};
+
+// Inventory info resource type and ID:
+// Individual inventory items are stored in these resource types.
+// Resource ID is item ID + kItemBaseResID.
+
+static const uint32 kItemInfoResType = MKTAG('I', 't', 'e', 'm'); // JMPItemInfoHandle
+static const uint32 kLeftAreaInfoResType = MKTAG('L', 'e', 'f', 't'); // ItemStateInfoHandle
+static const uint32 kMiddleAreaInfoResType = MKTAG('M', 'i', 'd', 'l'); // ItemStateInfoHandle
+static const uint32 kRightAreaInfoResType = MKTAG('R', 'g', 'h', 't'); // ItemStateInfoHandle
+static const uint32 kItemExtraInfoResType = MKTAG('I', 'X', 't', 'r'); // ItemExtraInfoHandle
+
+static const uint16 kItemBaseResID = 128;
+
+// Item IDs.
+
+static const ItemID kAirMask = 7;
+static const ItemID kAntidote = 8;
+static const ItemID kArgonCanister = 9;
+static const ItemID kCardBomb = 10;
+static const ItemID kCrowbar = 11;
+static const ItemID kGasCanister = 12;
+static const ItemID kHistoricalLog = 13;
+static const ItemID kJourneymanKey = 14;
+static const ItemID kKeyCard = 15;
+static const ItemID kMachineGun = 16;
+static const ItemID kMarsCard = 17;
+static const ItemID kNitrogenCanister = 18;
+static const ItemID kOrangeJuiceGlassFull = 19;
+static const ItemID kOrangeJuiceGlassEmpty = 20;
+static const ItemID kPoisonDart = 21;
+static const ItemID kSinclairKey = 22;
+static const ItemID kStunGun = 23;
+static const ItemID kArgonPickup = 24;
+
+// Biochips.
+
+static const ItemID kAIBiochip = 0;
+static const ItemID kInterfaceBiochip = 1;
+static const ItemID kMapBiochip = 2;
+static const ItemID kOpticalBiochip = 3;
+static const ItemID kPegasusBiochip = 4;
+static const ItemID kRetinalScanBiochip = 5;
+static const ItemID kShieldBiochip = 6;
+
+static const ItemID kNumItems = 25;
+
+// Item States.
+
+static const ItemState kAI000 = 0;
+static const ItemState kAI005 = 1;
+static const ItemState kAI006 = 2;
+static const ItemState kAI010 = 3;
+static const ItemState kAI015 = 4;
+static const ItemState kAI016 = 5;
+static const ItemState kAI020 = 6;
+static const ItemState kAI024 = 7;
+static const ItemState kAI100 = 8;
+static const ItemState kAI101 = 9;
+static const ItemState kAI105 = 10;
+static const ItemState kAI106 = 11;
+static const ItemState kAI110 = 12;
+static const ItemState kAI111 = 13;
+static const ItemState kAI115 = 14;
+static const ItemState kAI116 = 15;
+static const ItemState kAI120 = 16;
+static const ItemState kAI121 = 17;
+static const ItemState kAI124 = 18;
+static const ItemState kAI125 = 19;
+static const ItemState kAI126 = 20;
+static const ItemState kAI200 = 21;
+static const ItemState kAI201 = 22;
+static const ItemState kAI202 = 23;
+static const ItemState kAI205 = 24;
+static const ItemState kAI206 = 25;
+static const ItemState kAI210 = 26;
+static const ItemState kAI211 = 27;
+static const ItemState kAI212 = 28;
+static const ItemState kAI215 = 29;
+static const ItemState kAI216 = 30;
+static const ItemState kAI220 = 31;
+static const ItemState kAI221 = 32;
+static const ItemState kAI222 = 33;
+static const ItemState kAI224 = 34;
+static const ItemState kAI225 = 35;
+static const ItemState kAI226 = 36;
+static const ItemState kAI300 = 37;
+static const ItemState kAI301 = 38;
+static const ItemState kAI302 = 39;
+static const ItemState kAI303 = 40;
+static const ItemState kAI305 = 41;
+static const ItemState kAI306 = 42;
+static const ItemState kAI310 = 43;
+static const ItemState kAI311 = 44;
+static const ItemState kAI312 = 45;
+static const ItemState kAI313 = 46;
+static const ItemState kAI315 = 47;
+static const ItemState kAI316 = 48;
+static const ItemState kAI320 = 49;
+static const ItemState kAI321 = 50;
+static const ItemState kAI322 = 51;
+static const ItemState kAI323 = 52;
+static const ItemState kAI324 = 53;
+static const ItemState kAI325 = 54;
+static const ItemState kAI326 = 55;
+static const ItemState kNormalItem = 56;
+static const ItemState kMapUnavailable = 57;
+static const ItemState kMapEngaged = 58;
+static const ItemState kOptical000 = 59;
+static const ItemState kOptical001 = 60;
+static const ItemState kOptical002 = 61;
+static const ItemState kOptical010 = 62;
+static const ItemState kOptical011 = 63;
+static const ItemState kOptical012 = 64;
+static const ItemState kOptical020 = 65;
+static const ItemState kOptical021 = 66;
+static const ItemState kOptical100 = 67;
+static const ItemState kOptical101 = 68;
+static const ItemState kOptical102 = 69;
+static const ItemState kOptical110 = 70;
+static const ItemState kOptical111 = 71;
+static const ItemState kOptical112 = 72;
+static const ItemState kOptical120 = 73;
+static const ItemState kOptical121 = 74;
+static const ItemState kOptical200 = 75;
+static const ItemState kOptical201 = 76;
+static const ItemState kOptical210 = 77;
+static const ItemState kOptical211 = 78;
+static const ItemState kPegasusTSA00 = 79;
+static const ItemState kPegasusTSA10 = 80;
+static const ItemState kPegasusPrehistoric00 = 81;
+static const ItemState kPegasusPrehistoric01 = 82;
+static const ItemState kPegasusPrehistoric10 = 83;
+static const ItemState kPegasusPrehistoric11 = 84;
+static const ItemState kPegasusMars00 = 85;
+static const ItemState kPegasusMars01 = 86;
+static const ItemState kPegasusMars10 = 87;
+static const ItemState kPegasusMars11 = 88;
+static const ItemState kPegasusNorad00 = 89;
+static const ItemState kPegasusNorad01 = 90;
+static const ItemState kPegasusNorad10 = 91;
+static const ItemState kPegasusNorad11 = 92;
+static const ItemState kPegasusWSC00 = 93;
+static const ItemState kPegasusWSC01 = 94;
+static const ItemState kPegasusWSC10 = 95;
+static const ItemState kPegasusWSC11 = 96;
+static const ItemState kPegasusCaldoria = 97;
+static const ItemState kRetinalSimulating = 98;
+static const ItemState kShieldNormal = 99;
+static const ItemState kShieldRadiation = 100;
+static const ItemState kShieldPlasma = 101;
+static const ItemState kShieldCardBomb = 102;
+static const ItemState kShieldDraining = 103;
+static const ItemState kAirMaskEmptyOff = 104;
+static const ItemState kAirMaskEmptyFilter = 105;
+static const ItemState kAirMaskLowOff = 106;
+static const ItemState kAirMaskLowFilter = 107;
+static const ItemState kAirMaskLowOn = 108;
+static const ItemState kAirMaskFullOff = 109;
+static const ItemState kAirMaskFullFilter = 110;
+static const ItemState kAirMaskFullOn = 111;
+static const ItemState kArgonEmpty = 112;
+static const ItemState kArgonFull = 113;
+static const ItemState kFlashlightOff = 114;
+static const ItemState kFlashlightOn = 115;
+static const ItemState kNitrogenEmpty = 116;
+static const ItemState kNitrogenFull = 117;
+static const ItemState kFullGlass = 118;
+
+// Extra IDs.
+
+static const uint32 kRetinalScanSearching = 0;
+static const uint32 kRetinalScanActivated = 1;
+static const uint32 kShieldIntro = 2;
+static const uint32 kRemoveAirMask = 3;
+static const uint32 kRemoveArgon = 4;
+static const uint32 kRemoveCrowbar = 5;
+static const uint32 kGasCanLoop = 6;
+static const uint32 kRemoveJourneymanKey = 7;
+static const uint32 kRemoveMarsCard = 8;
+static const uint32 kRemoveNitrogen = 9;
+static const uint32 kRemoveGlass = 10;
+static const uint32 kRemoveDart = 11;
+static const uint32 kRemoveSinclairKey = 12;
+
+enum ItemType {
+ kInventoryItemType,
+ kBiochipItemType
+};
+
+class Sprite;
+
+/*
+
+ Item is an object which can be picked up and carried around.
+ Items have
+ a location
+ an ID.
+ weight
+ an owner (kNoActorID if no one is carrying the Item)
+
+*/
+
+class Item : public IDObject {
+public:
+ Item(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
+ virtual ~Item();
+
+ // WriteToStream writes everything EXCEPT the item's ID.
+ // It is assumed that the calling function will write and read the ID.
+ virtual void writeToStream(Common::WriteStream *stream);
+ virtual void readFromStream(Common::ReadStream *stream);
+
+ virtual ActorID getItemOwner() const;
+ virtual void setItemOwner(const ActorID owner);
+
+ void getItemRoom(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction) const;
+ void setItemRoom(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
+ NeighborhoodID getItemNeighborhood() const;
+
+ virtual WeightType getItemWeight();
+
+ virtual void setItemState(const ItemState state);
+ virtual ItemState getItemState() const;
+
+ virtual ItemType getItemType() = 0;
+
+ TimeValue getInfoLeftTime() const;
+ void getInfoRightTimes(TimeValue &, TimeValue &) const;
+ TimeValue getSharedAreaTime() const;
+
+ Sprite *getDragSprite(const DisplayElementID) const;
+
+ /*
+ select -- called when this item becomes current. Also called when the inventory
+ panel holding this item is raised and this is the current item.
+ deselect -- called when this item is no longer current.
+ activate -- called on the current item when the panel is closed.
+ */
+ // In an override of these three member functions, you must call the inherited
+ // member functions.
+ virtual void select();
+ virtual void deselect();
+ virtual bool isSelected() { return _isSelected; }
+
+ virtual void activate() { _isActive = true; }
+ virtual bool isActive() { return _isActive; }
+ virtual void pickedUp() {}
+ virtual void addedToInventory() {}
+ virtual void removedFromInventory() {}
+ virtual void dropped() {}
+
+ // Called when the shared area is taken by another item, but this item is still
+ // selected.
+ virtual void giveUpSharedArea() {}
+ virtual void takeSharedArea() {}
+
+ void findItemExtra(const uint32 extraID, ItemExtraEntry &entry);
+
+protected:
+ NeighborhoodID _itemNeighborhood;
+ RoomID _itemRoom;
+ DirectionConstant _itemDirection;
+ ActorID _itemOwnerID;
+ WeightType _itemWeight;
+ ItemState _itemState;
+
+ JMPItemInfo _itemInfo;
+ ItemStateInfo _sharedAreaInfo;
+ ItemExtraInfo _itemExtras;
+ bool _isActive;
+ bool _isSelected;
+
+ static void getItemStateEntry(ItemStateInfo, uint32, ItemState &, TimeValue &);
+ static void findItemStateEntryByState(ItemStateInfo, ItemState, TimeValue &);
+ static ItemStateInfo readItemState(Common::SeekableReadStream *stream);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/itemdragger.cpp b/engines/pegasus/items/itemdragger.cpp
new file mode 100644
index 0000000000..97fc5a97ac
--- /dev/null
+++ b/engines/pegasus/items/itemdragger.cpp
@@ -0,0 +1,193 @@
+/* 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/elements.h"
+#include "pegasus/hotspot.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/items/itemdragger.h"
+
+namespace Pegasus {
+
+SpriteDragger::SpriteDragger() {
+ _draggingSprite = 0;
+ _limitRect = Common::Rect(-30000, -30000, 30000, 30000);
+ _slopRect = Common::Rect(-30000, -30000, 30000, 30000);
+ _dragOffset.x = 0;
+ _dragOffset.y = 0;
+ _lastHotspot = 0;
+}
+
+void SpriteDragger::setDragSprite(Sprite *newSprite) {
+ if (!isTracking())
+ _draggingSprite = newSprite;
+}
+
+void SpriteDragger::setDragConstraints(const Common::Rect &limitRect, const Common::Rect &slopRect) {
+ if (!isTracking()) {
+ _rawLimitRect = limitRect;
+ _slopRect = slopRect;
+ }
+}
+
+void SpriteDragger::getDragConstraints(Common::Rect &limitRect, Common::Rect &slopRect) const {
+ limitRect = _rawLimitRect;
+ slopRect = _slopRect;
+}
+
+void SpriteDragger::startTracking(const Input &input) {
+ if (_draggingSprite) {
+ Tracker::startTracking(input);
+
+ if (isTracking()) {
+ input.getInputLocation(_startPoint);
+ _lastRawPoint = _startRawPoint = _startPoint;
+
+ Common::Rect r;
+ _draggingSprite->getBounds(r);
+ _dragOffset.x = _startPoint.x - r.left;
+ _dragOffset.y = _startPoint.y - r.top;
+
+ _limitRect = _rawLimitRect;
+ _limitRect.left += _dragOffset.x;
+ _limitRect.top += _dragOffset.y;
+ _limitRect.right -= r.width() - _dragOffset.x;
+ _limitRect.bottom -= r.height() - _dragOffset.y;
+ pinPointInRect(_limitRect, _startPoint);
+
+ _lastPoint = _startPoint;
+ if (_startPoint != _startRawPoint) {
+ Common::Point pt = _startPoint - _dragOffset;
+ _draggingSprite->moveElementTo(pt.x, pt.y);
+ }
+
+ _lastHotspot = g_allHotspots.findHotspot(_lastRawPoint);
+ if (_lastHotspot)
+ enterHotspot(_lastHotspot);
+ }
+ }
+}
+
+void SpriteDragger::continueTracking(const Input &input) {
+ if (_draggingSprite) {
+ Common::Point rawPoint;
+ input.getInputLocation(rawPoint);
+
+ if (!_slopRect.contains(rawPoint))
+ rawPoint = _startRawPoint;
+
+ if (rawPoint != _lastRawPoint) {
+ Common::Point newPoint = rawPoint;
+ pinPointInRect(_limitRect, newPoint);
+ newPoint -= _dragOffset;
+
+ if (newPoint != _lastPoint) {
+ _draggingSprite->moveElementTo(newPoint.x, newPoint.y);
+ _lastPoint = newPoint;
+ }
+
+ Hotspot *newHotspot = g_allHotspots.findHotspot(rawPoint);
+ if (newHotspot != _lastHotspot) {
+ if (_lastHotspot)
+ exitHotspot(_lastHotspot);
+ if (newHotspot)
+ enterHotspot(newHotspot);
+ _lastHotspot = newHotspot;
+ }
+
+ _lastRawPoint = rawPoint;
+ }
+ }
+}
+
+void SpriteDragger::pinPointInRect(const Common::Rect &r, Common::Point &pt) {
+ pt.x = CLIP<int>(pt.x, r.left, r.right - 1);
+ pt.y = CLIP<int>(pt.y, r.top, r.bottom - 1);
+}
+
+ItemDragger::ItemDragger(PegasusEngine *owner) : _inventoryDropSpot(kInventoryDropSpotID), _biochipDropSpot(kBiochipDropSpotID),
+ _inventoryHighlight(kInventoryDropHighlightID), _biochipHighlight(kBiochipDropHighlightID) {
+ _owner = owner;
+
+ Common::Rect r(kInventoryDropLeft, kInventoryDropTop, kInventoryDropRight, kInventoryDropBottom);
+ _inventoryDropSpot.setArea(r);
+ _inventoryDropSpot.setHotspotFlags(kDropItemSpotFlag);
+ g_allHotspots.push_back(&_inventoryDropSpot);
+
+ r = Common::Rect(kBiochipDropLeft, kBiochipDropTop, kBiochipDropRight, kBiochipDropBottom);
+ _biochipDropSpot.setArea(r);
+ _biochipDropSpot.setHotspotFlags(kDropBiochipSpotFlag);
+ g_allHotspots.push_back(&_biochipDropSpot);
+}
+
+void ItemDragger::startTracking(const Input &input) {
+ _inventoryHighlight.setDisplayOrder(kInventoryHiliteOrder);
+ _inventoryHighlight.startDisplaying();
+
+ _biochipHighlight.setDisplayOrder(kBiochipHiliteOrder);
+ _biochipHighlight.startDisplaying();
+
+ SpriteDragger::startTracking(input);
+}
+
+void ItemDragger::stopTracking(const Input &input) {
+ SpriteDragger::stopTracking(input);
+ _inventoryHighlight.hide();
+ _biochipHighlight.hide();
+ _inventoryHighlight.stopDisplaying();
+ _biochipHighlight.stopDisplaying();
+ _owner->dragTerminated(input);
+}
+
+bool ItemDragger::stopTrackingInput(const Input &input) {
+ return !JMPPPInput::isDraggingInput(input);
+}
+
+void ItemDragger::enterHotspot(Hotspot *spot) {
+ if (spot->getObjectID() == kInventoryDropSpotID)
+ _inventoryHighlight.show();
+ else if (spot->getObjectID() == kBiochipDropSpotID)
+ _biochipHighlight.show();
+ else if ((spot->getHotspotFlags() & kDropItemSpotFlag) != 0)
+ _draggingSprite->setCurrentFrameIndex(1);
+}
+
+void ItemDragger::exitHotspot(Hotspot *spot) {
+ if (spot->getObjectID() == kInventoryDropSpotID)
+ _inventoryHighlight.hide();
+ else if (spot->getObjectID() == kBiochipDropSpotID)
+ _biochipHighlight.hide();
+ else if ((spot->getHotspotFlags() & kDropItemSpotFlag) != 0)
+ _draggingSprite->setCurrentFrameIndex(0);
+}
+
+void ItemDragger::setHighlightBounds() {
+ uint32 color = g_system->getScreenFormat().RGBToColor(0x48, 0x80, 0xD8);
+ _inventoryHighlight.setBounds(Common::Rect(76, 334, 172, 430));
+ _inventoryHighlight.setHighlightColor(color);
+ _biochipHighlight.setBounds(Common::Rect(364, 334, 460, 430));
+ _biochipHighlight.setHighlightColor(color);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/itemdragger.h b/engines/pegasus/items/itemdragger.h
new file mode 100644
index 0000000000..fce953d695
--- /dev/null
+++ b/engines/pegasus/items/itemdragger.h
@@ -0,0 +1,96 @@
+/* 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_ITEMS_ITEMDRAGGER_H
+#define PEGASUS_ITEMS_ITEMDRAGGER_H
+
+#include "pegasus/elements.h"
+#include "pegasus/input.h"
+
+namespace Pegasus {
+
+// TODO: Merge SpriteDragger and ItemDragger
+
+class Hotspot;
+class Sprite;
+
+class SpriteDragger : public Tracker {
+public:
+ SpriteDragger();
+ virtual ~SpriteDragger() {}
+
+ void setDragSprite(Sprite *);
+ Sprite *getDragSprite() { return _draggingSprite; }
+
+ void setDragConstraints(const Common::Rect &, const Common::Rect &);
+ void getDragConstraints(Common::Rect &, Common::Rect &) const;
+
+ void startTracking(const Input &);
+ void continueTracking(const Input&);
+
+ Hotspot *getLastHotspot() const { return _lastHotspot; }
+
+protected:
+ virtual void enterHotspot(Hotspot *) {}
+ virtual void exitHotspot(Hotspot *) {}
+
+ Sprite *_draggingSprite;
+ Common::Point _startPoint, _lastPoint, _dragOffset;
+ Common::Point _startRawPoint, _lastRawPoint;
+ Common::Rect _rawLimitRect;
+ Common::Rect _limitRect;
+ Common::Rect _slopRect;
+ Hotspot *_lastHotspot;
+
+ // This is a replica of QuickDraw's PinPointInRect function
+ void pinPointInRect(const Common::Rect &, Common::Point &);
+};
+
+class PegasusEngine;
+
+class ItemDragger : public SpriteDragger {
+public:
+ ItemDragger(PegasusEngine *);
+ virtual ~ItemDragger() {}
+
+ void setHighlightBounds();
+ void startTracking(const Input &);
+ void stopTracking(const Input &);
+ bool stopTrackingInput(const Input &);
+
+protected:
+ virtual void enterHotspot(Hotspot *);
+ virtual void exitHotspot(Hotspot *);
+
+ PegasusEngine *_owner;
+ DropHighlight _inventoryHighlight;
+ Hotspot _inventoryDropSpot;
+ DropHighlight _biochipHighlight;
+ Hotspot _biochipDropSpot;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/itemlist.cpp b/engines/pegasus/items/itemlist.cpp
new file mode 100644
index 0000000000..ff8cae546b
--- /dev/null
+++ b/engines/pegasus/items/itemlist.cpp
@@ -0,0 +1,67 @@
+/* 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 "common/error.h"
+#include "common/stream.h"
+
+#include "pegasus/pegasus.h"
+#include "pegasus/items/item.h"
+#include "pegasus/items/itemlist.h"
+
+namespace Pegasus {
+
+ItemList::ItemList() {
+}
+
+ItemList::~ItemList() {
+}
+
+void ItemList::writeToStream(Common::WriteStream *stream) {
+ stream->writeUint32BE(size());
+
+ for (ItemIterator it = begin(); it != end(); it++) {
+ stream->writeUint16BE((*it)->getObjectID());
+ (*it)->writeToStream(stream);
+ }
+}
+
+void ItemList::readFromStream(Common::ReadStream *stream) {
+ uint32 itemCount = stream->readUint32BE();
+
+ for (uint32 i = 0; i < itemCount; i++) {
+ ItemID itemID = stream->readUint16BE();
+ g_allItems.findItemByID(itemID)->readFromStream(stream);
+ }
+}
+
+Item *ItemList::findItemByID(const ItemID id) {
+ for (ItemIterator it = begin(); it != end(); it++)
+ if ((*it)->getObjectID() == id)
+ return *it;
+
+ return 0;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/itemlist.h b/engines/pegasus/items/itemlist.h
new file mode 100644
index 0000000000..9b59206ab3
--- /dev/null
+++ b/engines/pegasus/items/itemlist.h
@@ -0,0 +1,59 @@
+/* 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_ITEMS_ITEMLIST_H
+#define PEGASUS_ITEMS_ITEMLIST_H
+
+#include "common/list.h"
+
+#include "pegasus/types.h"
+
+namespace Common {
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+class Item;
+
+class ItemList : public Common::List<Item *> {
+public:
+ ItemList();
+ virtual ~ItemList();
+
+ virtual void writeToStream(Common::WriteStream *stream);
+ virtual void readFromStream(Common::ReadStream *stream);
+
+ Item *findItemByID(const ItemID id);
+};
+
+typedef ItemList::iterator ItemIterator;
+
+#define g_allItems (((PegasusEngine *)g_engine)->getAllItems())
+
+} // End of namespace Pegasus
+
+#endif