aboutsummaryrefslogtreecommitdiff
path: root/engines/illusions
diff options
context:
space:
mode:
authorjohndoe1232014-03-28 21:53:21 +0100
committerEugene Sandulenko2018-07-20 06:43:33 +0000
commit3b3f84c764f8cab8f54b06bbafc607cfb6899fdd (patch)
tree8ef0d8e3af51b7e0a4f232e36c250aa89aeae655 /engines/illusions
parent33d28deb690c79a6aca190c5b1bc998c39d95662 (diff)
downloadscummvm-rg350-3b3f84c764f8cab8f54b06bbafc607cfb6899fdd.tar.gz
scummvm-rg350-3b3f84c764f8cab8f54b06bbafc607cfb6899fdd.tar.bz2
scummvm-rg350-3b3f84c764f8cab8f54b06bbafc607cfb6899fdd.zip
ILLUSIONS: Implement inventory
- Implement cursor camera tracking - Various bugfixes
Diffstat (limited to 'engines/illusions')
-rw-r--r--engines/illusions/actor.cpp7
-rw-r--r--engines/illusions/backgroundresource.cpp9
-rw-r--r--engines/illusions/backgroundresource.h3
-rw-r--r--engines/illusions/bbdou/bbdou_cursor.cpp136
-rw-r--r--engines/illusions/bbdou/bbdou_cursor.h5
-rw-r--r--engines/illusions/bbdou/bbdou_inventory.cpp196
-rw-r--r--engines/illusions/bbdou/bbdou_inventory.h63
-rw-r--r--engines/illusions/bbdou/bbdou_specialcode.cpp46
-rw-r--r--engines/illusions/bbdou/bbdou_specialcode.h15
-rw-r--r--engines/illusions/camera.cpp29
-rw-r--r--engines/illusions/camera.h4
-rw-r--r--engines/illusions/illusions.cpp1
-rw-r--r--engines/illusions/scriptman.cpp3
-rw-r--r--engines/illusions/scriptopcodes.cpp16
-rw-r--r--engines/illusions/scriptopcodes.h1
-rw-r--r--engines/illusions/sequenceopcodes.cpp13
-rw-r--r--engines/illusions/sequenceopcodes.h2
-rw-r--r--engines/illusions/talkresource.cpp2
-rw-r--r--engines/illusions/talkthread.cpp36
-rw-r--r--engines/illusions/talkthread.h8
-rw-r--r--engines/illusions/thread.cpp26
-rw-r--r--engines/illusions/thread.h3
22 files changed, 581 insertions, 43 deletions
diff --git a/engines/illusions/actor.cpp b/engines/illusions/actor.cpp
index 7f2a054b0f..53190ef97b 100644
--- a/engines/illusions/actor.cpp
+++ b/engines/illusions/actor.cpp
@@ -433,13 +433,13 @@ Common::Point Control::calcPosition(Common::Point posDelta) {
pos.x += accuX * actor->_scale / 100;
pos.y += accuY * actor->_scale / 100;
_actor->_position = pos;
- if (!(_actor->_flags & 8)) {
+ if (!(_flags & 8)) {
pos.x -= posDelta.x;
pos.y -= posDelta.y;
}
} else {
pos = _actor->_position;
- if (!(_actor->_flags & 8)) {
+ if (!(_flags & 8)) {
pos.x -= posDelta.x;
pos.y -= posDelta.y;
}
@@ -574,7 +574,8 @@ void Control::startTalkActor(uint32 sequenceId, byte *entryTblPtr, uint32 thread
subControl->_actor->notifyThreadId2 = threadId;
subControl->_actor->entryTblPtr = entryTblPtr;
subControl->_actor->flags |= 0x80;
- script_TalkThreads_sub_417FA0(subControl->_actor->_notifyThreadId2, 0);
+ Thread *thread = _vm->_threads->findThread(threadId);
+ thread->sendMessage(kMsgClearSequenceId2, 0);
}
*/
}
diff --git a/engines/illusions/backgroundresource.cpp b/engines/illusions/backgroundresource.cpp
index d2b01fea93..50a88d284a 100644
--- a/engines/illusions/backgroundresource.cpp
+++ b/engines/illusions/backgroundresource.cpp
@@ -181,6 +181,7 @@ void BackgroundResource::load(byte *data, uint32 dataSize) {
_bgInfos = new BgInfo[_bgInfosCount];
stream.seek(0x20);
uint32 bgInfosOffs = stream.readUint32LE();
+ debug("_bgInfosCount: %d", _bgInfosCount);
for (uint i = 0; i < _bgInfosCount; ++i) {
stream.seek(bgInfosOffs + i * 0x1C);
_bgInfos[i].load(data, stream);
@@ -314,7 +315,7 @@ void BackgroundItem::pause() {
krndictRemoveID(_bgRes->_item48s[i].id);
*/
// TODO _vm->setDefPointDimensions1();
- // TODO memcpy(&_savedCamera, &_vm->camera, sizeof(backgroundItem->savedCamera));
+ _vm->_camera->getActiveState(_savedCameraState);
/* Unused
_savedPalette = malloc(1024);
savePalette(_savedPalette);
@@ -338,11 +339,7 @@ void BackgroundItem::unpause() {
_savedPalette = 0;
*/
// TODO _vm->_screen->_fadeClear();
- // TODO memcpy(&_vm->camera, &_savedCamera, sizeof(SavedCamera));
- /* TODO
- currTime = krnxxxGetCurrentTime();
- _vm->_camera.panStartTime = currTime;
- */
+ _vm->_camera->setActiveState(_savedCameraState);
_vm->_backgroundItems->refreshPan();
}
}
diff --git a/engines/illusions/backgroundresource.h b/engines/illusions/backgroundresource.h
index daf2ffd770..741047f5b9 100644
--- a/engines/illusions/backgroundresource.h
+++ b/engines/illusions/backgroundresource.h
@@ -23,6 +23,7 @@
#ifndef ILLUSIONS_BACKGROUNDRESOURCE_H
#define ILLUSIONS_BACKGROUNDRESOURCE_H
+#include "illusions/camera.h"
#include "illusions/graphics.h"
#include "illusions/resourcesystem.h"
#include "graphics/surface.h"
@@ -154,7 +155,7 @@ public:
BackgroundResource *_bgRes;
Common::Point _panPoints[kMaxBackgroundItemSurfaces];
Graphics::Surface *_surfaces[kMaxBackgroundItemSurfaces];
- // TODO SavedCamera savedCamera;
+ CameraState _savedCameraState;
// TODO? byte *savedPalette;
};
diff --git a/engines/illusions/bbdou/bbdou_cursor.cpp b/engines/illusions/bbdou/bbdou_cursor.cpp
index 1c4af97a2c..ec877556db 100644
--- a/engines/illusions/bbdou/bbdou_cursor.cpp
+++ b/engines/illusions/bbdou/bbdou_cursor.cpp
@@ -22,6 +22,7 @@
#include "illusions/illusions.h"
#include "illusions/bbdou/bbdou_cursor.h"
+#include "illusions/bbdou/bbdou_specialcode.h"
#include "illusions/actor.h"
#include "illusions/camera.h"
#include "illusions/dictionary.h"
@@ -142,6 +143,25 @@ int BbdouCursor::findStruct8bsValue(uint32 objectId) {
return 11;
}
+bool BbdouCursor::updateTrackingCursor(Control *control) {
+ uint32 sequenceId;
+ if (getTrackingCursorSequenceId(control, sequenceId)) {
+ if (_data._sequenceId98 != sequenceId) {
+ saveBeforeTrackingCursor(control, sequenceId);
+ show(control);
+ _data._sequenceId98 = sequenceId;
+ }
+ return true;
+ } else {
+ if (_data._sequenceId98) {
+ _data._sequenceId98 = 0;
+ restoreAfterTrackingCursor();
+ show(control);
+ }
+ return false;
+ }
+}
+
void BbdouCursor::saveInfo() {
_data._mode2 = _data._mode;
_data._sequenceId2 = _data._sequenceId;
@@ -157,6 +177,24 @@ void BbdouCursor::restoreInfo() {
_data._sequenceId2 = 0;
}
+void BbdouCursor::saveBeforeTrackingCursor(Control *control, uint32 sequenceId) {
+ if (_data._currOverlappedObjectId || _data._mode == 3) {
+ if (_data._mode == 3)
+ restoreInfo();
+ control->setActorIndexTo1();
+ if (_data._item10._playSound48)
+ _bbdou->playSoundEffect(4);
+ _bbdou->resetItem10(control->_objectId, &_data._item10);
+ }
+ _data._currOverlappedObjectId = 0;
+ if (_data._mode != 4) {
+ saveInfo();
+ _data._mode = 4;
+ _data._holdingObjectId = 0;
+ }
+ _data._sequenceId = sequenceId;
+}
+
void BbdouCursor::restoreAfterTrackingCursor() {
_data._holdingObjectId = _data._holdingObjectId2;
if (_data._holdingObjectId2) {
@@ -191,6 +229,104 @@ uint32 BbdouCursor::getSequenceId1(int sequenceIndex) {
}
}
+uint BbdouCursor::calcTrackingFlags(Common::Point actorPos, Common::Point trackingLimits) {
+ uint trackingFlags = 0;
+ int16 x = actorPos.x - 320;
+ int16 y = actorPos.y - 240;
+ if (x < -trackingLimits.x)
+ trackingFlags = 1;
+ else if (x > trackingLimits.x)
+ trackingFlags = 3;
+ else
+ trackingFlags = 2;
+ if (y < -trackingLimits.y)
+ trackingFlags += 0;
+ else if (y > trackingLimits.y)
+ trackingFlags += 6;
+ else
+ trackingFlags += 3;
+ return trackingFlags;
+}
+
+uint BbdouCursor::calcTrackingCursorIndex(uint trackingFlags) {
+ uint cursorIndex = 0;
+ switch (trackingFlags) {
+ case 1:
+ if (_vm->_camera->isAtPanLimit(1)) {
+ if (!_vm->_camera->isAtPanLimit(3))
+ cursorIndex = 4;
+ } else {
+ if (!_vm->_camera->isAtPanLimit(3))
+ cursorIndex = 1;
+ else
+ cursorIndex = 2;
+ }
+ break;
+ case 2:
+ if (!_vm->_camera->isAtPanLimit(1))
+ cursorIndex = 2;
+ break;
+ case 3:
+ if (_vm->_camera->isAtPanLimit(1)) {
+ if (!_vm->_camera->isAtPanLimit(4))
+ cursorIndex = 6;
+ } else {
+ if (!_vm->_camera->isAtPanLimit(4))
+ cursorIndex = 3;
+ else
+ cursorIndex = 2;
+ }
+ break;
+ case 4:
+ if (!_vm->_camera->isAtPanLimit(3))
+ cursorIndex = 4;
+ break;
+ case 6:
+ if (!_vm->_camera->isAtPanLimit(4))
+ cursorIndex = 6;
+ break;
+ case 7:
+ if (_vm->_camera->isAtPanLimit(2)) {
+ if (!_vm->_camera->isAtPanLimit(3))
+ cursorIndex = 4;
+ } else {
+ if (!_vm->_camera->isAtPanLimit(3))
+ cursorIndex = 8;
+ else
+ cursorIndex = 7;
+ }
+ break;
+ case 8:
+ if (!_vm->_camera->isAtPanLimit(2))
+ cursorIndex = 8;
+ break;
+ case 9:
+ if (_vm->_camera->isAtPanLimit(2)) {
+ if (!_vm->_camera->isAtPanLimit(4))
+ cursorIndex = 6;
+ } else {
+ if (!_vm->_camera->isAtPanLimit(4))
+ cursorIndex = 9;
+ else
+ cursorIndex = 8;
+ }
+ break;
+ }
+ return cursorIndex;
+}
+
+bool BbdouCursor::getTrackingCursorSequenceId(Control *control, uint32 &outSequenceId) {
+ static const uint32 kTrackingCursorSequenceIds[] = {
+ 0, 0x000609BF, 0x00060018, 0x000609C0, 0x00060016,
+ 0, 0x00060017, 0x000609C1, 0x00060019, 0x000609C2
+ };
+ Common::Point trackingLimits = _vm->_camera->getTrackingLimits();
+ uint trackingFlags = calcTrackingFlags(control->_actor->_position, trackingLimits);
+ uint cursorIndex = calcTrackingCursorIndex(trackingFlags);
+ outSequenceId = kTrackingCursorSequenceIds[cursorIndex];
+ return outSequenceId != 0;
+}
+
void BbdouCursor::clearCursorDataField14() {
for (uint i = 0; i < 32; ++i)
_data._item10._verbActive[i] = 0;
diff --git a/engines/illusions/bbdou/bbdou_cursor.h b/engines/illusions/bbdou/bbdou_cursor.h
index bd3ba3aea3..43918e88a8 100644
--- a/engines/illusions/bbdou/bbdou_cursor.h
+++ b/engines/illusions/bbdou/bbdou_cursor.h
@@ -94,10 +94,15 @@ public:
uint32 findCursorSequenceId(uint32 objectId);
void setStruct8bsValue(uint32 objectId, int value);
int findStruct8bsValue(uint32 objectId);
+ bool updateTrackingCursor(Control *control);
void saveInfo();
void restoreInfo();
+ void saveBeforeTrackingCursor(Control *control, uint32 sequenceId);
void restoreAfterTrackingCursor();
uint32 getSequenceId1(int sequenceIndex);
+ uint calcTrackingFlags(Common::Point actorPos, Common::Point trackingLimits);
+ uint calcTrackingCursorIndex(uint trackingFlags);
+ bool getTrackingCursorSequenceId(Control *control, uint32 &outSequenceId);
public:
IllusionsEngine *_vm;
BbdouSpecialCode *_bbdou;
diff --git a/engines/illusions/bbdou/bbdou_inventory.cpp b/engines/illusions/bbdou/bbdou_inventory.cpp
index b1d4f92381..4c5646f5b7 100644
--- a/engines/illusions/bbdou/bbdou_inventory.cpp
+++ b/engines/illusions/bbdou/bbdou_inventory.cpp
@@ -22,6 +22,8 @@
#include "illusions/illusions.h"
#include "illusions/bbdou/bbdou_inventory.h"
+#include "illusions/bbdou/bbdou_cursor.h"
+#include "illusions/bbdou/bbdou_specialcode.h"
#include "illusions/actor.h"
#include "illusions/camera.h"
#include "illusions/dictionary.h"
@@ -29,4 +31,198 @@
namespace Illusions {
+// InventoryItem
+
+InventoryItem::InventoryItem(uint32 objectId, uint32 sequenceId)
+ : _objectId(objectId), _sequenceId(sequenceId),
+ _assigned(false), _flag(false), _timesPresent(0), _fieldE(0) {
+}
+
+// InventorySlot
+
+InventorySlot::InventorySlot(uint32 namedPointId)
+ : _namedPointId(namedPointId), _objectId(0), _inventoryItem(0) {
+}
+
+// InventoryBag
+
+InventoryBag::InventoryBag(IllusionsEngine *vm, uint32 sceneId)
+ : _vm(vm), _sceneId(sceneId), _isActive(false), _fieldA(0) {
+}
+
+void InventoryBag::registerInventorySlot(uint32 namedPointId) {
+ _inventorySlots.push_back(new InventorySlot(namedPointId));
+}
+
+bool InventoryBag::addInventoryItem(InventoryItem *inventoryItem, InventorySlot *inventorySlot) {
+ // NOTE Skipped support for multiple items per slot, not used in BBDOU
+ if (!inventorySlot) {
+ for (InventorySlotsIterator it = _inventorySlots.begin(); it != _inventorySlots.end(); ++it)
+ if (!(*it)->_inventoryItem) {
+ inventorySlot = *it;
+ break;
+ }
+ }
+ if (inventorySlot) {
+ inventorySlot->_inventoryItem = inventoryItem;
+ return true;
+ }
+ return false;
+}
+
+void InventoryBag::removeInventoryItem(InventoryItem *inventoryItem) {
+ // TODO
+}
+
+void InventoryBag::buildItems() {
+ for (InventorySlotsIterator it = _inventorySlots.begin();
+ it != _inventorySlots.end(); ++it) {
+ InventorySlot *inventorySlot = *it;
+ InventoryItem *inventoryItem = inventorySlot->_inventoryItem;
+ if (inventoryItem) {
+ ++inventoryItem->_timesPresent;
+ if (!inventoryItem->_assigned || inventoryItem->_flag || inventoryItem->_timesPresent > 1)
+ inventorySlot->_inventoryItem = 0;
+ }
+ }
+}
+
+// BbdouInventory
+
+BbdouInventory::BbdouInventory(IllusionsEngine *vm, BbdouSpecialCode *bbdou)
+ : _vm(vm), _bbdou(bbdou) {
+}
+
+void BbdouInventory::registerInventoryBag(uint32 sceneId) {
+ _inventoryBags.push_back(new InventoryBag(_vm, sceneId));
+ _activeBagSceneId = sceneId;
+}
+
+void BbdouInventory::registerInventoryItem(uint32 objectId, uint32 sequenceId) {
+ _activeBagSceneId = 0;
+ _inventoryItems.push_back(new InventoryItem(objectId, sequenceId));
+}
+
+void BbdouInventory::registerInventorySlot(uint32 namedPointId) {
+ InventoryBag *inventoryBag = getInventoryBag(_activeBagSceneId);
+ inventoryBag->registerInventorySlot(namedPointId);
+}
+
+void BbdouInventory::addInventoryItem(uint32 objectId) {
+ _activeBagSceneId = 0;
+ InventoryItem *inventoryItem = getInventoryItem(objectId);
+ bool assigned = inventoryItem->_assigned;
+ inventoryItem->_assigned = true;
+ if (!assigned && !inventoryItem->_flag) {
+ for (uint i = 0; i < _inventoryBags.size(); ++i)
+ if (!_inventoryBags[i]->addInventoryItem(inventoryItem, 0))
+ inventoryItem->_assigned = false;
+ }
+ if (_activeInventorySceneId)
+ refresh();
+}
+
+void BbdouInventory::removeInventoryItem(uint32 objectId) {
+ InventoryItem *inventoryItem = getInventoryItem(objectId);
+ bool flag = inventoryItem->_flag;
+ inventoryItem->_flag = true;
+ if (!flag && inventoryItem->_assigned) {
+ if (_activeInventorySceneId) {
+ InventoryBag *inventoryBag = getInventoryBag(_activeInventorySceneId);
+ inventoryBag->removeInventoryItem(inventoryItem);
+ }
+ refresh();
+ }
+}
+
+void BbdouInventory::open() {
+ _activeBagSceneId = 0;
+ InventoryBag *inventoryBag = getInventoryBag(_vm->getCurrentScene());
+ buildItems(inventoryBag);
+ if (_activeInventorySceneId) {
+ refresh();
+ refresh();
+ } else {
+ _activeInventorySceneId = _vm->getCurrentScene();
+ _index = 1;
+ inventoryBag->_isActive = true;
+ for (InventoryBag::InventorySlotsIterator it = inventoryBag->_inventorySlots.begin();
+ it != inventoryBag->_inventorySlots.end(); ++it) {
+ InventorySlot *inventorySlot = *it;
+ Common::Point slotPos = _vm->getNamedPointPosition(inventorySlot->_namedPointId);
+ Control *control = _vm->_dict->getObjectControl(inventorySlot->_objectId);
+ if (control) {
+ control->setActorPosition(slotPos);
+ control->startSequenceActor(0x0006005A, 2, 0);
+ } else {
+ inventorySlot->_objectId = _vm->_controls->newTempObjectId();
+ _vm->_controls->placeActor(0x00050012, slotPos, 0x0006005A, inventorySlot->_objectId, 0);
+ }
+ // TODO causeDeclare(0x1B0002, 0, inventorySlot->_objectId, Inventory_cause0x1B0002);
+ // TODO causeDeclare(0x1B0001, 0, inventorySlot->_objectId, Inventory_cause0x1B0001);
+ // TODO causeDeclare(0x1B0008, 0, inventorySlot->_objectId, Inventory_cause0x1B0001);
+ }
+ refresh();
+ }
+}
+
+void BbdouInventory::close() {
+ if (!_activeInventorySceneId)
+ return;
+ InventoryBag *inventoryBag = getInventoryBag(_vm->getCurrentScene());
+ for (InventoryBag::InventorySlotsIterator it = inventoryBag->_inventorySlots.begin();
+ it != inventoryBag->_inventorySlots.end(); ++it) {
+ InventorySlot *inventorySlot = *it;
+ Control *control = _vm->_dict->getObjectControl(inventorySlot->_objectId);
+ control->startSequenceActor(0x00060187, 2, 0);
+ }
+ inventoryBag->_isActive = false;
+ _activeInventorySceneId = 0;
+}
+
+InventoryBag *BbdouInventory::getInventoryBag(uint32 sceneId) {
+ for (uint i = 0; i < _inventoryBags.size(); ++i)
+ if (_inventoryBags[i]->_sceneId == sceneId)
+ return _inventoryBags[i];
+ return 0;
+}
+
+InventoryItem *BbdouInventory::getInventoryItem(uint32 objectId) {
+ for (uint i = 0; i < _inventoryItems.size(); ++i)
+ if (_inventoryItems[i]->_objectId == objectId)
+ return _inventoryItems[i];
+ return 0;
+}
+
+void BbdouInventory::refresh() {
+ if (!_activeInventorySceneId)
+ return;
+ InventoryBag *inventoryBag = getInventoryBag(_activeInventorySceneId);
+ for (InventoryBag::InventorySlotsIterator it = inventoryBag->_inventorySlots.begin();
+ it != inventoryBag->_inventorySlots.end(); ++it) {
+ InventorySlot *inventorySlot = *it;
+ Control *control = _vm->_dict->getObjectControl(inventorySlot->_objectId);
+ InventoryItem *inventoryItem = inventorySlot->_inventoryItem;
+ if (inventoryItem) {
+ control->startSequenceActor(inventoryItem->_sequenceId, 2, 0);
+ control->appearActor();
+ } else {
+ control->startSequenceActor(0x00060187, 2, 0);
+ }
+ }
+}
+
+void BbdouInventory::buildItems(InventoryBag *inventoryBag) {
+ for (InventoryItemsIterator it = _inventoryItems.begin(); it != _inventoryItems.end(); ++it)
+ (*it)->_timesPresent = 0;
+ inventoryBag->buildItems();
+ for (InventoryItemsIterator it = _inventoryItems.begin(); it != _inventoryItems.end(); ++it) {
+ InventoryItem *inventoryItem = *it;
+ if (inventoryItem->_assigned && !inventoryItem->_flag &&
+ inventoryItem->_timesPresent == 0 &&
+ inventoryItem->_objectId != _bbdou->_cursor->_data._holdingObjectId)
+ inventoryBag->addInventoryItem(inventoryItem, 0);
+ }
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_inventory.h b/engines/illusions/bbdou/bbdou_inventory.h
index 31023c063a..a983212114 100644
--- a/engines/illusions/bbdou/bbdou_inventory.h
+++ b/engines/illusions/bbdou/bbdou_inventory.h
@@ -24,6 +24,7 @@
#define ILLUSIONS_BBDOU_BBDOU_INVENTORY_H
#include "illusions/specialcode.h"
+#include "common/array.h"
#include "common/rect.h"
namespace Illusions {
@@ -32,6 +33,68 @@ class IllusionsEngine;
class BbdouSpecialCode;
class Control;
+struct InventoryItem {
+ uint32 _objectId;
+ uint32 _sequenceId;
+ bool _assigned;
+ bool _flag;
+ int _timesPresent;
+ int _fieldE;
+ InventoryItem(uint32 objectId, uint32 sequenceId);
+};
+
+struct InventorySlot {
+ uint32 _namedPointId;
+ uint32 _objectId;
+ InventoryItem *_inventoryItem;
+ InventorySlot(uint32 namedPointId);
+};
+
+class InventoryBag {
+public:
+ InventoryBag(IllusionsEngine *vm, uint32 sceneId);
+ void registerInventorySlot(uint32 namedPointId);
+ bool addInventoryItem(InventoryItem *inventoryItem, InventorySlot *inventorySlot);
+ void removeInventoryItem(InventoryItem *inventoryItem);
+ void buildItems();
+protected:
+public:
+ typedef Common::Array<InventorySlot*> InventorySlots;
+ typedef InventorySlots::iterator InventorySlotsIterator;
+ IllusionsEngine *_vm;
+ uint32 _sceneId;
+ InventorySlots _inventorySlots;
+ bool _isActive;
+ int _fieldA;
+};
+
+class BbdouInventory {
+public:
+ BbdouInventory(IllusionsEngine *vm, BbdouSpecialCode *bbdou);
+ void registerInventoryBag(uint32 sceneId);
+ void registerInventoryItem(uint32 objectId, uint32 sequenceId);
+ void registerInventorySlot(uint32 namedPointId);
+ void addInventoryItem(uint32 objectId);
+ void removeInventoryItem(uint32 objectId);
+ void open();
+ void close();
+ InventoryBag *getInventoryBag(uint32 sceneId);
+ InventoryItem *getInventoryItem(uint32 objectId);
+ void refresh();
+ void buildItems(InventoryBag *inventoryBag);
+protected:
+ typedef Common::Array<InventoryItem*> InventoryItems;
+ typedef InventoryItems::iterator InventoryItemsIterator;
+ IllusionsEngine *_vm;
+ BbdouSpecialCode *_bbdou;
+ Common::Array<InventoryBag*> _inventoryBags;
+ InventoryItems _inventoryItems;
+ uint32 _activeBagSceneId;
+ uint32 _activeInventorySceneId;
+ int _index;
+ //field_12 dw
+};
+
} // End of namespace Illusions
#endif // ILLUSIONS_BBDOU_BBDOU_INVENTORY_H
diff --git a/engines/illusions/bbdou/bbdou_specialcode.cpp b/engines/illusions/bbdou/bbdou_specialcode.cpp
index 96e4cb0c11..c74676d168 100644
--- a/engines/illusions/bbdou/bbdou_specialcode.cpp
+++ b/engines/illusions/bbdou/bbdou_specialcode.cpp
@@ -23,6 +23,7 @@
#include "illusions/illusions.h"
#include "illusions/bbdou/bbdou_specialcode.h"
#include "illusions/bbdou/bbdou_bubble.h"
+#include "illusions/bbdou/bbdou_inventory.h"
#include "illusions/bbdou/bbdou_cursor.h"
#include "illusions/actor.h"
#include "illusions/camera.h"
@@ -73,9 +74,11 @@ BbdouSpecialCode::BbdouSpecialCode(IllusionsEngine *vm)
: SpecialCode(vm) {
_bubble = new BbdouBubble(_vm, this);
_cursor = new BbdouCursor(_vm, this);
+ _inventory = new BbdouInventory(_vm, this);
}
BbdouSpecialCode::~BbdouSpecialCode() {
+ delete _inventory;
delete _cursor;
delete _bubble;
}
@@ -92,6 +95,12 @@ void BbdouSpecialCode::init() {
SPECIAL(0x00160013, spcInitBubble);
SPECIAL(0x00160014, spcSetupBubble);
SPECIAL(0x00160015, spcSetObjectInteractMode);
+ SPECIAL(0x00160019, spcRegisterInventoryBag);
+ SPECIAL(0x0016001A, spcRegisterInventorySlot);
+ SPECIAL(0x0016001B, spcRegisterInventoryItem);
+ SPECIAL(0x0016001C, spcOpenInventory);
+ SPECIAL(0x0016001D, spcAddInventoryItem);
+ SPECIAL(0x00160025, spcCloseInventory);
}
void BbdouSpecialCode::run(uint32 specialCodeId, OpCall &opCall) {
@@ -163,6 +172,36 @@ void BbdouSpecialCode::spcSetObjectInteractMode(OpCall &opCall) {
_vm->notifyThreadId(opCall._callerThreadId);
}
+void BbdouSpecialCode::spcRegisterInventoryBag(OpCall &opCall) {
+ ARG_UINT32(sceneId);
+ _inventory->registerInventoryBag(sceneId);
+}
+
+void BbdouSpecialCode::spcRegisterInventorySlot(OpCall &opCall) {
+ ARG_UINT32(namedPointId);
+ _inventory->registerInventorySlot(namedPointId);
+}
+
+void BbdouSpecialCode::spcRegisterInventoryItem(OpCall &opCall) {
+ ARG_UINT32(objectId);
+ ARG_UINT32(sequenceId);
+ _inventory->registerInventoryItem(objectId, sequenceId);
+}
+
+void BbdouSpecialCode::spcOpenInventory(OpCall &opCall) {
+ _inventory->open();
+}
+
+void BbdouSpecialCode::spcAddInventoryItem(OpCall &opCall) {
+ ARG_UINT32(objectId);
+debug("### spcAddInventoryItem %08X", objectId);
+ _inventory->addInventoryItem(objectId);
+}
+
+void BbdouSpecialCode::spcCloseInventory(OpCall &opCall) {
+ _inventory->close();
+}
+
void BbdouSpecialCode::playSoundEffect(int soundIndex) {
static const uint32 kSoundEffectIds[] = {
0, 1,
@@ -302,7 +341,7 @@ void BbdouSpecialCode::cursorInteractControlRoutine(Control *cursorControl, uint
cursorData._idleCtr = 0;
}
- if (updateTrackingCursor(cursorControl))
+ if (_cursor->updateTrackingCursor(cursorControl))
cursorData._flags |= 1;
else
cursorData._flags &= ~1;
@@ -432,11 +471,6 @@ void BbdouSpecialCode::cursorControlRoutine2(Control *cursorControl, uint32 delt
// TODO
}
-bool BbdouSpecialCode::updateTrackingCursor(Control *cursorControl) {
- // TODO
- return false;
-}
-
bool BbdouSpecialCode::testVerbId(uint32 verbId, uint32 holdingObjectId, uint32 overlappedObjectId) {
static const uint32 kVerbIdsEE[] = {0x001B0002, 0x001B0001, 0};
static const uint32 kVerbIdsE9[] = {0x001B0005, 0};
diff --git a/engines/illusions/bbdou/bbdou_specialcode.h b/engines/illusions/bbdou/bbdou_specialcode.h
index 9781c6d15d..dcfb5baf63 100644
--- a/engines/illusions/bbdou/bbdou_specialcode.h
+++ b/engines/illusions/bbdou/bbdou_specialcode.h
@@ -32,6 +32,7 @@ namespace Illusions {
class IllusionsEngine;
class BbdouBubble;
class BbdouCursor;
+class BbdouInventory;
struct CursorData;
struct Item10;
@@ -74,6 +75,7 @@ public:
Map _map;
BbdouCursor *_cursor;
BbdouBubble *_bubble;
+ BbdouInventory *_inventory;
// Special code interface functions
void spcInitCursor(OpCall &opCall);
void spcEnableCursor(OpCall &opCall);
@@ -82,10 +84,18 @@ public:
void spcInitBubble(OpCall &opCall);
void spcSetupBubble(OpCall &opCall);
void spcSetObjectInteractMode(OpCall &opCall);
-protected:
- // Internal functions
+ void spcRegisterInventoryBag(OpCall &opCall);
+ void spcRegisterInventorySlot(OpCall &opCall);
+ void spcRegisterInventoryItem(OpCall &opCall);
+ void spcOpenInventory(OpCall &opCall);
+ void spcAddInventoryItem(OpCall &opCall);
+ void spcCloseInventory(OpCall &opCall);
+
void playSoundEffect(int soundIndex);
void resetItem10(uint32 objectId, Item10 *item10);
+
+protected:
+ // Internal functions
bool testValueRange(int value);
void setCursorControlRoutine(uint32 objectId, int num);
Common::Point getBackgroundCursorPos(Common::Point cursorPos);
@@ -94,7 +104,6 @@ protected:
bool findVerbId(Item10 *item10, uint32 currOverlappedObjectId, int always0, uint32 &outVerbId);
void cursorInteractControlRoutine(Control *cursorControl, uint32 deltaTime);
void cursorControlRoutine2(Control *cursorControl, uint32 deltaTime);
- bool updateTrackingCursor(Control *cursorControl);
bool testVerbId(uint32 verbId, uint32 holdingObjectId, uint32 overlappedObjectId);
bool getCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId,
uint32 &outVerbId, uint32 &outObjectId2, uint32 &outObjectId);
diff --git a/engines/illusions/camera.cpp b/engines/illusions/camera.cpp
index 300065a27f..57d6f6fc51 100644
--- a/engines/illusions/camera.cpp
+++ b/engines/illusions/camera.cpp
@@ -243,8 +243,6 @@ void Camera::update(uint32 currTime) {
if (_activeState._paused)
return;
- //debug("_activeState._cameraMode = %d", _activeState._cameraMode);
-
switch (_activeState._cameraMode) {
case 1:
updateMode1(currTime);
@@ -306,6 +304,33 @@ Common::Point Camera::getScreenOffset() {
return screenOffs;
}
+Common::Point Camera::getTrackingLimits() {
+ return _activeState._trackingLimits;
+}
+
+bool Camera::isAtPanLimit(int limitNum) {
+ switch (limitNum) {
+ case 1:
+ return _activeState._currPan.y <= _activeState._bounds._topLeft.y;
+ case 2:
+ return _activeState._currPan.y >= _activeState._bounds._bottomRight.y;
+ case 3:
+ return _activeState._currPan.x <= _activeState._bounds._topLeft.x;
+ case 4:
+ return _activeState._currPan.x >= _activeState._bounds._bottomRight.x;
+ }
+ return false;
+}
+
+void Camera::setActiveState(CameraState &state) {
+ _activeState = state;
+ _activeState._panStartTime = getCurrentTime();
+}
+
+void Camera::getActiveState(CameraState &state) {
+ state = _activeState;
+}
+
void Camera::updateMode1(uint32 currTime) {
Common::Point ptOffs = getPtOffset(*_activeState._panToPositionPtr);
int deltaX = ptOffs.x - _activeState._currPan.x + 320 - _activeState._centerPt.x;
diff --git a/engines/illusions/camera.h b/engines/illusions/camera.h
index 6c9556c88d..a6f8a7333f 100644
--- a/engines/illusions/camera.h
+++ b/engines/illusions/camera.h
@@ -81,6 +81,10 @@ public:
void setBoundsToDimensions(WidthHeight &dimensions);
Common::Point getCurrentPan();
Common::Point getScreenOffset();
+ Common::Point getTrackingLimits();
+ bool isAtPanLimit(int limitNum);
+ void setActiveState(CameraState &state);
+ void getActiveState(CameraState &state);
protected:
IllusionsEngine *_vm;
CameraState _activeState;
diff --git a/engines/illusions/illusions.cpp b/engines/illusions/illusions.cpp
index bd302f8959..968dc0f583 100644
--- a/engines/illusions/illusions.cpp
+++ b/engines/illusions/illusions.cpp
@@ -310,6 +310,7 @@ uint32 IllusionsEngine::causeTrigger(uint32 sceneId, uint32 verbId, uint32 objec
uint32 causeThreadId = 0;
// TODO Also search for native trigger functions later and run it (findCauseFunc)
if (_scriptMan->findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs)) {
+ debug("Run cause at %08X", codeOffs);
causeThreadId = _scriptMan->startTempScriptThread(_scriptMan->_scriptResource->getCode(codeOffs),
callingThreadId, verbId, objectId2, objectId);
}
diff --git a/engines/illusions/scriptman.cpp b/engines/illusions/scriptman.cpp
index b556c0c1b8..961ffd4579 100644
--- a/engines/illusions/scriptman.cpp
+++ b/engines/illusions/scriptman.cpp
@@ -210,8 +210,7 @@ void ScriptMan::setCurrFontId(uint32 fontId) {
}
bool ScriptMan::checkActiveTalkThreads() {
- // TODO
- return false;
+ return _threads->isActiveThread(kMsgQueryTalkThreadActive);
}
uint32 ScriptMan::clipTextDuration(uint32 duration) {
diff --git a/engines/illusions/scriptopcodes.cpp b/engines/illusions/scriptopcodes.cpp
index abfda679c7..fbb9448437 100644
--- a/engines/illusions/scriptopcodes.cpp
+++ b/engines/illusions/scriptopcodes.cpp
@@ -98,6 +98,7 @@ void ScriptOpcodes::initOpcodes() {
OPCODE(20, opEnterScene);
OPCODE(25, opChangeScene);
OPCODE(26, opStartModalScene);
+ OPCODE(27, opExitModalScene);
OPCODE(30, opEnterCloseUpScene);
OPCODE(31, opExitCloseUpScene);
OPCODE(32, opPanCenterObject);
@@ -282,6 +283,14 @@ void ScriptOpcodes::opStartModalScene(ScriptThread *scriptThread, OpCall &opCall
opCall._result = kTSSuspend;
}
+void ScriptOpcodes::opExitModalScene(ScriptThread *scriptThread, OpCall &opCall) {
+ // NOTE Skipped checking for stalled resources
+ _vm->_input->discardButtons(0xFFFF);
+ _vm->_scriptMan->exitScene(opCall._callerThreadId);
+ _vm->_scriptMan->leavePause(opCall._callerThreadId);
+ // TODO _vm->_talkItems->unpauseByTag(_vm->getCurrentScene());
+}
+
void ScriptOpcodes::opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(sceneId);
@@ -609,7 +618,7 @@ void ScriptOpcodes::opCompareBlockCounter(ScriptThread *scriptThread, OpCall &op
bool compareResult = false;
switch (compareOp) {
case 1:
- compareResult = false;//lvalue == rvalue;
+ compareResult = lvalue == rvalue;
break;
case 2:
compareResult = lvalue != rvalue;
@@ -660,7 +669,6 @@ void ScriptOpcodes::opLoadSpecialCodeModule(ScriptThread *scriptThread, OpCall &
ARG_SKIP(2);
ARG_UINT32(specialCodeModuleId);
_vm->_resSys->loadResource(specialCodeModuleId, 0, 0);
- // TODO _vm->loadSpecialCodeModule(specialCodeModuleId);
}
void ScriptOpcodes::opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall) {
@@ -669,10 +677,6 @@ void ScriptOpcodes::opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall)
_vm->_scriptMan->_callerThreadId = opCall._callerThreadId;
_vm->_specialCode->run(specialCodeId, opCall);
_vm->_scriptMan->_callerThreadId = 0;
-
- //DEBUG Resume calling thread, later done by the special code
- //_vm->notifyThreadId(opCall._callerThreadId);
-
}
void ScriptOpcodes::opStopActor(ScriptThread *scriptThread, OpCall &opCall) {
diff --git a/engines/illusions/scriptopcodes.h b/engines/illusions/scriptopcodes.h
index 8516c85156..507d21b5e8 100644
--- a/engines/illusions/scriptopcodes.h
+++ b/engines/illusions/scriptopcodes.h
@@ -73,6 +73,7 @@ protected:
void opEnterScene(ScriptThread *scriptThread, OpCall &opCall);
void opChangeScene(ScriptThread *scriptThread, OpCall &opCall);
void opStartModalScene(ScriptThread *scriptThread, OpCall &opCall);
+ void opExitModalScene(ScriptThread *scriptThread, OpCall &opCall);
void opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
void opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
void opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall);
diff --git a/engines/illusions/sequenceopcodes.cpp b/engines/illusions/sequenceopcodes.cpp
index 409aa15816..7df968df3d 100644
--- a/engines/illusions/sequenceopcodes.cpp
+++ b/engines/illusions/sequenceopcodes.cpp
@@ -57,6 +57,7 @@ void SequenceOpcodes::initOpcodes() {
// Register opcodes
OPCODE(2, opSetFrameIndex);
OPCODE(3, opEndSequence);
+ OPCODE(4, opIncFrameDelay);
OPCODE(5, opSetRandomFrameDelay);
OPCODE(6, opSetFrameSpeed);
OPCODE(7, opJump);
@@ -67,6 +68,7 @@ void SequenceOpcodes::initOpcodes() {
OPCODE(12, opNextLoop);
OPCODE(14, opSwitchActorIndex);
OPCODE(15, opSwitchFacing);
+ OPCODE(16, opAppearActor);
OPCODE(17, opDisappearActor);
OPCODE(28, opNotifyThreadId1);
OPCODE(29, opSetPathCtrY);
@@ -130,10 +132,17 @@ void SequenceOpcodes::opEndSequence(Control *control, OpCall &opCall) {
opCall._result = 1;
}
+void SequenceOpcodes::opIncFrameDelay(Control *control, OpCall &opCall) {
+ ARG_INT16(frameDelayIncr);
+ control->_actor->_seqCodeValue3 += frameDelayIncr;
+ opCall._result = 2;
+}
+
void SequenceOpcodes::opSetRandomFrameDelay(Control *control, OpCall &opCall) {
ARG_INT16(minFrameDelay);
ARG_INT16(maxFrameDelay);
control->_actor->_seqCodeValue3 += 0;//DEBUG minFrameDelay + _vm->getRandom(maxFrameDelay);
+ opCall._result = 2;
}
void SequenceOpcodes::opSetFrameSpeed(Control *control, OpCall &opCall) {
@@ -201,6 +210,10 @@ void SequenceOpcodes::opSwitchFacing(Control *control, OpCall &opCall) {
opCall._deltaOfs += jumpOffs;
}
+void SequenceOpcodes::opAppearActor(Control *control, OpCall &opCall) {
+ control->appearActor();
+}
+
void SequenceOpcodes::opDisappearActor(Control *control, OpCall &opCall) {
control->disappearActor();
control->_actor->_newFrameIndex = 0;
diff --git a/engines/illusions/sequenceopcodes.h b/engines/illusions/sequenceopcodes.h
index 849846ffc9..abf1987d89 100644
--- a/engines/illusions/sequenceopcodes.h
+++ b/engines/illusions/sequenceopcodes.h
@@ -47,6 +47,7 @@ protected:
// Opcodes
void opSetFrameIndex(Control *control, OpCall &opCall);
void opEndSequence(Control *control, OpCall &opCall);
+ void opIncFrameDelay(Control *control, OpCall &opCall);
void opSetRandomFrameDelay(Control *control, OpCall &opCall);
void opSetFrameSpeed(Control *control, OpCall &opCall);
void opJump(Control *control, OpCall &opCall);
@@ -57,6 +58,7 @@ protected:
void opNextLoop(Control *control, OpCall &opCall);
void opSwitchActorIndex(Control *control, OpCall &opCall);
void opSwitchFacing(Control *control, OpCall &opCall);
+ void opAppearActor(Control *control, OpCall &opCall);
void opDisappearActor(Control *control, OpCall &opCall);
void opNotifyThreadId1(Control *control, OpCall &opCall);
void opSetPathCtrY(Control *control, OpCall &opCall);
diff --git a/engines/illusions/talkresource.cpp b/engines/illusions/talkresource.cpp
index fe14effd39..1d17408fa8 100644
--- a/engines/illusions/talkresource.cpp
+++ b/engines/illusions/talkresource.cpp
@@ -29,7 +29,7 @@ namespace Illusions {
// TalkResourceLoader
void TalkResourceLoader::load(Resource *resource) {
- debug("TalkResourceLoader::load() Loading font %08X from %s...", resource->_resId, resource->_filename.c_str());
+ debug("TalkResourceLoader::load() Loading text %08X from %s...", resource->_resId, resource->_filename.c_str());
TalkResource *talkResource = new TalkResource();
talkResource->load(resource->_data, resource->_dataSize);
diff --git a/engines/illusions/talkthread.cpp b/engines/illusions/talkthread.cpp
index fc777b7aef..c8bee715ce 100644
--- a/engines/illusions/talkthread.cpp
+++ b/engines/illusions/talkthread.cpp
@@ -72,11 +72,12 @@ TalkThread::TalkThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThrea
_voiceStartTime = getCurrentTime();
_voiceEndTime = _voiceStartTime + duration;
_entryTblPtr = 0;
-
- /* TODO
- if (callingThreadId)
- thread->tag = *(_DWORD *)(krndictGetIDValue(callingThreadId) + 20);
- */
+
+ if (callingThreadId) {
+ Thread *callingThread = _vm->_scriptMan->_threads->findThread(callingThreadId);
+ if (callingThread)
+ _tag = callingThread->_tag;
+ }
}
@@ -251,6 +252,31 @@ void TalkThread::onResume() {
void TalkThread::onTerminated() {
}
+void TalkThread::onKill() {
+ _callingThreadId = 0;
+ sendMessage(kMsgClearSequenceId1, 0);
+ sendMessage(kMsgClearSequenceId2, 0);
+}
+
+uint32 TalkThread::sendMessage(int msgNum, uint32 msgValue) {
+ // TODO
+ switch (msgNum) {
+ case kMsgQueryTalkThreadActive:
+ if (_status != 1 && _status != 2)
+ return 1;
+ break;
+ case kMsgClearSequenceId1:
+ _sequenceId1 = 0;
+ _flags |= 3;
+ // TODO _field30 = 0;
+ break;
+ case kMsgClearSequenceId2:
+ _sequenceId2 = 0;
+ break;
+ }
+ return 0;
+}
+
void TalkThread::refreshText() {
_currEntryText = _entryText;
int charCount = insertText();
diff --git a/engines/illusions/talkthread.h b/engines/illusions/talkthread.h
index fd0e3d0ba0..ada593b571 100644
--- a/engines/illusions/talkthread.h
+++ b/engines/illusions/talkthread.h
@@ -30,6 +30,12 @@ namespace Illusions {
class IllusionsEngine;
struct TalkEntry;
+enum {
+ kMsgQueryTalkThreadActive = 0,
+ kMsgClearSequenceId1 = 1,
+ kMsgClearSequenceId2 = 2
+};
+
class TalkThread : public Thread {
public:
TalkThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThreadId, uint notifyFlags,
@@ -41,6 +47,8 @@ public:
virtual void onPause();
virtual void onResume();
virtual void onTerminated();
+ virtual void onKill();
+ virtual uint32 sendMessage(int msgNum, uint32 msgValue);
public:
//field0 dw
int _status;
diff --git a/engines/illusions/thread.cpp b/engines/illusions/thread.cpp
index 83e0ce5ab4..38e69007c0 100644
--- a/engines/illusions/thread.cpp
+++ b/engines/illusions/thread.cpp
@@ -54,6 +54,15 @@ void Thread::onResume() {
void Thread::onTerminated() {
}
+void Thread::onKill() {
+ // TODO artmgrThreadIsDead(thread->threadId);
+ terminate();
+}
+
+uint32 Thread::sendMessage(int msgNum, uint32 msgValue) {
+ return 0;
+}
+
void Thread::pause() {
if (!_terminated) {
++_pauseCtr;
@@ -252,14 +261,7 @@ void ThreadList::killThread(uint32 threadId) {
killThread(childThread->_threadId);
}
- if (thread->_type == kTTTalkThread) {
- thread->_callingThreadId = 0;
- // TODO script_TalkThreads_sub_417F60(thread->_threadId, 0);
- // TODO script_TalkThreads_sub_417FA0(thread->_threadId, 0);
- } else {
- // TODO artmgrThreadIsDead(thread->threadId);
- thread->terminate();
- }
+ thread->onKill();
}
@@ -274,4 +276,12 @@ uint32 ThreadList::getThreadSceneId(uint32 threadId) {
return thread ? thread->_tag : 0;
}
+bool ThreadList::isActiveThread(int msgNum) {
+ // Check if at least one thread returns a non-null value for the message
+ for (Iterator it = _threads.begin(); it != _threads.end(); ++it)
+ if ((*it)->sendMessage(msgNum, 0) != 0)
+ return true;
+ return false;
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/thread.h b/engines/illusions/thread.h
index fc1a059e2f..2cd3cc2a98 100644
--- a/engines/illusions/thread.h
+++ b/engines/illusions/thread.h
@@ -54,6 +54,8 @@ public:
virtual void onPause();
virtual void onResume();
virtual void onTerminated();
+ virtual void onKill();
+ virtual uint32 sendMessage(int msgNum, uint32 msgValue);
void pause();
void resume();
void suspend();
@@ -93,6 +95,7 @@ public:
void killThread(uint32 threadId);
void setThreadSceneId(uint32 threadId, uint32 sceneId);
uint32 getThreadSceneId(uint32 threadId);
+ bool isActiveThread(int msgNum);
protected:
typedef Common::List<Thread*> List;
typedef List::iterator Iterator;