aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjohndoe1232014-03-30 09:31:53 +0200
committerEugene Sandulenko2018-07-20 06:43:33 +0000
commitbabe997295dbadd95ab497bc6b88e7a0021567e5 (patch)
treee61eb739a3d3f92f8d7e731d3684757932f70652
parent3b3f84c764f8cab8f54b06bbafc607cfb6899fdd (diff)
downloadscummvm-rg350-babe997295dbadd95ab497bc6b88e7a0021567e5.tar.gz
scummvm-rg350-babe997295dbadd95ab497bc6b88e7a0021567e5.tar.bz2
scummvm-rg350-babe997295dbadd95ab497bc6b88e7a0021567e5.zip
ILLUSIONS: Add more script opcodes
- Add support for duplicate keys to the dictionary - Add trigger functions support - Improve inventory, now items can be clicked
-rw-r--r--engines/illusions/actor.cpp50
-rw-r--r--engines/illusions/actor.h2
-rw-r--r--engines/illusions/actorresource.cpp2
-rw-r--r--engines/illusions/backgroundresource.cpp12
-rw-r--r--engines/illusions/bbdou/bbdou_inventory.cpp123
-rw-r--r--engines/illusions/bbdou/bbdou_inventory.h6
-rw-r--r--engines/illusions/bbdou/bbdou_specialcode.cpp60
-rw-r--r--engines/illusions/bbdou/bbdou_specialcode.h5
-rw-r--r--engines/illusions/dictionary.h36
-rw-r--r--engines/illusions/illusions.cpp27
-rw-r--r--engines/illusions/illusions.h8
-rw-r--r--engines/illusions/scriptman.cpp77
-rw-r--r--engines/illusions/scriptman.h30
-rw-r--r--engines/illusions/scriptopcodes.cpp65
-rw-r--r--engines/illusions/scriptopcodes.h6
-rw-r--r--engines/illusions/sequenceopcodes.cpp39
-rw-r--r--engines/illusions/sequenceopcodes.h7
-rw-r--r--engines/illusions/talkresource.cpp2
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<Control*, uint32, void, Cursor>(_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<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
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 T>
class DictionaryHashMap {
+protected:
+ typedef Common::List<T*> List;
+ typedef typename List::iterator ListIterator;
+ typedef Common::HashMap<uint32, List*> 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<uint32, T*>::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<uint32, T*> _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<TriggerFunction*, uint32, void> 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<ActiveScene, 16> _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<TriggerFunction*> 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);
}