aboutsummaryrefslogtreecommitdiff
path: root/engines/illusions/bbdou
diff options
context:
space:
mode:
Diffstat (limited to 'engines/illusions/bbdou')
-rw-r--r--engines/illusions/bbdou/bbdou_inventory.cpp123
-rw-r--r--engines/illusions/bbdou/bbdou_inventory.h6
-rw-r--r--engines/illusions/bbdou/bbdou_specialcode.cpp60
-rw-r--r--engines/illusions/bbdou/bbdou_specialcode.h5
4 files changed, 185 insertions, 9 deletions
diff --git a/engines/illusions/bbdou/bbdou_inventory.cpp b/engines/illusions/bbdou/bbdou_inventory.cpp
index 4c5646f5b7..5502616337 100644
--- a/engines/illusions/bbdou/bbdou_inventory.cpp
+++ b/engines/illusions/bbdou/bbdou_inventory.cpp
@@ -28,9 +28,12 @@
#include "illusions/camera.h"
#include "illusions/dictionary.h"
#include "illusions/input.h"
+#include "illusions/scriptman.h"
namespace Illusions {
+typedef Common::Functor2Mem<TriggerFunction*, uint32, void, BbdouInventory> InventoryTriggerFunctionCallback;
+
// InventoryItem
InventoryItem::InventoryItem(uint32 objectId, uint32 sequenceId)
@@ -71,7 +74,9 @@ bool InventoryBag::addInventoryItem(InventoryItem *inventoryItem, InventorySlot
}
void InventoryBag::removeInventoryItem(InventoryItem *inventoryItem) {
- // TODO
+ for (InventorySlotsIterator it = _inventorySlots.begin(); it != _inventorySlots.end(); ++it)
+ if ((*it)->_inventoryItem && (*it)->_inventoryItem->_objectId == inventoryItem->_objectId)
+ (*it)->_inventoryItem = 0;
}
void InventoryBag::buildItems() {
@@ -87,12 +92,34 @@ void InventoryBag::buildItems() {
}
}
+InventorySlot *InventoryBag::getInventorySlot(uint32 objectId) {
+ for (uint i = 0; i < _inventorySlots.size(); ++i)
+ if (_inventorySlots[i]->_objectId == objectId)
+ return _inventorySlots[i];
+ return 0;
+}
+
+InventorySlot *InventoryBag::findClosestSlot(Common::Point putPos, int index) {
+ uint minDistance = 0xFFFFFFFF;
+ InventorySlot *minDistanceSlot = 0;
+ for (InventorySlotsIterator it = _inventorySlots.begin(); it != _inventorySlots.end(); ++it) {
+ InventorySlot *inventorySlot = *it;
+ Common::Point slotPos = _vm->getNamedPointPosition(inventorySlot->_namedPointId);
+ uint currDistance = (slotPos.y - putPos.y) * (slotPos.y - putPos.y) + (slotPos.x - putPos.x) * (slotPos.x - putPos.x);
+ if (currDistance < minDistance) {
+ minDistance = currDistance;
+ minDistanceSlot = inventorySlot;
+ }
+ }
+ return minDistanceSlot;
+}
+
// 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;
@@ -158,9 +185,9 @@ void BbdouInventory::open() {
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);
+ _vm->causeDeclare(0x1B0002, 0, inventorySlot->_objectId, new InventoryTriggerFunctionCallback(this, &BbdouInventory::cause0x1B0002));
+ _vm->causeDeclare(0x1B0001, 0, inventorySlot->_objectId, new InventoryTriggerFunctionCallback(this, &BbdouInventory::cause0x1B0001));
+ _vm->causeDeclare(0x1B0008, 0, inventorySlot->_objectId, new InventoryTriggerFunctionCallback(this, &BbdouInventory::cause0x1B0001));
}
refresh();
}
@@ -175,7 +202,7 @@ void BbdouInventory::close() {
InventorySlot *inventorySlot = *it;
Control *control = _vm->_dict->getObjectControl(inventorySlot->_objectId);
control->startSequenceActor(0x00060187, 2, 0);
- }
+ }
inventoryBag->_isActive = false;
_activeInventorySceneId = 0;
}
@@ -225,4 +252,88 @@ void BbdouInventory::buildItems(InventoryBag *inventoryBag) {
}
}
+void BbdouInventory::cause0x1B0001(TriggerFunction *triggerFunction, uint32 callingThreadId) {
+ // TODO
+ debug("cause0x1B0001");
+ uint32 foundSceneId, foundVerbId, foundObjectId2, foundObjectId;
+ bool found;
+ InventoryBag *inventoryBag = getInventoryBag(_activeInventorySceneId);
+ InventorySlot *inventorySlot = inventoryBag->getInventorySlot(triggerFunction->_objectId);
+ uint32 objectId = inventorySlot->_inventoryItem->_objectId;
+
+ foundSceneId = _activeInventorySceneId;
+ foundVerbId = triggerFunction->_verbId;
+ foundObjectId2 = 0;
+
+ if (triggerFunction->_verbId == 0x1B0008) {
+ foundVerbId = 0x1B0003;
+ foundObjectId2 = _bbdou->_cursor->_data._holdingObjectId;
+ }
+
+ if (_vm->causeIsDeclared(_activeInventorySceneId, foundVerbId, foundObjectId2, objectId)) {
+ foundSceneId = _activeInventorySceneId;
+ foundObjectId = objectId;
+ found = true;
+ } else if (foundVerbId == 0x1B0003 && _vm->causeIsDeclared(_activeInventorySceneId, 0x1B0008, 0, objectId)) {
+ foundSceneId = _activeInventorySceneId;
+ foundVerbId = 0x1B0008;
+ foundObjectId2 = 0;
+ foundObjectId = objectId;
+ found = true;
+ } else if (_vm->causeIsDeclared(_activeInventorySceneId, foundVerbId, foundObjectId2, 0x40001)) {
+ foundSceneId = _activeInventorySceneId;
+ foundObjectId = 0x40001;
+ found = true;
+ } else if (_vm->causeIsDeclared(0x10003, foundVerbId, foundObjectId2, objectId)) {
+ foundSceneId = 0x10003;
+ foundObjectId = objectId;
+ found = true;
+ } else if (foundVerbId == 0x1B0003 && _vm->causeIsDeclared(0x10003, 0x1B0008, 0, objectId)) {
+ foundSceneId = 0x10003;
+ foundVerbId = 0x1B0008;
+ foundObjectId2 = 0;
+ foundObjectId = objectId;
+ found = true;
+ } else if (_vm->causeIsDeclared(0x10003, foundVerbId, foundObjectId2, 0x40001)) {
+ foundSceneId = 0x10003;
+ foundObjectId = 0x40001;
+ found = true;
+ }
+
+ if (found)
+ _vm->causeTrigger(foundSceneId, foundVerbId, foundObjectId2, foundObjectId, callingThreadId);
+ else
+ _vm->notifyThreadId(callingThreadId);
+
+}
+
+void BbdouInventory::cause0x1B0002(TriggerFunction *triggerFunction, uint32 callingThreadId) {
+ InventoryBag *inventoryBag = getInventoryBag(_activeInventorySceneId);
+ InventorySlot *inventorySlot = inventoryBag->getInventorySlot(triggerFunction->_objectId);
+ uint32 objectId = inventorySlot->_inventoryItem->_objectId;
+ if (_vm->causeIsDeclared(_activeInventorySceneId, triggerFunction->_verbId, 0, objectId)) {
+ _vm->causeTrigger(_activeInventorySceneId, triggerFunction->_verbId, 0, objectId, callingThreadId);
+ } else {
+ _bbdou->startHoldingObjectId(0x4001A, objectId, 0);
+ _vm->notifyThreadId(callingThreadId);
+ }
+}
+
+void BbdouInventory::putBackInventoryItem(uint32 objectId, Common::Point cursorPosition) {
+ InventoryItem *inventoryItem = getInventoryItem(objectId);
+ bool flag = inventoryItem->_flag;
+ inventoryItem->_flag = false;
+ if (!flag && !inventoryItem->_assigned)
+ return;
+ for (uint i = 0; i < _inventoryBags.size(); ++i) {
+ if (_inventoryBags[i]->_sceneId == _activeInventorySceneId) {
+ InventorySlot *inventorySlot = _inventoryBags[i]->findClosestSlot(cursorPosition, _index);
+ _inventoryBags[i]->addInventoryItem(inventoryItem, inventorySlot);
+ } else {
+ debug("putBackInventoryItem OTHER STUFF TODO");
+ }
+ }
+ refresh();
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_inventory.h b/engines/illusions/bbdou/bbdou_inventory.h
index a983212114..3c211e5340 100644
--- a/engines/illusions/bbdou/bbdou_inventory.h
+++ b/engines/illusions/bbdou/bbdou_inventory.h
@@ -32,6 +32,7 @@ namespace Illusions {
class IllusionsEngine;
class BbdouSpecialCode;
class Control;
+class TriggerFunction;
struct InventoryItem {
uint32 _objectId;
@@ -57,6 +58,8 @@ public:
bool addInventoryItem(InventoryItem *inventoryItem, InventorySlot *inventorySlot);
void removeInventoryItem(InventoryItem *inventoryItem);
void buildItems();
+ InventorySlot *getInventorySlot(uint32 objectId);
+ InventorySlot *findClosestSlot(Common::Point putPos, int index);
protected:
public:
typedef Common::Array<InventorySlot*> InventorySlots;
@@ -82,6 +85,9 @@ public:
InventoryItem *getInventoryItem(uint32 objectId);
void refresh();
void buildItems(InventoryBag *inventoryBag);
+ void cause0x1B0001(TriggerFunction *triggerFunction, uint32 callingThreadId);
+ void cause0x1B0002(TriggerFunction *triggerFunction, uint32 callingThreadId);
+ void putBackInventoryItem(uint32 objectId, Common::Point cursorPosition);
protected:
typedef Common::Array<InventoryItem*> InventoryItems;
typedef InventoryItems::iterator InventoryItemsIterator;
diff --git a/engines/illusions/bbdou/bbdou_specialcode.cpp b/engines/illusions/bbdou/bbdou_specialcode.cpp
index c74676d168..1547aabf1b 100644
--- a/engines/illusions/bbdou/bbdou_specialcode.cpp
+++ b/engines/illusions/bbdou/bbdou_specialcode.cpp
@@ -92,6 +92,8 @@ void BbdouSpecialCode::init() {
SPECIAL(0x00160008, spcEnableCursor);
SPECIAL(0x00160009, spcDisableCursor);
SPECIAL(0x0016000A, spcAddCursorSequence);
+ SPECIAL(0x0016000B, spcCursorStartHoldingObjectId);
+ SPECIAL(0x0016000C, spcCursorStopHoldingObjectId);
SPECIAL(0x00160013, spcInitBubble);
SPECIAL(0x00160014, spcSetupBubble);
SPECIAL(0x00160015, spcSetObjectInteractMode);
@@ -100,6 +102,7 @@ void BbdouSpecialCode::init() {
SPECIAL(0x0016001B, spcRegisterInventoryItem);
SPECIAL(0x0016001C, spcOpenInventory);
SPECIAL(0x0016001D, spcAddInventoryItem);
+ SPECIAL(0x0016001E, spcRemoveInventoryItem);
SPECIAL(0x00160025, spcCloseInventory);
}
@@ -148,6 +151,22 @@ void BbdouSpecialCode::spcAddCursorSequence(OpCall &opCall) {
_vm->notifyThreadId(opCall._callerThreadId);
}
+void BbdouSpecialCode::spcCursorStartHoldingObjectId(OpCall &opCall) {
+ ARG_UINT32(objectId);
+ ARG_UINT32(holdingObjectId);
+ ARG_INT16(doPlaySound);
+ startHoldingObjectId(objectId, holdingObjectId, doPlaySound != 0);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcCursorStopHoldingObjectId(OpCall &opCall) {
+ ARG_UINT32(objectId);
+ ARG_INT16(doPlaySound);
+ stopHoldingObjectId(objectId, doPlaySound != 0);
+ _cursor->_data._mode = 1;
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
void BbdouSpecialCode::spcInitBubble(OpCall &opCall) {
_bubble->init();
_vm->notifyThreadId(opCall._callerThreadId);
@@ -194,10 +213,14 @@ void BbdouSpecialCode::spcOpenInventory(OpCall &opCall) {
void BbdouSpecialCode::spcAddInventoryItem(OpCall &opCall) {
ARG_UINT32(objectId);
-debug("### spcAddInventoryItem %08X", objectId);
_inventory->addInventoryItem(objectId);
}
+void BbdouSpecialCode::spcRemoveInventoryItem(OpCall &opCall) {
+ ARG_UINT32(objectId);
+ _inventory->removeInventoryItem(objectId);
+}
+
void BbdouSpecialCode::spcCloseInventory(OpCall &opCall) {
_inventory->close();
}
@@ -531,7 +554,7 @@ bool BbdouSpecialCode::getCause(uint32 sceneId, uint32 verbId, uint32 objectId2,
}
if (success) {
- debug("getCause() -> %08X %08X %08X", outVerbId, outObjectId2, outObjectId);
+ //debug("getCause() -> %08X %08X %08X", outVerbId, outObjectId2, outObjectId);
}
return success;
@@ -539,7 +562,7 @@ bool BbdouSpecialCode::getCause(uint32 sceneId, uint32 verbId, uint32 objectId2,
bool BbdouSpecialCode::runCause(Control *cursorControl, CursorData &cursorData,
uint32 verbId, uint32 objectId2, uint32 objectId, int soundIndex) {
- debug("runCause(%08X, %08X, %08X)", verbId, objectId2, objectId);
+ //debug("runCause(%08X, %08X, %08X)", verbId, objectId2, objectId);
uint32 sceneId = _vm->getCurrentScene();
uint32 outVerbId, outObjectId2, outObjectId;
bool success = false;
@@ -584,4 +607,35 @@ uint32 BbdouSpecialCode::startCauseThread(uint32 cursorObjectId, uint32 sceneId,
return tempThreadId;
}
+void BbdouSpecialCode::startHoldingObjectId(uint32 objectId1, uint32 holdingObjectId, bool doPlaySound) {
+ Control *control = _vm->_dict->getObjectControl(objectId1);
+ if (_cursor->_data._holdingObjectId)
+ _inventory->putBackInventoryItem(_cursor->_data._holdingObjectId, control->_actor->_position);
+ _cursor->_data._holdingObjectId = holdingObjectId;
+ _cursor->_data._sequenceId = _cursor->findCursorSequenceId(holdingObjectId);
+ if (_cursor->_data._visibleCtr > 0)
+ _cursor->show(control);
+ _cursor->_data._mode = 2;
+ _cursor->_data._item10._verbId = 0x1B0003;
+ if (!doPlaySound)
+ playSoundEffect(5);
+ _inventory->removeInventoryItem(holdingObjectId);
+}
+
+void BbdouSpecialCode::stopHoldingObjectId(uint32 objectId1, bool doPlaySound) {
+ Control *control = _vm->_dict->getObjectControl(objectId1);
+ uint32 holdingObjectId = _cursor->_data._holdingObjectId;
+ _cursor->_data._holdingObjectId = 0;
+ _cursor->_data._sequenceId = 0x6000F;
+ if (!doPlaySound && holdingObjectId)
+ playSoundEffect(6);
+ if (_cursor->_data._visibleCtr > 0)
+ _cursor->show(control);
+ _cursor->_data._item10._verbId = 0x1B0001;
+ if (_cursor->_data._mode == 3)
+ holdingObjectId = _cursor->_data._holdingObjectId2;
+ if (holdingObjectId)
+ _inventory->putBackInventoryItem(holdingObjectId, control->_actor->_position);
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_specialcode.h b/engines/illusions/bbdou/bbdou_specialcode.h
index dcfb5baf63..d018f3859d 100644
--- a/engines/illusions/bbdou/bbdou_specialcode.h
+++ b/engines/illusions/bbdou/bbdou_specialcode.h
@@ -81,6 +81,8 @@ public:
void spcEnableCursor(OpCall &opCall);
void spcDisableCursor(OpCall &opCall);
void spcAddCursorSequence(OpCall &opCall);
+ void spcCursorStartHoldingObjectId(OpCall &opCall);
+ void spcCursorStopHoldingObjectId(OpCall &opCall);
void spcInitBubble(OpCall &opCall);
void spcSetupBubble(OpCall &opCall);
void spcSetObjectInteractMode(OpCall &opCall);
@@ -89,10 +91,13 @@ public:
void spcRegisterInventoryItem(OpCall &opCall);
void spcOpenInventory(OpCall &opCall);
void spcAddInventoryItem(OpCall &opCall);
+ void spcRemoveInventoryItem(OpCall &opCall);
void spcCloseInventory(OpCall &opCall);
void playSoundEffect(int soundIndex);
void resetItem10(uint32 objectId, Item10 *item10);
+ void startHoldingObjectId(uint32 objectId1, uint32 holdingObjectId, bool doPlaySound);
+ void stopHoldingObjectId(uint32 objectId1, bool doPlaySound);
protected:
// Internal functions