diff options
author | johndoe123 | 2014-03-28 21:53:21 +0100 |
---|---|---|
committer | Eugene Sandulenko | 2018-07-20 06:43:33 +0000 |
commit | 3b3f84c764f8cab8f54b06bbafc607cfb6899fdd (patch) | |
tree | 8ef0d8e3af51b7e0a4f232e36c250aa89aeae655 /engines | |
parent | 33d28deb690c79a6aca190c5b1bc998c39d95662 (diff) | |
download | scummvm-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')
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; |