From babe997295dbadd95ab497bc6b88e7a0021567e5 Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Sun, 30 Mar 2014 09:31:53 +0200 Subject: ILLUSIONS: Add more script opcodes - Add support for duplicate keys to the dictionary - Add trigger functions support - Improve inventory, now items can be clicked --- engines/illusions/actor.cpp | 50 +++++++++++ engines/illusions/actor.h | 2 + engines/illusions/actorresource.cpp | 2 +- engines/illusions/backgroundresource.cpp | 12 +-- engines/illusions/bbdou/bbdou_inventory.cpp | 123 ++++++++++++++++++++++++-- engines/illusions/bbdou/bbdou_inventory.h | 6 ++ engines/illusions/bbdou/bbdou_specialcode.cpp | 60 ++++++++++++- engines/illusions/bbdou/bbdou_specialcode.h | 5 ++ engines/illusions/dictionary.h | 36 ++++++-- engines/illusions/illusions.cpp | 27 ++++-- engines/illusions/illusions.h | 8 +- engines/illusions/scriptman.cpp | 77 ++++++++++++++-- engines/illusions/scriptman.h | 30 ++++++- engines/illusions/scriptopcodes.cpp | 65 +++++++++++++- engines/illusions/scriptopcodes.h | 6 ++ engines/illusions/sequenceopcodes.cpp | 39 ++++++++ engines/illusions/sequenceopcodes.h | 7 +- engines/illusions/talkresource.cpp | 2 +- 18 files changed, 518 insertions(+), 39 deletions(-) diff --git a/engines/illusions/actor.cpp b/engines/illusions/actor.cpp index 53190ef97b..d9eb94975f 100644 --- a/engines/illusions/actor.cpp +++ b/engines/illusions/actor.cpp @@ -30,6 +30,8 @@ #include "illusions/scriptman.h" #include "illusions/scriptopcodes.h" #include "illusions/sequenceopcodes.h" +#include "illusions/talkthread.h" +#include "illusions/thread.h" namespace Illusions { @@ -641,6 +643,51 @@ void Control::setActorIndexTo2() { _actor->_actorIndex = 2; } +void Control::startSubSequence(int linkIndex, uint32 sequenceId) { + Control *linkedControl = _vm->_dict->getObjectControl(_actor->_subobjects[linkIndex - 1]); + Actor *linkedActor = linkedControl->_actor; + if (!linkedActor->_entryTblPtr) + linkedActor->_flags &= ~0x80; + linkedActor->_flags &= ~0x400; + linkedActor->_flags |= 0x100; + linkedActor->_sequenceId = sequenceId; + linkedActor->_notifyThreadId1 = 0; + linkedActor->_notifyId3C = 0; + linkedActor->_path40 = 0; + + Sequence *sequence = _vm->_dict->findSequence(sequenceId); + linkedActor->_seqCodeIp = sequence->_sequenceCode; + linkedActor->_frames = _vm->_actorItems->findSequenceFrames(sequence); + linkedActor->_seqCodeValue3 = 0; + linkedActor->_seqCodeValue1 = 0; + linkedActor->_seqCodeValue2 = 600; + linkedActor->initSequenceStack(); + linkedControl->sequenceActor(); + linkedControl->appearActor(); +} + +void Control::stopSubSequence(int linkIndex) { + Control *linkedControl = _vm->_dict->getObjectControl(_actor->_subobjects[linkIndex - 1]); + Actor *linkedActor = linkedControl->_actor; + uint32 notifySequenceId2 = _actor->_notifyThreadId2; + _actor->_linkIndex2 = linkIndex; + if (_actor->_entryTblPtr) { + linkedActor->_flags |= 0x80; + linkedActor->_entryTblPtr = _actor->_entryTblPtr; + linkedActor->_notifyThreadId2 = _actor->_notifyThreadId2; + linkedActor->_seqCodeValue1 = _actor->_seqCodeValue1; + linkedActor->_seqCodeValue3 = _actor->_seqCodeValue3; + _actor->_flags &= ~0x80; + _actor->_entryTblPtr = 0; + _actor->_notifyThreadId1 = 0; + _actor->_notifyThreadId2 = 0; + } + if (notifySequenceId2) { + Thread *talkThread = _vm->_scriptMan->_threads->findThread(notifySequenceId2); + talkThread->sendMessage(kMsgClearSequenceId2, 0); + } +} + void Control::startSequenceActorIntern(uint32 sequenceId, int value, byte *entryTblPtr, uint32 notifyThreadId) { stopActor(); @@ -710,6 +757,7 @@ void Controls::placeActor(uint32 actorTypeId, Common::Point placePt, uint32 sequ Actor *actor = newActor(); ActorType *actorType = _vm->_dict->findActorType(actorTypeId); + control->_objectId = objectId; control->_flags = actorType->_flags; control->_priority = actorType->_priority; @@ -718,11 +766,13 @@ void Controls::placeActor(uint32 actorTypeId, Common::Point placePt, uint32 sequ control->_actor = actor; if (actorTypeId == 0x50001 && objectId == 0x40004) actor->setControlRoutine(new Common::Functor2Mem(_vm->_cursor, &Cursor::cursorControlRoutine)); + if (actorType->_surfInfo._dimensions._width > 0 || actorType->_surfInfo._dimensions._height > 0) { actor->createSurface(actorType->_surfInfo); } else { actor->_flags |= 0x0200; } + actor->_position = placePt; actor->_position2 = placePt; Common::Point currPan = _vm->_camera->getCurrentPan(); diff --git a/engines/illusions/actor.h b/engines/illusions/actor.h index 7e3bc7f228..50d3f7c1c8 100644 --- a/engines/illusions/actor.h +++ b/engines/illusions/actor.h @@ -174,6 +174,8 @@ public: void sequenceActor(); void setActorIndexTo1(); void setActorIndexTo2(); + void startSubSequence(int linkIndex, uint32 sequenceId); + void stopSubSequence(int linkIndex); public: IllusionsEngine *_vm; uint _flags; diff --git a/engines/illusions/actorresource.cpp b/engines/illusions/actorresource.cpp index affca78879..058b093ac6 100644 --- a/engines/illusions/actorresource.cpp +++ b/engines/illusions/actorresource.cpp @@ -140,7 +140,7 @@ void ActorType::load(byte *dataStart, Common::SeekableReadStream &stream) { _pathWalkPointsIndex, _scaleLayerIndex, _pathWalkRectIndex); debug(5, "ActorType::load() _priorityLayerIndex: %d; _regionLayerIndex: %d; _flags: %04X", _priorityLayerIndex, _regionLayerIndex,_flags); - + } // ActorResource diff --git a/engines/illusions/backgroundresource.cpp b/engines/illusions/backgroundresource.cpp index 50a88d284a..754b9d2e80 100644 --- a/engines/illusions/backgroundresource.cpp +++ b/engines/illusions/backgroundresource.cpp @@ -66,6 +66,7 @@ void BackgroundResourceLoader::unload(Resource *resource) { delete backgroundItem->_bgRes; _vm->_backgroundItems->freeBackgroundItem(backgroundItem); // TODO _vm->setDefPointDimensions1(); + debug("BackgroundResourceLoader::unload() Unloading background %08X OK", resource->_resId); } void BackgroundResourceLoader::buildFilename(Resource *resource) { @@ -272,11 +273,12 @@ void BackgroundItem::initSurface() { } void BackgroundItem::freeSurface() { - for (uint i = 0; i < _bgRes->_bgInfosCount; ++i) { - _surfaces[i]->free(); - delete _surfaces[i]; - _surfaces[i] = 0; - } + for (uint i = 0; i < _bgRes->_bgInfosCount; ++i) + if (_surfaces[i]) { + _surfaces[i]->free(); + delete _surfaces[i]; + _surfaces[i] = 0; + } } void BackgroundItem::drawTiles(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) { 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 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 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 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 diff --git a/engines/illusions/dictionary.h b/engines/illusions/dictionary.h index 6bdc539725..11b05a6348 100644 --- a/engines/illusions/dictionary.h +++ b/engines/illusions/dictionary.h @@ -34,25 +34,49 @@ class TalkEntry; template class DictionaryHashMap { +protected: + typedef Common::List List; + typedef typename List::iterator ListIterator; + typedef Common::HashMap Map; + typedef typename Map::iterator MapIterator; + Map _map; public: + ~DictionaryHashMap() { + for (MapIterator it = _map.begin(); it != _map.end(); ++it) + delete it->_value; + } + void add(uint32 id, T *value) { - _map[id] = value; + MapIterator it = _map.find(id); + List *list; + if (it != _map.end()) + list = it->_value; + else { + list = new List(); + _map[id] = list; + } + list->push_back(value); } void remove(uint32 id) { - _map.erase(id); + MapIterator it = _map.find(id); + List *list; + if (it != _map.end()) { + list = it->_value; + list->pop_back(); + if (list->empty()) + _map.erase(id); + } } T *find(uint32 id) { - typename Common::HashMap::iterator it = _map.find(id); + MapIterator it = _map.find(id); if (it != _map.end()) - return it->_value; + return it->_value->back(); return 0; } -protected: - Common::HashMap _map; }; class Dictionary { diff --git a/engines/illusions/illusions.cpp b/engines/illusions/illusions.cpp index 968dc0f583..99b7b19a16 100644 --- a/engines/illusions/illusions.cpp +++ b/engines/illusions/illusions.cpp @@ -107,6 +107,7 @@ Common::Error IllusionsEngine::run() { _controls = new Controls(this); _cursor = new Cursor(this); _talkItems = new TalkItems(this); + _triggerFunctions = new TriggerFunctions(); // TODO Move to own class _resGetCtr = 0; @@ -117,7 +118,9 @@ Common::Error IllusionsEngine::run() { // Actor/graphics/script test /* TODO 0x0010000B LinkIndex 0x00060AAB 0x00060556 - */ + */ + + _scriptMan->_globalSceneId = 0x00010003; _resSys->loadResource(0x000D0001, 0, 0); @@ -136,6 +139,7 @@ Common::Error IllusionsEngine::run() { } #endif + delete _triggerFunctions; delete _talkItems; delete _cursor; delete _controls; @@ -276,7 +280,7 @@ int IllusionsEngine::updateGraphics() { uint32 priority = control->getPriority(); _screen->_drawQueue->insertSprite(&actor->_drawFlags, actor->_surface, actor->_surfInfo._dimensions, drawPosition, control->_position, - priority, actor->_scale, actor->_spriteFlags); + priority, 100/*actor->_scale TODO DEBUG*/, actor->_spriteFlags); } } } @@ -298,19 +302,26 @@ int IllusionsEngine::getRandom(int max) { bool IllusionsEngine::causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { uint32 codeOffs; - // TODO Also search for native trigger functions later (findCauseFunc) - bool r = _scriptMan->findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs); + bool r = + _triggerFunctions->find(sceneId, verbId, objectId2, objectId) || + _scriptMan->findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs); debug(3, "causeIsDeclared() sceneId: %08X; verbId: %08X; objectId2: %08X; objectId: %08X -> %d", sceneId, verbId, objectId2, objectId, r); return r; } +void IllusionsEngine::causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) { + _triggerFunctions->add(getCurrentScene(), verbId, objectId2, objectId, callback); +} + uint32 IllusionsEngine::causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId) { uint32 codeOffs; 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); + TriggerFunction *triggerFunction = _triggerFunctions->find(sceneId, verbId, objectId2, objectId); + if (triggerFunction) { + triggerFunction->run(callingThreadId); + } else 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); } @@ -329,7 +340,7 @@ Common::Point IllusionsEngine::getNamedPointPosition(uint32 namedPointId) { _controls->findNamedPoint(namedPointId, pt)) return pt; // TODO - debug("getNamedPointPosition(%08X) UNKNOWN", namedPointId); + //debug("getNamedPointPosition(%08X) UNKNOWN", namedPointId); return Common::Point(0, 0); } diff --git a/engines/illusions/illusions.h b/engines/illusions/illusions.h index 58dc519285..cf3549e8bb 100644 --- a/engines/illusions/illusions.h +++ b/engines/illusions/illusions.h @@ -59,6 +59,7 @@ class Control; class Controls; class Cursor; class Dictionary; +class FramesList; class Input; class Screen; class ScriptResource; @@ -66,7 +67,10 @@ class ScriptMan; class Sequence; class SpecialCode; class TalkItems; -class FramesList; +class TriggerFunctions; +class TriggerFunction; + +typedef Common::Functor2 TriggerFunctionCallback; class IllusionsEngine : public Engine { protected: @@ -97,6 +101,7 @@ public: Cursor *_cursor; TalkItems *_talkItems; SpecialCode *_specialCode; + TriggerFunctions *_triggerFunctions; int _resGetCtr; uint32 _resGetTime; @@ -115,6 +120,7 @@ public: // TODO Move to ScriptMan? bool causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); + void causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback); uint32 causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId); int convertPanXCoord(int16 x); diff --git a/engines/illusions/scriptman.cpp b/engines/illusions/scriptman.cpp index 961ffd4579..20749438d1 100644 --- a/engines/illusions/scriptman.cpp +++ b/engines/illusions/scriptman.cpp @@ -61,15 +61,15 @@ void ActiveScenes::unpauseActiveScene() { --_stack.top()._pauseCtr; } -int ActiveScenes::getActiveScenesCount() { +uint ActiveScenes::getActiveScenesCount() { return _stack.size(); } void ActiveScenes::getActiveSceneInfo(uint index, uint32 *sceneId, int *pauseCtr) { if (sceneId) - *sceneId = _stack[index]._sceneId; + *sceneId = _stack[index - 1]._sceneId; if (pauseCtr) - *pauseCtr = _stack[index]._pauseCtr; + *pauseCtr = _stack[index - 1]._pauseCtr; } uint32 ActiveScenes::getCurrentScene() { @@ -85,6 +85,60 @@ bool ActiveScenes::isSceneActive(uint32 sceneId) { return false; } +// TriggerFunction + +TriggerFunction::TriggerFunction(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) + : _sceneId(sceneId), _verbId(verbId), _objectId2(objectId2), _objectId(objectId), _callback(callback) { +} + +TriggerFunction::~TriggerFunction() { + delete _callback; +} + +void TriggerFunction::run(uint32 callingThreadId) { + (*_callback)(this, callingThreadId); +} + +// TriggerFunctions + +void TriggerFunctions::add(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) { + ItemsIterator it = findInternal(sceneId, verbId, objectId2, objectId); + if (it != _triggerFunctions.end()) { + delete *it; + _triggerFunctions.erase(it); + } + _triggerFunctions.push_back(new TriggerFunction(sceneId, verbId, objectId2, objectId, callback)); +} + +TriggerFunction *TriggerFunctions::find(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { + ItemsIterator it = findInternal(sceneId, verbId, objectId2, objectId); + if (it != _triggerFunctions.end()) + return (*it); + return 0; +} + +void TriggerFunctions::removeBySceneId(uint32 sceneId) { + ItemsIterator it = _triggerFunctions.begin(); + while (it != _triggerFunctions.end()) { + if ((*it)->_sceneId == sceneId) { + delete *it; + it = _triggerFunctions.erase(it); + } else + ++it; + } +} + +TriggerFunctions::ItemsIterator TriggerFunctions::findInternal(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { + ItemsIterator it = _triggerFunctions.begin(); + for (; it != _triggerFunctions.end(); ++it) { + TriggerFunction *triggerFunction = *it; + if (triggerFunction->_sceneId == sceneId && triggerFunction->_verbId == verbId && + triggerFunction->_objectId2 == objectId2 && triggerFunction->_objectId == objectId) + break; + } + return it; +} + // ScriptStack ScriptStack::ScriptStack() { @@ -240,7 +294,7 @@ void ScriptMan::reset() { bool ScriptMan::enterScene(uint32 sceneId, uint32 threadId) { ProgInfo *progInfo = _scriptResource->getProgInfo(sceneId & 0xFFFF); if (!progInfo) { - // TODO dumpActiveScenes(_someSceneId2, threadId); + // TODO dumpActiveScenes(_globalSceneId, threadId); sceneId = _theSceneId; } _activeScenes.push(sceneId); @@ -253,7 +307,7 @@ void ScriptMan::exitScene(uint32 threadId) { // TODO UpdateFunctions_disableByTag__TODO_maybe(sceneId); _threads->terminateThreadsByTag(sceneId, threadId); _vm->_controls->destroyControlsByTag(sceneId); - // TODO causeFunc_removeBySceneId(sceneId); + _vm->_triggerFunctions->removeBySceneId(sceneId); _vm->_resSys->unloadResourcesByTag(sceneId); _activeScenes.pop(); } @@ -278,6 +332,19 @@ void ScriptMan::leavePause(uint32 threadId) { _activeScenes.unpauseActiveScene(); } +void ScriptMan::dumpActiveScenes(uint32 sceneId, uint32 threadId) { + uint activeScenesCount = _activeScenes.getActiveScenesCount(); + while (activeScenesCount > 0) { + uint32 activeSceneId; + _activeScenes.getActiveSceneInfo(activeScenesCount, &activeSceneId, 0); + if (activeSceneId == sceneId) + break; + exitScene(threadId); + --activeScenesCount; + } + _vm->_camera->clearCameraModeStack(); +} + void ScriptMan::newScriptThread(uint32 threadId, uint32 callingThreadId, uint notifyFlags, byte *scriptCodeIp, uint32 value8, uint32 valueC, uint32 value10) { ScriptThread *scriptThread = new ScriptThread(_vm, threadId, callingThreadId, notifyFlags, diff --git a/engines/illusions/scriptman.h b/engines/illusions/scriptman.h index adfc365327..6ea28c8272 100644 --- a/engines/illusions/scriptman.h +++ b/engines/illusions/scriptman.h @@ -23,6 +23,7 @@ #ifndef ILLUSIONS_SCRIPTMAN_H #define ILLUSIONS_SCRIPTMAN_H +#include "illusions/illusions.h" #include "illusions/scriptresource.h" #include "illusions/thread.h" #include "common/algorithm.h" @@ -46,7 +47,7 @@ public: void pop(); void pauseActiveScene(); void unpauseActiveScene(); - int getActiveScenesCount(); + uint getActiveScenesCount(); void getActiveSceneInfo(uint index, uint32 *sceneId, int *pauseCtr); uint32 getCurrentScene(); bool isSceneActive(uint32 sceneId); @@ -54,6 +55,31 @@ protected: Common::FixedStack _stack; }; +struct TriggerFunction; + +struct TriggerFunction { + uint32 _sceneId; + uint32 _verbId; + uint32 _objectId2; + uint32 _objectId; + TriggerFunctionCallback *_callback; + TriggerFunction(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback); + ~TriggerFunction(); + void run(uint32 callingThreadId); +}; + +class TriggerFunctions { +public: + void add(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback); + TriggerFunction *find(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); + void removeBySceneId(uint32 sceneId); +public: + typedef Common::List Items; + typedef Items::iterator ItemsIterator; + Items _triggerFunctions; + ItemsIterator findInternal(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); +}; + class ScriptStack { public: ScriptStack(); @@ -92,6 +118,7 @@ public: void exitScene(uint32 threadId); void enterPause(uint32 threadId); void leavePause(uint32 threadId); + void dumpActiveScenes(uint32 sceneId, uint32 threadId); public: IllusionsEngine *_vm; @@ -104,6 +131,7 @@ public: uint32 _theSceneId; uint32 _theThreadId; + uint32 _globalSceneId; bool _doScriptThreadInit; uint32 _nextTempThreadId; diff --git a/engines/illusions/scriptopcodes.cpp b/engines/illusions/scriptopcodes.cpp index fbb9448437..77a7d1f523 100644 --- a/engines/illusions/scriptopcodes.cpp +++ b/engines/illusions/scriptopcodes.cpp @@ -102,7 +102,9 @@ void ScriptOpcodes::initOpcodes() { OPCODE(30, opEnterCloseUpScene); OPCODE(31, opExitCloseUpScene); OPCODE(32, opPanCenterObject); + OPCODE(34, opPanToObject); OPCODE(35, opPanToNamedPoint); + OPCODE(36, opPanToPoint); OPCODE(37, opPanStop); OPCODE(39, opSetDisplay); OPCODE(42, opIncBlockCounter); @@ -137,6 +139,9 @@ void ScriptOpcodes::initOpcodes() { OPCODE(87, opDeactivateButton); OPCODE(88, opActivateButton); OPCODE(103, opJumpIf); + OPCODE(104, opIsPrevSceneId); + OPCODE(105, opIsCurrentSceneId); + OPCODE(106, opIsActiveSceneId); OPCODE(107, opNot); OPCODE(108, opAnd); OPCODE(109, opOr); @@ -156,6 +161,7 @@ void ScriptOpcodes::initOpcodes() { OPCODE(176, opStackPush0); OPCODE(177, opSetFontId); OPCODE(178, opAddMenuKey); + OPCODE(179, opChangeSceneAll); } #undef OPCODE @@ -248,17 +254,30 @@ void ScriptOpcodes::opEnterScene(ScriptThread *scriptThread, OpCall &opCall) { uint scenesCount = _vm->_scriptMan->_activeScenes.getActiveScenesCount(); if (scenesCount > 0) { uint32 currSceneId; - _vm->_scriptMan->_activeScenes.getActiveSceneInfo(scenesCount - 1, &currSceneId, 0); + _vm->_scriptMan->_activeScenes.getActiveSceneInfo(scenesCount, &currSceneId, 0); // TODO krnfileDump(currSceneId); } if (!_vm->_scriptMan->enterScene(sceneId, opCall._callerThreadId)) opCall._result = kTSTerminate; } +//DEBUG Scenes +uint32 dsceneId = 0x00010031, dthreadId = 0x00020036;//MAP +//uint32 dsceneId = 0x00010028, dthreadId = 0x000202A1; +//uint32 dsceneId = 0x00010007, dthreadId = 0x0002000C;//Auditorium +//uint32 dsceneId = 0x0001000B, dthreadId = 0x00020010; + void ScriptOpcodes::opChangeScene(ScriptThread *scriptThread, OpCall &opCall) { ARG_SKIP(2); ARG_UINT32(sceneId); ARG_UINT32(threadId); + + if (dsceneId) { + sceneId = dsceneId; + threadId = dthreadId; + dsceneId = 0; + } + // NOTE Skipped checking for stalled resources _vm->_input->discardButtons(0xFFFF); _vm->_scriptMan->_prevSceneId = _vm->getCurrentScene(); @@ -312,6 +331,14 @@ void ScriptOpcodes::opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall _vm->_camera->panCenterObject(objectId, speed); } +void ScriptOpcodes::opPanToObject(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(speed); + ARG_UINT32(objectId); + Control *control = _vm->_dict->getObjectControl(objectId); + Common::Point pos = control->getActorPosition(); + _vm->_camera->panToPoint(pos, speed, opCall._callerThreadId); +} + void ScriptOpcodes::opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) { ARG_INT16(speed); ARG_UINT32(namedPointId); @@ -319,6 +346,13 @@ void ScriptOpcodes::opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall _vm->_camera->panToPoint(pos, speed, opCall._callerThreadId); } +void ScriptOpcodes::opPanToPoint(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(speed); + ARG_INT16(x); + ARG_INT16(y); + _vm->_camera->panToPoint(Common::Point(x, y), speed, opCall._callerThreadId); +} + void ScriptOpcodes::opPanStop(ScriptThread *scriptThread, OpCall &opCall) { _vm->_camera->stopPan(); } @@ -586,6 +620,21 @@ void ScriptOpcodes::opJumpIf(ScriptThread *scriptThread, OpCall &opCall) { opCall._deltaOfs += jumpOffs; } +void ScriptOpcodes::opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall) { + ARG_UINT32(sceneId); + _vm->_scriptMan->_stack.push(_vm->_scriptMan->_prevSceneId == sceneId ? 1 : 0); +} + +void ScriptOpcodes::opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall) { + ARG_UINT32(sceneId); + _vm->_scriptMan->_stack.push(_vm->getCurrentScene() == sceneId ? 1 : 0); +} + +void ScriptOpcodes::opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall) { + ARG_UINT32(sceneId); + _vm->_scriptMan->_stack.push(_vm->_scriptMan->_activeScenes.isSceneActive(sceneId) ? 1 : 0); +} + void ScriptOpcodes::opNot(ScriptThread *scriptThread, OpCall &opCall) { int16 value = _vm->_scriptMan->_stack.pop(); _vm->_scriptMan->_stack.push(value != 0 ? 0 : 1); @@ -731,4 +780,18 @@ void ScriptOpcodes::opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall) { // TODO _vm->addMenuKey(key, threadId); } +void ScriptOpcodes::opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(sceneId); + ARG_UINT32(threadId); + // NOTE Skipped checking for stalled resources + _vm->_input->discardButtons(0xFFFF); + _vm->_scriptMan->_prevSceneId = _vm->getCurrentScene(); + _vm->_scriptMan->dumpActiveScenes(_vm->_scriptMan->_globalSceneId, opCall._callerThreadId); + _vm->_scriptMan->enterScene(sceneId, opCall._callerThreadId); + // TODO _vm->_gameStates->writeStates(_vm->_scriptMan->_prevSceneId, sceneId, threadId); + _vm->_scriptMan->startAnonScriptThread(threadId, 0, + scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10); +} + } // End of namespace Illusions diff --git a/engines/illusions/scriptopcodes.h b/engines/illusions/scriptopcodes.h index 507d21b5e8..32f23fdff6 100644 --- a/engines/illusions/scriptopcodes.h +++ b/engines/illusions/scriptopcodes.h @@ -77,7 +77,9 @@ protected: void opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall); void opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall); void opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall); + void opPanToObject(ScriptThread *scriptThread, OpCall &opCall); void opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall); + void opPanToPoint(ScriptThread *scriptThread, OpCall &opCall); void opPanStop(ScriptThread *scriptThread, OpCall &opCall); void opSetDisplay(ScriptThread *scriptThread, OpCall &opCall); void opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall); @@ -112,6 +114,9 @@ protected: void opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall); void opActivateButton(ScriptThread *scriptThread, OpCall &opCall); void opJumpIf(ScriptThread *scriptThread, OpCall &opCall); + void opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall); + void opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall); + void opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall); void opNot(ScriptThread *scriptThread, OpCall &opCall); void opAnd(ScriptThread *scriptThread, OpCall &opCall); void opOr(ScriptThread *scriptThread, OpCall &opCall); @@ -131,6 +136,7 @@ protected: void opStackPush0(ScriptThread *scriptThread, OpCall &opCall); void opSetFontId(ScriptThread *scriptThread, OpCall &opCall); void opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall); + void opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall); }; diff --git a/engines/illusions/sequenceopcodes.cpp b/engines/illusions/sequenceopcodes.cpp index 7df968df3d..23d1781902 100644 --- a/engines/illusions/sequenceopcodes.cpp +++ b/engines/illusions/sequenceopcodes.cpp @@ -70,9 +70,12 @@ void SequenceOpcodes::initOpcodes() { OPCODE(15, opSwitchFacing); OPCODE(16, opAppearActor); OPCODE(17, opDisappearActor); + OPCODE(18, opAppearForeignActor); + OPCODE(19, opDisappearForeignActor); OPCODE(28, opNotifyThreadId1); OPCODE(29, opSetPathCtrY); OPCODE(33, opSetPathWalkPoints); + OPCODE(35, opSetScale); OPCODE(36, opSetScaleLayer); OPCODE(38, opSetPathWalkRects); OPCODE(39, opSetPriority); @@ -80,6 +83,8 @@ void SequenceOpcodes::initOpcodes() { OPCODE(50, opPlaySound); OPCODE(51, opStopSound); OPCODE(53, opPlaceSubActor); + OPCODE(54, opStartSubSequence); + OPCODE(55, opStopSubSequence); } #undef OPCODE @@ -219,6 +224,23 @@ void SequenceOpcodes::opDisappearActor(Control *control, OpCall &opCall) { control->_actor->_newFrameIndex = 0; } +void SequenceOpcodes::opAppearForeignActor(Control *control, OpCall &opCall) { + ARG_INT16(foreignObjectNum); + Control *foreignControl = _vm->_dict->getObjectControl(foreignObjectNum | 0x40000); + if (!foreignControl) { + Common::Point pos = _vm->getNamedPointPosition(0x00070023); + _vm->_controls->placeActor(0x00050001, pos, 0x00060001, foreignObjectNum | 0x40000, 0); + foreignControl = _vm->_dict->getObjectControl(foreignObjectNum | 0x40000); + } + foreignControl->appearActor(); +} + +void SequenceOpcodes::opDisappearForeignActor(Control *control, OpCall &opCall) { + ARG_INT16(foreignObjectNum); + Control *foreignControl = _vm->_dict->getObjectControl(foreignObjectNum | 0x40000); + foreignControl->disappearActor(); +} + void SequenceOpcodes::opNotifyThreadId1(Control *control, OpCall &opCall) { _vm->notifyThreadId(control->_actor->_notifyThreadId1); } @@ -235,6 +257,12 @@ void SequenceOpcodes::opSetPathWalkPoints(Control *control, OpCall &opCall) { // TODO control->_actor->_pathWalkPoints = bgRes->getPathWalkPoints(pathWalkPointsIndex - 1); } +void SequenceOpcodes::opSetScale(Control *control, OpCall &opCall) { + ARG_INT16(scale); + control->_actor->_flags &= ~4; + control->setActorScale(scale); +} + void SequenceOpcodes::opSetScaleLayer(Control *control, OpCall &opCall) { ARG_INT16(scaleLayerIndex); BackgroundResource *bgRes = _vm->_backgroundItems->getActiveBgResource(); @@ -290,4 +318,15 @@ void SequenceOpcodes::opPlaceSubActor(Control *control, OpCall &opCall) { _vm->_controls->placeSubActor(control->_objectId, linkIndex, actorTypeId, sequenceId); } +void SequenceOpcodes::opStartSubSequence(Control *control, OpCall &opCall) { + ARG_INT16(linkIndex); + ARG_UINT32(sequenceId); + control->startSubSequence(linkIndex, sequenceId); +} + +void SequenceOpcodes::opStopSubSequence(Control *control, OpCall &opCall) { + ARG_INT16(linkIndex); + control->stopSubSequence(linkIndex); +} + } // End of namespace Illusions diff --git a/engines/illusions/sequenceopcodes.h b/engines/illusions/sequenceopcodes.h index abf1987d89..028d567879 100644 --- a/engines/illusions/sequenceopcodes.h +++ b/engines/illusions/sequenceopcodes.h @@ -60,16 +60,21 @@ protected: void opSwitchFacing(Control *control, OpCall &opCall); void opAppearActor(Control *control, OpCall &opCall); void opDisappearActor(Control *control, OpCall &opCall); + void opAppearForeignActor(Control *control, OpCall &opCall); + void opDisappearForeignActor(Control *control, OpCall &opCall); void opNotifyThreadId1(Control *control, OpCall &opCall); void opSetPathCtrY(Control *control, OpCall &opCall); void opSetPathWalkPoints(Control *control, OpCall &opCall); + void opSetScale(Control *control, OpCall &opCall); void opSetScaleLayer(Control *control, OpCall &opCall); void opSetPathWalkRects(Control *control, OpCall &opCall); void opSetPriority(Control *control, OpCall &opCall); void opSetPriorityLayer(Control *control, OpCall &opCall); void opPlaySound(Control *control, OpCall &opCall); void opStopSound(Control *control, OpCall &opCall); - void opPlaceSubActor(Control *control, OpCall &opCall); + void opPlaceSubActor(Control *control, OpCall &opCall); + void opStartSubSequence(Control *control, OpCall &opCall); + void opStopSubSequence(Control *control, OpCall &opCall); }; diff --git a/engines/illusions/talkresource.cpp b/engines/illusions/talkresource.cpp index 1d17408fa8..0c1108ea27 100644 --- a/engines/illusions/talkresource.cpp +++ b/engines/illusions/talkresource.cpp @@ -78,7 +78,7 @@ void TalkEntry::load(byte *dataStart, Common::SeekableReadStream &stream) { _tblPtr = dataStart + tblOffs; _voiceName = dataStart + voiceNameOffs; - debug("TalkEntry::load() _talkId: %08X; textOffs: %08X; tblOffs: %08X; voiceNameOffs: %08X", + debug(0, "TalkEntry::load() _talkId: %08X; textOffs: %08X; tblOffs: %08X; voiceNameOffs: %08X", _talkId, textOffs, tblOffs, voiceNameOffs); } -- cgit v1.2.3