aboutsummaryrefslogtreecommitdiff
path: root/engines/illusions/bbdou
diff options
context:
space:
mode:
authorjohndoe1232014-03-25 19:57:21 +0100
committerEugene Sandulenko2018-07-20 06:43:33 +0000
commite05a7899755011f860f2b09ce6d5b4e0a15107b9 (patch)
treeb16815bcf51d3b776e63563d04f9997cb4a4567f /engines/illusions/bbdou
parent28cb39eb2b48d8c6e80e35ef6e26e02cc209fc0f (diff)
downloadscummvm-rg350-e05a7899755011f860f2b09ce6d5b4e0a15107b9.tar.gz
scummvm-rg350-e05a7899755011f860f2b09ce6d5b4e0a15107b9.tar.bz2
scummvm-rg350-e05a7899755011f860f2b09ce6d5b4e0a15107b9.zip
ILLUSIONS: More work on BBDOU specific code (cursor, bubble)
- Add input handling code
Diffstat (limited to 'engines/illusions/bbdou')
-rw-r--r--engines/illusions/bbdou/bbdou_bubble.cpp150
-rw-r--r--engines/illusions/bbdou/bbdou_bubble.h81
-rw-r--r--engines/illusions/bbdou/bbdou_cursor.cpp167
-rw-r--r--engines/illusions/bbdou/bbdou_cursor.h77
-rw-r--r--engines/illusions/bbdou/bbdou_specialcode.cpp304
-rw-r--r--engines/illusions/bbdou/bbdou_specialcode.h33
6 files changed, 806 insertions, 6 deletions
diff --git a/engines/illusions/bbdou/bbdou_bubble.cpp b/engines/illusions/bbdou/bbdou_bubble.cpp
new file mode 100644
index 0000000000..3256bc404d
--- /dev/null
+++ b/engines/illusions/bbdou/bbdou_bubble.cpp
@@ -0,0 +1,150 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "illusions/illusions.h"
+#include "illusions/bbdou/bbdou_bubble.h"
+#include "illusions/actor.h"
+#include "illusions/camera.h"
+#include "illusions/dictionary.h"
+#include "illusions/input.h"
+
+namespace Illusions {
+
+BbdouBubble::BbdouBubble(IllusionsEngine *vm, BbdouSpecialCode *bbdou)
+ : _vm(vm), _bbdou(bbdou) {
+}
+
+BbdouBubble::~BbdouBubble() {
+}
+
+void BbdouBubble::init() {
+
+ static const uint32 kObjectIds3[] = {
+ 0x0004003B, 0x0004003C, 0x0004003D, 0x0004003E,
+ 0x0004003F, 0x00040040, 0x00040041, 0x00040042,
+ 0x00040043, 0x00040044, 0x00040045, 0x00040046,
+ 0x00040047, 0x00040048, 0x00040049, 0x0004004A,
+ 0x0004004B, 0x0004004C, 0x0004004D, 0x0004004E,
+ 0x0004004F, 0x00040050, 0x00040051, 0x00040052,
+ 0x00040053, 0x00040054, 0x00040055, 0x00040056,
+ 0x00040057, 0x00040058, 0x00040059, 0x0004005A
+ };
+
+ static const uint32 kObjectIds2[] = {
+ 0x0004001B, 0x0004001C, 0x0004001D, 0x0004001E,
+ 0x0004001F, 0x00040020, 0x00040021, 0x00040022,
+ 0x00040023, 0x00040024, 0x00040025, 0x00040026,
+ 0x00040027, 0x00040028, 0x00040029, 0x0004002A,
+ 0x0004002B, 0x0004002C, 0x0004002D, 0x0004002E,
+ 0x0004002F, 0x00040030, 0x00040031, 0x00040032,
+ 0x00040033, 0x00040034, 0x00040035, 0x00040036,
+ 0x00040037, 0x00040038, 0x00040039, 0x0004003A
+ };
+
+ _field1414 = 0x4005B;
+ _field1418 = 0x4005C;
+
+ for (uint i = 0; i < 32; ++i)
+ _objectIds[i] = kObjectIds3[i];
+
+ for (uint i = 0; i < 32; ++i) {
+ _items[i]._objectId = kObjectIds2[i];
+ _items[i]._enabled = 0;
+ _items[i]._position.x = 0;
+ _items[i]._position.y = 0;
+ _items[i]._sequenceId = 0;
+ }
+
+ _currItem0 = 0;
+ _prevItem0 = 0;
+ _someItem0 = 0;
+ _pt1.x = 0;
+ _pt1.y = 0;
+ _pt2.x = 0;
+ _pt2.y = 0;
+
+}
+
+void BbdouBubble::addItem0(uint32 sequenceId1, uint32 sequenceId2, uint32 progResKeywordId,
+ uint32 namedPointId, int16 count, uint32 *namedPointIds) {
+ Item0 item0;
+ item0._sequenceId1 = sequenceId1;
+ item0._sequenceId2 = sequenceId2;
+ item0._progResKeywordId = progResKeywordId;
+ item0._baseNamedPointId = namedPointId;
+ item0._count = count;
+ for (int16 i = 0; i < count; ++i)
+ item0._namedPointIds[i] = FROM_LE_32(namedPointIds[i]);
+ item0._objectId = 0;
+ item0._pt.x = 0;
+ item0._pt.y = 0;
+ _item0s.push_back(item0);
+}
+
+void BbdouBubble::show() {
+
+ if (_prevItem0) {
+ hide();
+ }
+
+ _prevItem0 = _currItem0;
+ _currItem0 = 0;
+
+ // TODO calcBubbles(_pt1, _pt2);
+
+ Control *control = _vm->_dict->getObjectControl(_prevItem0->_objectId);
+ control->setActorPosition(_pt2);
+ control->startSequenceActor(0x60057, 2, 0);
+ control->startSequenceActor(_prevItem0->_sequenceId1, 2, 0);
+ control->appearActor();
+ control->deactivateObject();
+
+ for (uint i = 0; i < 32; ++i) {
+ if (_items[i]._enabled == 1) {
+ Control *subControl = _vm->_dict->getObjectControl(_items[i]._objectId);
+ subControl->setActorPosition(_items[i]._position);
+ subControl->startSequenceActor(_items[i]._sequenceId, 2, 0);
+ }
+ }
+
+}
+
+void BbdouBubble::hide() {
+ _someItem0 = _prevItem0;
+ _prevItem0 = 0;
+ if (_someItem0) {
+ Control *control = _vm->_dict->getObjectControl(_someItem0->_objectId);
+ control->startSequenceActor(_someItem0->_sequenceId2, 2, 0);
+ for (uint i = 0; i < 32; ++i) {
+ Control *subControl = _vm->_dict->getObjectControl(_objectIds[i]);
+ subControl->stopActor();
+ subControl->disappearActor();
+ }
+ for (uint i = 0; i < 32; ++i) {
+ Control *subControl = _vm->_dict->getObjectControl(_items[i]._objectId);
+ subControl->stopActor();
+ subControl->disappearActor();
+ }
+ }
+}
+
+} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_bubble.h b/engines/illusions/bbdou/bbdou_bubble.h
new file mode 100644
index 0000000000..9064acd08c
--- /dev/null
+++ b/engines/illusions/bbdou/bbdou_bubble.h
@@ -0,0 +1,81 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ILLUSIONS_BBDOU_BBDOU_BUBBLE_H
+#define ILLUSIONS_BBDOU_BBDOU_BUBBLE_H
+
+#include "illusions/specialcode.h"
+#include "common/rect.h"
+
+namespace Illusions {
+
+class IllusionsEngine;
+class BbdouSpecialCode;
+class Control;
+
+struct Item0 {
+ uint32 _sequenceId1;
+ uint32 _sequenceId2;
+ int16 _count;
+ uint32 _progResKeywordId;
+ uint32 _baseNamedPointId;
+ uint32 _namedPointIds[32];
+ uint32 _objectId;
+ Common::Point _pt;
+ Item0() : _count(0) {}
+};
+
+struct Item141C {
+ uint32 _objectId;
+ int16 _enabled;
+ Common::Point _position;
+ int16 _fieldA;
+ uint32 _sequenceId;
+};
+
+class BbdouBubble {
+public:
+ BbdouBubble(IllusionsEngine *vm, BbdouSpecialCode *bbdou);
+ ~BbdouBubble();
+ void init();
+ void addItem0(uint32 sequenceId1, uint32 sequenceId2, uint32 progResKeywordId,
+ uint32 namedPointId, int16 count, uint32 *namedPointIds);
+ void show();
+ void hide();
+protected:
+ IllusionsEngine *_vm;
+ BbdouSpecialCode *_bbdou;
+ Common::Array<Item0> _item0s;
+ Item0 *_currItem0;
+ Item0 *_prevItem0;
+ Item0 *_someItem0;
+ uint32 _objectIds[32];
+ Common::Point _pt1;
+ Common::Point _pt2;
+ int _field1414;
+ int _field1418;
+ Item141C _items[32];
+};
+
+} // End of namespace Illusions
+
+#endif // ILLUSIONS_BBDOU_BBDOU_BUBBLE_H
diff --git a/engines/illusions/bbdou/bbdou_cursor.cpp b/engines/illusions/bbdou/bbdou_cursor.cpp
index 9c0bcc8170..16cd82ade6 100644
--- a/engines/illusions/bbdou/bbdou_cursor.cpp
+++ b/engines/illusions/bbdou/bbdou_cursor.cpp
@@ -23,17 +23,178 @@
#include "illusions/illusions.h"
#include "illusions/bbdou/bbdou_cursor.h"
#include "illusions/actor.h"
+#include "illusions/camera.h"
+#include "illusions/dictionary.h"
+#include "illusions/input.h"
namespace Illusions {
-BbdouCursor::BbdouCursor(IllusionsEngine *vm)
- : _vm(vm) {
+// NOTE It's assumed there's only one game cursor object
+// The original stores the _data inside the actor, here it's inside the Cursor class.
+
+BbdouCursor::BbdouCursor(IllusionsEngine *vm, BbdouSpecialCode *bbdou)
+ : _vm(vm), _bbdou(bbdou) {
}
BbdouCursor::~BbdouCursor() {
}
-void BbdouCursor::init() {
+void BbdouCursor::init(uint32 objectId, uint32 progResKeywordId) {
+
+ Common::Point pos = _vm->_camera->getCurrentPan();
+ _vm->_controls->placeActor(0x50001, pos, 0x6000C, objectId, 0);
+
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ //control->_actor->setControlRoutine(new Common::Functor2Mem<Control*, uint32, void, BbdouCursor>(this, &BbdouCursor::actorControlRoutine1));
+ control->_flags |= 8;
+
+ _data._mode = 1;
+ _data._mode2 = 0;
+ _data._verbId1 = 0x1B0000;
+ _data._progResKeywordId = progResKeywordId;
+ _data._currOverlappedObjectId = 0;
+ _data._overlappedObjectId = 0;
+ _data._sequenceId = 0x6000F;
+ _data._holdingObjectId = 0;
+ _data._holdingObjectId2 = 0;
+ _data._visibleCtr = 0;
+ _data._causeThreadId1 = 0;
+ _data._causeThreadId2 = 0;
+ _data._field90 = 0;
+ _data._flags = 0;
+ _data._item10._field58 = 1;
+ _data._sequenceId98 = 0;
+ _data._idleCtr = 0;
+ _data._item10._verbId = 0x1B0000;
+ _data._item10._field0 = 1;
+ _data._item10._playSound48 = 0;
+ _data._item10._objectIds[0] = 0;
+ _data._item10._objectIds[1] = 0;
+ _data._item10._index = 0;
+ _data._item10._flag56 = 0;
+
+ clearCursorDataField14();
+
+ control->setActorIndexTo1();
+
+}
+
+void BbdouCursor::enable(uint32 objectId) {
+ ++_data._visibleCtr;
+ if (_data._visibleCtr == 1) {
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ show(control);
+ _vm->_camera->pushCameraMode();
+ _vm->_camera->panEdgeFollow(objectId, 360);
+ _data._idleCtr = 0;
+ }
+ _vm->_input->discardButtons(0xFFFF);
+}
+
+void BbdouCursor::disable(uint32 objectId) {
+ hide(objectId);
+}
+
+void BbdouCursor::addCursorSequence(uint32 objectId, uint32 sequenceId) {
+ for (uint i = 0; i < kMaxCursorSequences; ++i)
+ if (_cursorSequences[i]._objectId == 0) {
+ _cursorSequences[i]._objectId = objectId;
+ _cursorSequences[i]._sequenceId = sequenceId;
+ break;
+ }
+}
+
+uint32 BbdouCursor::findCursorSequenceId(uint32 objectId) {
+ for (uint i = 0; i < kMaxCursorSequences; ++i)
+ if (_cursorSequences[i]._objectId == objectId)
+ return _cursorSequences[i]._sequenceId;
+ return 0;
+}
+
+int BbdouCursor::findStruct8bsValue(uint32 objectId) {
+ for (uint i = 0; i < kMaxCursorSequences; ++i)
+ if (_cursorStruct8bs[i]._objectId == objectId)
+ return _cursorStruct8bs[i]._value;
+ return 11;
+}
+
+void BbdouCursor::saveInfo() {
+ _data._mode2 = _data._mode;
+ _data._sequenceId2 = _data._sequenceId;
+ _data._holdingObjectId2 = _data._holdingObjectId;
+}
+
+void BbdouCursor::restoreInfo() {
+ _data._mode = _data._mode2;
+ _data._holdingObjectId = _data._holdingObjectId2;
+ _data._sequenceId = _data._sequenceId2;
+ _data._mode2 = 0;
+ _data._holdingObjectId2 = 0;
+ _data._sequenceId2 = 0;
+}
+
+void BbdouCursor::restoreAfterTrackingCursor() {
+ _data._holdingObjectId = _data._holdingObjectId2;
+ if (_data._holdingObjectId2) {
+ _data._mode = 2;
+ _data._sequenceId = findCursorSequenceId(_data._holdingObjectId2);
+ } else {
+ _data._mode = 1;
+ _data._sequenceId = 0x6000F;
+ }
+ _data._mode2 = 0;
+ _data._sequenceId2 = 0;
+ _data._holdingObjectId2 = 0;
+ _data._sequenceId98 = 0;
+}
+
+uint32 BbdouCursor::getSequenceId1(int sequenceIndex) {
+ switch (sequenceIndex) {
+ case 2:
+ return 0x60010;
+ case 3:
+ return 0x60011;
+ case 4:
+ return 0x60012;
+ case 5:
+ return 0x60013;
+ case 6:
+ return 0x60015;
+ case 7:
+ return 0x60014;
+ default:
+ return 0;
+ }
+}
+
+void BbdouCursor::clearCursorDataField14() {
+ for (uint i = 0; i < 32; ++i)
+ _data._item10._verbActive[i] = 0;
+ if (_data._item10._field0 == 1) {
+ _data._item10._verbActive[1] = 1;
+ _data._item10._verbActive[2] = 1;
+ _data._item10._verbActive[3] = 1;
+ _data._item10._verbActive[5] = 1;
+ } else if (_data._item10._field0 == 3) {
+ _data._item10._verbActive[1] = 1;
+ _data._item10._verbActive[2] = 1;
+ }
+}
+
+void BbdouCursor::show(Control *control) {
+ control->startSequenceActor(_data._sequenceId, 2, 0);
+ control->appearActor();
+}
+
+void BbdouCursor::hide(uint32 objectId) {
+ --_data._visibleCtr;
+ if (_data._visibleCtr == 0) {
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ control->startSequenceActor(0x60029, 2, 0);
+ // TODO item10_sub_10005040(objectId, &cursorData->item10);
+ _vm->_camera->popCameraMode();
+ }
+ _vm->_input->discardButtons(0xFFFF);
}
} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_cursor.h b/engines/illusions/bbdou/bbdou_cursor.h
index df3ed82f1a..8f02632857 100644
--- a/engines/illusions/bbdou/bbdou_cursor.h
+++ b/engines/illusions/bbdou/bbdou_cursor.h
@@ -28,14 +28,85 @@
namespace Illusions {
class IllusionsEngine;
+class BbdouSpecialCode;
+class Control;
+struct Item10;
+
+struct Item10 {
+ int _field0;
+ int16 _verbActive[32];
+ uint32 _verbId;
+ int16 _playSound48;
+ //field_4A dw
+ uint32 _objectIds[2];
+ int16 _index;
+ int16 _flag56;
+ int _field58;
+};
+
+struct CursorData {
+ int _mode;
+ int _mode2;
+ uint32 _verbId1;
+ uint32 _progResKeywordId;
+ Item10 _item10;
+ uint32 _currOverlappedObjectId;
+ uint32 _overlappedObjectId;
+ uint32 _sequenceId;
+ uint32 _sequenceId2;
+ uint32 _holdingObjectId;
+ uint32 _holdingObjectId2;
+ int _visibleCtr;
+ //field_86 dw
+ uint32 _causeThreadId1;
+ uint32 _causeThreadId2;
+ int16 _field90;
+ //field_92 dw
+ uint _flags;
+ uint32 _sequenceId98;
+ int16 _idleCtr;
+ //field_9E db
+ //field_9F db
+};
+
+struct CursorSequence {
+ uint32 _objectId;
+ uint32 _sequenceId;
+ CursorSequence() : _objectId(0), _sequenceId(0) {}
+};
+
+struct Struct8b {
+ uint32 _objectId;
+ int _value;
+ Struct8b() : _objectId(0), _value(0) {}
+};
+
+const uint kMaxCursorSequences = 100;
class BbdouCursor {
public:
- BbdouCursor(IllusionsEngine *vm);
+ BbdouCursor(IllusionsEngine *vm, BbdouSpecialCode *bbdou);
~BbdouCursor();
- void init();
-protected:
+ void init(uint32 objectId, uint32 progResKeywordId);
+ void enable(uint32 objectId);
+ void disable(uint32 objectId);
+ void addCursorSequence(uint32 objectId, uint32 sequenceId);
+ uint32 findCursorSequenceId(uint32 objectId);
+ int findStruct8bsValue(uint32 objectId);
+ void saveInfo();
+ void restoreInfo();
+ void restoreAfterTrackingCursor();
+ uint32 getSequenceId1(int sequenceIndex);
+public:
IllusionsEngine *_vm;
+ BbdouSpecialCode *_bbdou;
+ Control *_control;
+ CursorData _data;
+ CursorSequence _cursorSequences[kMaxCursorSequences];
+ Struct8b _cursorStruct8bs[512];
+ void clearCursorDataField14();
+ void show(Control *control);
+ void hide(uint32 objectId);
};
} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_specialcode.cpp b/engines/illusions/bbdou/bbdou_specialcode.cpp
index 028fdb54a8..e0d29e7265 100644
--- a/engines/illusions/bbdou/bbdou_specialcode.cpp
+++ b/engines/illusions/bbdou/bbdou_specialcode.cpp
@@ -22,7 +22,13 @@
#include "illusions/illusions.h"
#include "illusions/bbdou/bbdou_specialcode.h"
+#include "illusions/bbdou/bbdou_bubble.h"
#include "illusions/bbdou/bbdou_cursor.h"
+#include "illusions/actor.h"
+#include "illusions/camera.h"
+#include "illusions/dictionary.h"
+#include "illusions/input.h"
+#include "illusions/scriptman.h"
#include "illusions/scriptopcodes.h"
namespace Illusions {
@@ -31,15 +37,313 @@ namespace Illusions {
BbdouSpecialCode::BbdouSpecialCode(IllusionsEngine *vm)
: SpecialCode(vm) {
+ _bubble = new BbdouBubble(_vm, this);
+ _cursor = new BbdouCursor(_vm, this);
}
BbdouSpecialCode::~BbdouSpecialCode() {
+ delete _cursor;
+ delete _bubble;
}
+typedef Common::Functor1Mem<OpCall&, void, BbdouSpecialCode> SpecialCodeFunctionI;
+#define SPECIAL(id, func) _map[id] = new SpecialCodeFunctionI(this, &BbdouSpecialCode::func);
+
void BbdouSpecialCode::init() {
+ // TODO
+ SPECIAL(0x00160006, spcInitCursor);
+ SPECIAL(0x00160008, spcEnableCursor);
+ SPECIAL(0x00160009, spcDisableCursor);
+ SPECIAL(0x0016000A, spcAddCursorSequence);
+ SPECIAL(0x00160013, spcInitBubble);
+ SPECIAL(0x00160014, spcSetupBubble);
+ SPECIAL(0x00160015, spcSetObjectInteractMode);
}
void BbdouSpecialCode::run(uint32 specialCodeId, OpCall &opCall) {
+ MapIterator it = _map.find(specialCodeId);
+ if (it != _map.end()) {
+ (*(*it)._value)(opCall);
+ } else {
+ debug("BbdouSpecialCode::run() Unimplemented special code %08X", specialCodeId);
+ _vm->notifyThreadId(opCall._callerThreadId);
+ }
+}
+
+// Special codes
+
+// Convenience macros
+#define ARG_SKIP(x) opCall.skip(x);
+#define ARG_INT16(name) int16 name = opCall.readSint16(); debug("ARG_INT16(" #name " = %d)", name);
+#define ARG_UINT32(name) uint32 name = opCall.readUint32(); debug("ARG_UINT32(" #name " = %08X)", name);
+
+void BbdouSpecialCode::spcInitCursor(OpCall &opCall) {
+ ARG_UINT32(objectId);
+ ARG_UINT32(progResKeywordId);
+ _cursor->init(objectId, progResKeywordId);
+ setCursorControlRoutine(objectId, 0);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcEnableCursor(OpCall &opCall) {
+ ARG_UINT32(objectId);
+ _cursor->enable(objectId);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcDisableCursor(OpCall &opCall) {
+ ARG_UINT32(objectId);
+ _cursor->disable(objectId);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcAddCursorSequence(OpCall &opCall) {
+ ARG_SKIP(4);
+ ARG_UINT32(objectId);
+ ARG_UINT32(sequenceId);
+ _cursor->addCursorSequence(objectId, sequenceId);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcInitBubble(OpCall &opCall) {
+ _bubble->init();
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcSetupBubble(OpCall &opCall) {
+ ARG_UINT32(sequenceId1);
+ ARG_UINT32(sequenceId2);
+ ARG_UINT32(progResKeywordId);
+ ARG_UINT32(namedPointId);
+ ARG_INT16(count);
+ _bubble->addItem0(sequenceId1, sequenceId2, progResKeywordId, namedPointId,
+ count, (uint32*)opCall._code);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcSetObjectInteractMode(OpCall &opCall) {
+ ARG_SKIP(4);
+ ARG_UINT32(objectId);
+ ARG_INT16(value);
+ // TODO Cursor_updateStruct8bs(objectId, v3);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::playSoundEffect(int soundIndex) {
+ static const uint32 kSoundEffectIds[] = {
+ 0, 1,
+ 0x900C1, 2,
+ 0, 3,
+ 0x900C0, 4,
+ 0x900C2, 5,
+ 0, 6
+ };
+ uint32 soundEffectId = kSoundEffectIds[2 * soundIndex];
+ if (soundEffectId) {
+ // TODO _vm->startSound(soundEffectId, 255, 0);
+ }
+}
+
+void BbdouSpecialCode::resetItem10(uint32 objectId, Item10 *item10) {
+ if (item10->_playSound48 == 1) {
+ _bubble->hide();
+ item10->_verbId = 0x1B0000;
+ item10->_playSound48 = 0;
+ item10->_objectIds[0] = 0;
+ item10->_objectIds[1] = 0;
+ }
+ _vm->_input->discardButtons(0xFFFF);
+}
+
+bool BbdouSpecialCode::testValueRange(int value) {
+ return value >= 2 && value <= 7;
+}
+
+void BbdouSpecialCode::setCursorControlRoutine(uint32 objectId, int num) {
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ if (num == 0)
+ control->_actor->setControlRoutine(
+ new Common::Functor2Mem<Control*, uint32, void, BbdouSpecialCode>(this, &BbdouSpecialCode::cursorInteractControlRoutine));
+ else
+ control->_actor->setControlRoutine(
+ new Common::Functor2Mem<Control*, uint32, void, BbdouSpecialCode>(this, &BbdouSpecialCode::cursorControlRoutine2));
+}
+
+Common::Point BbdouSpecialCode::getBackgroundCursorPos(Common::Point cursorPos) {
+ Common::Point pt = _vm->_camera->getScreenOffset();
+ pt.x += cursorPos.x;
+ pt.y += cursorPos.y;
+ return pt;
+}
+
+bool BbdouSpecialCode::runCause(Control *control, CursorData &cursorData,
+ uint32 verbId, uint32 objectId1, uint32 objectId2, int soundIndex) {
+ // TODO
+ return false;
+}
+
+void BbdouSpecialCode::showBubble(uint32 objectId, uint32 overlappedObjectId, uint32 holdingObjectId,
+ Item10 *item10, uint32 progResKeywordId) {
+ // TODO
+}
+
+bool BbdouSpecialCode::findVerbId(Item10 *item10, uint32 currOverlappedObjectId, int always0, uint32 &outVerbId) {
+ // TODO
+ return false;
+}
+
+void BbdouSpecialCode::cursorInteractControlRoutine(Control *cursorControl, uint32 deltaTime) {
+ Actor *actor = cursorControl->_actor;
+ CursorData &cursorData = _cursor->_data;
+
+ if (cursorData._visibleCtr > 0) {
+
+ Common::Point cursorPos = _vm->_input->getCursorPosition();
+
+ if (cursorPos == actor->_position) {
+ cursorData._idleCtr += deltaTime;
+ if (cursorData._idleCtr > 3600)
+ cursorData._idleCtr = 0;
+ } else {
+ actor->_position.x = cursorPos.x;
+ actor->_position.y = cursorPos.y;
+ cursorData._idleCtr = 0;
+ }
+
+ if (updateTrackingCursor(cursorControl))
+ cursorData._flags |= 1;
+ else
+ cursorData._flags &= ~1;
+
+ cursorPos = getBackgroundCursorPos(cursorPos);
+ bool foundOverlapped = false;
+ Control *overlappedControl = 0;
+
+ if (cursorData._flags & 1) {
+ foundOverlapped = 0;
+ } else if (_vm->_scriptMan->_activeScenes.getCurrentScene() == 0x1000D) {
+ /* TODO foundOverlapped = artcntrlGetOverlappedObjectAccurate(cursorControl, cursorPos,
+ &overlappedControl, cursorData._item10._field58);*/
+ } else {
+ foundOverlapped = _vm->_controls->getOverlappedObject(cursorControl, cursorPos,
+ &overlappedControl, cursorData._item10._field58);
+ debug("overlappedControl: %p", (void*)overlappedControl);
+ }
+
+ if (foundOverlapped) {
+ if (overlappedControl->_objectId != cursorData._currOverlappedObjectId) {
+ if (cursorData._item10._playSound48)
+ playSoundEffect(4);
+ resetItem10(cursorControl->_objectId, &cursorData._item10);
+ int value = _cursor->findStruct8bsValue(overlappedControl->_objectId);
+ if (!testValueRange(value)) {
+ if (cursorData._mode == 3)
+ _cursor->restoreInfo();
+ _cursor->show(cursorControl);
+ cursorControl->setActorIndexTo2();
+ if (cursorData._overlappedObjectId != overlappedControl->_objectId) {
+ cursorData._overlappedObjectId = overlappedControl->_objectId;
+ runCause(cursorControl, cursorData, 0x1B0009, 0, overlappedControl->_objectId, 0);
+ }
+ if (value == 10) {
+ if (cursorData._holdingObjectId) {
+ cursorData._item10._verbId = 0x1B0003;
+ cursorData._currOverlappedObjectId = overlappedControl->_objectId;
+ }
+ else {
+ cursorData._item10._verbId = 0x1B0002;
+ cursorData._currOverlappedObjectId = overlappedControl->_objectId;
+ }
+ } else {
+ playSoundEffect(3);
+ showBubble(cursorControl->_objectId, overlappedControl->_objectId,
+ cursorData._holdingObjectId, &cursorData._item10,
+ cursorData._progResKeywordId);
+ cursorData._currOverlappedObjectId = overlappedControl->_objectId;
+ }
+ } else {
+ if (cursorData._mode != 3) {
+ _cursor->saveInfo();
+ cursorData._mode = 3;
+ cursorData._item10._verbId = 0x1B0006;
+ cursorData._holdingObjectId = 0;
+ }
+ cursorData._sequenceId = _cursor->getSequenceId1(value);
+ _cursor->show(cursorControl);
+ cursorData._currOverlappedObjectId = overlappedControl->_objectId;
+ }
+ }
+ } else {
+ if (cursorData._overlappedObjectId) {
+ runCause(cursorControl, cursorData, 0x1B0009, 0, 0x40003, 0);
+ cursorData._overlappedObjectId = 0;
+ }
+ if (cursorData._currOverlappedObjectId || cursorData._mode == 3) {
+ if (cursorData._mode == 3)
+ _cursor->restoreInfo();
+ _cursor->show(cursorControl);
+ cursorControl->setActorIndexTo1();
+ if (cursorData._item10._playSound48)
+ playSoundEffect(4);
+ resetItem10(cursorControl->_objectId, &cursorData._item10);
+ }
+ cursorData._currOverlappedObjectId = 0;
+ }
+ }
+
+ actor->_seqCodeValue1 = 100 * deltaTime;
+
+ if (cursorData._visibleCtr <= 0) {
+ if (cursorData._currOverlappedObjectId || cursorData._mode == 3 || cursorData._mode == 4) {
+ if (cursorData._mode == 3) {
+ _cursor->restoreInfo();
+ } else if (cursorData._mode == 4) {
+ _cursor->restoreAfterTrackingCursor();
+ }
+ cursorControl->setActorIndexTo1();
+ }
+ cursorData._currOverlappedObjectId = 0;
+ } else if (cursorData._currOverlappedObjectId) {
+ if (_vm->_input->pollButton(1)) {
+ cursorData._idleCtr = 0;
+ if (runCause(cursorControl, cursorData, cursorData._item10._verbId, cursorData._holdingObjectId, cursorData._currOverlappedObjectId, 1)) {
+ resetItem10(cursorControl->_objectId, &cursorData._item10);
+ cursorData._currOverlappedObjectId = 0;
+ cursorControl->setActorIndexTo1();
+ }
+ } else if (_vm->_input->pollButton(2)) {
+ uint32 verbId;
+ cursorData._idleCtr = 0;
+ if (cursorData._holdingObjectId) {
+ runCause(cursorControl, cursorData, 0x1B000B, 0, 0x40003, 0);
+ cursorData._currOverlappedObjectId = 0;
+ } else if (findVerbId(&cursorData._item10, cursorData._currOverlappedObjectId, 0, verbId) &&
+ runCause(cursorControl, cursorData, verbId, cursorData._holdingObjectId, cursorData._currOverlappedObjectId, 1)) {
+ resetItem10(cursorControl->_objectId, &cursorData._item10);
+ cursorData._currOverlappedObjectId = 0;
+ cursorControl->setActorIndexTo1();
+ }
+ }
+ } else {
+ if (_vm->_input->pollButton(1)) {
+ cursorData._idleCtr = 0;
+ runCause(cursorControl, cursorData, 0x1B0002, 0, 0x40003, 0);
+ } else if (_vm->_input->pollButton(4)) {
+ cursorData._idleCtr = 0;
+ if (cursorData._item10._field58 <= 1)
+ runCause(cursorControl, cursorData, cursorData._holdingObjectId != 0 ? 0x1B000B : 0x1B0004, 0, 0x40003, 0);
+ }
+ }
+
+}
+
+void BbdouSpecialCode::cursorControlRoutine2(Control *cursorControl, uint32 deltaTime) {
+ // TODO
+}
+
+bool BbdouSpecialCode::updateTrackingCursor(Control *cursorControl) {
+ // TODO
+ return false;
}
} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_specialcode.h b/engines/illusions/bbdou/bbdou_specialcode.h
index 98aef581be..1dda19fa78 100644
--- a/engines/illusions/bbdou/bbdou_specialcode.h
+++ b/engines/illusions/bbdou/bbdou_specialcode.h
@@ -24,11 +24,17 @@
#define ILLUSIONS_BBDOU_BBDOU_SPECIALCODE_H
#include "illusions/specialcode.h"
+#include "common/hashmap.h"
namespace Illusions {
class IllusionsEngine;
+class BbdouBubble;
class BbdouCursor;
+struct CursorData;
+struct Item10;
+
+typedef Common::Functor1<OpCall&, void> SpecialCodeFunction;
class BbdouSpecialCode : public SpecialCode {
public:
@@ -37,7 +43,34 @@ public:
virtual void init();
virtual void run(uint32 specialCodeId, OpCall &opCall);
public:
+ typedef Common::HashMap<uint32, SpecialCodeFunction*> Map;
+ typedef Map::iterator MapIterator;
+ Map _map;
BbdouCursor *_cursor;
+ BbdouBubble *_bubble;
+ // Special code interface functions
+ void spcInitCursor(OpCall &opCall);
+ void spcEnableCursor(OpCall &opCall);
+ void spcDisableCursor(OpCall &opCall);
+ void spcAddCursorSequence(OpCall &opCall);
+ void spcInitBubble(OpCall &opCall);
+ void spcSetupBubble(OpCall &opCall);
+ void spcSetObjectInteractMode(OpCall &opCall);
+protected:
+ // Internal functions
+ void playSoundEffect(int soundIndex);
+ void resetItem10(uint32 objectId, Item10 *item10);
+ bool testValueRange(int value);
+ void setCursorControlRoutine(uint32 objectId, int num);
+ Common::Point getBackgroundCursorPos(Common::Point cursorPos);
+ bool runCause(Control *control, CursorData &cursorData,
+ uint32 verbId, uint32 objectId1, uint32 objectId2, int soundIndex);
+ void showBubble(uint32 objectId, uint32 overlappedObjectId, uint32 holdingObjectId,
+ Item10 *item10, uint32 progResKeywordId);
+ 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);
};
} // End of namespace Illusions