diff options
Diffstat (limited to 'engines/illusions/bbdou')
-rw-r--r-- | engines/illusions/bbdou/bbdou_inventory.cpp | 123 | ||||
-rw-r--r-- | engines/illusions/bbdou/bbdou_inventory.h | 6 | ||||
-rw-r--r-- | engines/illusions/bbdou/bbdou_specialcode.cpp | 60 | ||||
-rw-r--r-- | engines/illusions/bbdou/bbdou_specialcode.h | 5 |
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 |