aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/script/script_eob.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/kyra/script/script_eob.cpp')
-rw-r--r--engines/kyra/script/script_eob.cpp1622
1 files changed, 1622 insertions, 0 deletions
diff --git a/engines/kyra/script/script_eob.cpp b/engines/kyra/script/script_eob.cpp
new file mode 100644
index 0000000000..709921deb9
--- /dev/null
+++ b/engines/kyra/script/script_eob.cpp
@@ -0,0 +1,1622 @@
+/* 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.
+ *
+ */
+
+#ifdef ENABLE_EOB
+
+#include "kyra/engine/eobcommon.h"
+#include "kyra/graphics/screen_eob.h"
+#include "kyra/script/script_eob.h"
+#include "kyra/resource/resource.h"
+#include "kyra/sound/sound.h"
+
+#include "common/system.h"
+
+namespace Kyra {
+
+void EoBCoreEngine::runLevelScript(int block, int flags) {
+ _inf->run(block, flags);
+}
+
+void EoBCoreEngine::setScriptFlags(uint32 flags) {
+ _inf->setFlags(flags);
+}
+
+void EoBCoreEngine::clearScriptFlags(uint32 flags) {
+ _inf->clearFlags(flags);
+}
+
+bool EoBCoreEngine::checkScriptFlags(uint32 flags) {
+ return _inf->checkFlags(flags);
+}
+
+const uint8 *EoBCoreEngine::initScriptTimers(const uint8 *pos) {
+ _scriptTimersCount = 0;
+
+ while (((int16)READ_LE_UINT16(pos)) != -1) {
+ _scriptTimers[_scriptTimersCount].func = READ_LE_UINT16(pos);
+ pos += 2;
+ uint16 ticks = READ_LE_UINT16(pos) * 18;
+ _scriptTimers[_scriptTimersCount].ticks = ticks;
+ pos += 2;
+ _scriptTimers[_scriptTimersCount++].next = _system->getMillis() + ticks * _tickLength;
+ }
+
+ return pos;
+}
+
+void EoBCoreEngine::updateScriptTimers() {
+ bool timerUpdate = false;
+ if ((_scriptTimersMode & 2) && _stepsUntilScriptCall && _stepCounter > _stepsUntilScriptCall) {
+ _inf->run(0, 0x20);
+ _stepCounter = 0;
+ timerUpdate = true;
+ }
+
+ if (_scriptTimersMode & 1) {
+ for (int i = 0; i < _scriptTimersCount; i++) {
+ if (_scriptTimers[i].next < _system->getMillis()) {
+ _inf->run(_scriptTimers[i].func, _flags.gameID == GI_EOB1 ? 0x20 : 0x80);
+ _scriptTimers[i].next = _system->getMillis() + _scriptTimers[i].ticks * _tickLength;
+ _sceneUpdateRequired = true;
+ timerUpdate = true;
+ }
+ }
+ }
+
+ if (timerUpdate)
+ updateScriptTimersExtra();
+}
+
+EoBInfProcessor::EoBInfProcessor(EoBCoreEngine *engine, Screen_EoB *screen) : _vm(engine), _screen(screen),
+ _commandMin(engine->game() == GI_EOB1 ? -27 : -31) {
+
+#define Opcode(x) _opcodes.push_back(new InfOpcode(new InfProc(this, &EoBInfProcessor::x), #x))
+#define OpcodeAlt(x) if (_vm->game() == GI_EOB1) { Opcode(x##_v1); } else { Opcode(x##_v2); }
+ Opcode(oeob_setWallType);
+ Opcode(oeob_toggleWallState);
+ Opcode(oeob_openDoor);
+ Opcode(oeob_closeDoor);
+ Opcode(oeob_replaceMonster);
+ Opcode(oeob_movePartyOrObject);
+ Opcode(oeob_moveInventoryItemToBlock);
+ OpcodeAlt(oeob_printMessage);
+ Opcode(oeob_setFlags);
+ Opcode(oeob_playSoundEffect);
+ Opcode(oeob_removeFlags);
+ Opcode(oeob_modifyCharacterHitPoints);
+ Opcode(oeob_calcAndInflictCharacterDamage);
+ Opcode(oeob_jump);
+ Opcode(oeob_end);
+ Opcode(oeob_returnFromSubroutine);
+ Opcode(oeob_callSubroutine);
+ OpcodeAlt(oeob_eval);
+ Opcode(oeob_deleteItem);
+ Opcode(oeob_loadNewLevelOrMonsters);
+ Opcode(oeob_increasePartyExperience);
+ OpcodeAlt(oeob_createItem);
+ Opcode(oeob_launchObject);
+ Opcode(oeob_changeDirection);
+ Opcode(oeob_identifyItems);
+ Opcode(oeob_sequence);
+ Opcode(oeob_delay);
+ Opcode(oeob_drawScene);
+ Opcode(oeob_dialogue);
+ Opcode(oeob_specialEvent);
+#undef Opcode
+#undef OpcodeAlt
+
+ _scriptData = 0;
+ _scriptSize = 0;
+
+ _abortScript = 0;
+ _abortAfterSubroutine = 0;
+ _dlgResult = 0;
+ _preventRest = 0;
+
+ _lastScriptFunc = 0;
+ _lastScriptFlags = 0;
+
+ _subroutineStack = new int8*[10];
+ memset(_subroutineStack, 0, 10 * sizeof(int8 *));
+ _subroutineStackPos = 0;
+
+ _flagTable = new uint32[18];
+ memset(_flagTable, 0, 18 * sizeof(uint32));
+
+ _stack = new int16[30];
+ memset(_stack, 0, 30 * sizeof(int16));
+ _stackIndex = 0;
+
+ _activeCharacter = -1;
+}
+
+EoBInfProcessor::~EoBInfProcessor() {
+ delete[] _subroutineStack;
+ delete[] _flagTable;
+ delete[] _stack;
+ delete[] _scriptData;
+
+ for (Common::Array<const InfOpcode *>::const_iterator a = _opcodes.begin(); a != _opcodes.end(); ++a)
+ delete *a;
+
+ _opcodes.clear();
+}
+
+void EoBInfProcessor::loadData(const uint8 *data, uint32 dataSize) {
+ delete[] _scriptData;
+ _scriptSize = dataSize;
+ _scriptData = new int8[_scriptSize];
+ memcpy(_scriptData, data, _scriptSize);
+}
+
+void EoBInfProcessor::run(int func, int flags) {
+ int o = _vm->_levelBlockProperties[func].assignedObjects;
+ if (!o)
+ return;
+
+ uint16 f = _vm->_levelBlockProperties[func].flags;
+
+ uint16 subFlags = ((f & 0xFFF8) >> 3) | 0xE0;
+ if (!(flags & subFlags))
+ return;
+
+ _abortScript = 0;
+ _abortAfterSubroutine = 0;
+ _dlgResult = 0;
+ _activeCharacter = -1;
+
+ _lastScriptFunc = func;
+ _lastScriptFlags = flags;
+
+ int8 *pos = (int8 *)(_scriptData + o);
+
+ do {
+ int8 cmd = *pos++;
+ if (cmd <= _commandMin || cmd >= 0)
+ continue;
+ debugC(3, kDebugLevelScript, "[0x%.04X] EoBInfProcessor::%s()", (uint32)(pos - _scriptData), _opcodes[-(cmd + 1)]->desc.c_str());
+ pos += (*_opcodes[-(cmd + 1)]->proc)(pos);
+ } while (!_abortScript && !_abortAfterSubroutine);
+}
+
+void EoBInfProcessor::setFlags(uint32 flags) {
+ _flagTable[17] |= flags;
+}
+
+void EoBInfProcessor::clearFlags(uint32 flags) {
+ _flagTable[17] &= ~flags;
+}
+
+bool EoBInfProcessor::checkFlags(uint32 flags) const {
+ return ((_flagTable[17] & flags) == flags) ? true : false;
+}
+
+bool EoBInfProcessor::preventRest() const {
+ return _preventRest ? true : false;
+}
+
+void EoBInfProcessor::loadState(Common::SeekableSubReadStreamEndian &in, bool origFile) {
+ _preventRest = (_vm->game() == GI_EOB1 && origFile) ? 0 : in.readByte();
+ int numFlags = (_vm->game() == GI_EOB1 && origFile) ? 12 : 18;
+ for (int i = 0; i < numFlags; i++)
+ _flagTable[i] = in.readUint32();
+ if (_vm->game() == GI_EOB1 && origFile)
+ setFlags(in.readUint32());
+}
+
+void EoBInfProcessor::saveState(Common::OutSaveFile *out, bool origFile) {
+ if (_vm->game() == GI_EOB2 || !origFile)
+ out->writeByte(_preventRest);
+ int numFlags = (_vm->game() == GI_EOB1 && origFile) ? 12 : 18;
+ for (int i = 0; i < numFlags; i++) {
+ if (origFile)
+ out->writeUint32LE(_flagTable[i]);
+ else
+ out->writeUint32BE(_flagTable[i]);
+ }
+ if (_vm->game() == GI_EOB1 && origFile)
+ out->writeUint32LE(_flagTable[17]);
+}
+
+void EoBInfProcessor::reset() {
+ _preventRest = 0;
+ memset(_flagTable, 0, 18 * sizeof(uint32));
+}
+
+const char *EoBInfProcessor::getString(uint16 index) {
+ if (index == 0xFFFF)
+ return 0;
+
+ int8 *res = _scriptData + READ_LE_UINT16(_scriptData);
+
+ while (index) {
+ if (*res++)
+ continue;
+ index--;
+ }
+
+ return (const char *)res;
+}
+
+int EoBInfProcessor::oeob_setWallType(int8 *data) {
+ int8 *pos = data;
+
+ uint16 block = 0;
+ int8 dir = 0;
+
+ switch (*pos++) {
+ case -23:
+ block = READ_LE_UINT16(pos);
+ pos += 2;
+ dir = *pos++;
+ _vm->_levelBlockProperties[block].walls[dir] = *pos++;
+ _vm->checkSceneUpdateNeed(block);
+ break;
+
+ case -19:
+ _vm->_currentDirection = *pos++;
+ break;
+
+ case -9:
+ block = READ_LE_UINT16(pos);
+ pos += 2;
+ dir = *pos++;
+ memset(_vm->_levelBlockProperties[block].walls, dir, 4 * sizeof(uint8));
+ _vm->checkSceneUpdateNeed(block);
+ break;
+
+ default:
+ break;
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_toggleWallState(int8 *data) {
+ int8 *pos = data;
+
+ uint16 block = 0;
+ int8 dir = 0;
+ uint8 a = 0;
+ uint8 b = 0;
+
+ switch (*pos++) {
+ case -23:
+ block = READ_LE_UINT16(pos);
+ pos += 2;
+ dir = *pos++;
+ a = (uint8)*pos++;
+ b = (uint8)*pos++;
+ a = (_vm->_levelBlockProperties[block].walls[dir] == a) ? b : a;
+ _vm->_levelBlockProperties[block].walls[dir] = a;
+ _vm->checkSceneUpdateNeed(block);
+ break;
+
+ case -22:
+ _vm->processDoorSwitch(READ_LE_UINT16(pos), 0);
+ pos += 2;
+ break;
+
+ case -9:
+ block = READ_LE_UINT16(pos);
+ pos += 2;
+ a = (uint8)*pos++;
+ b = (uint8)*pos++;
+ a = (_vm->_levelBlockProperties[block].walls[dir] == a) ? b : a;
+ memset(_vm->_levelBlockProperties[block].walls, a, 4 * sizeof(uint8));
+ _vm->checkSceneUpdateNeed(block);
+ break;
+
+ default:
+ break;
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_openDoor(int8 *data) {
+ int8 *pos = data;
+ _vm->openDoor(READ_LE_UINT16(pos));
+ pos += 2;
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_closeDoor(int8 *data) {
+ int8 *pos = data;
+ _vm->closeDoor(READ_LE_UINT16(pos));
+ pos += 2;
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_replaceMonster(int8 *data) {
+ int8 *pos = data;
+ _vm->replaceMonster(pos[1], READ_LE_UINT16(pos + 2), pos[4], pos[5], pos[6], pos[7], pos[8], pos[9], READ_LE_UINT16(pos + 10), READ_LE_UINT16(pos + 12));
+ pos += 14;
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_movePartyOrObject(int8 *data) {
+ int8 *pos = data;
+
+ int8 a = *pos++;
+ uint16 b = 0xFFFF;
+ uint16 c = 0;
+ uint16 d = 0;
+
+ if (_vm->game() == GI_EOB2 && a == -31) {
+ b = READ_LE_UINT16(pos);
+ pos += 2;
+ }
+
+ if (_vm->game() == GI_EOB1) {
+ if (a != -15) {
+ c = READ_LE_UINT16(pos);
+ pos += 2;
+ }
+ d = READ_LE_UINT16(pos);
+ pos += 2;
+ }
+
+ if (_vm->game() == GI_EOB2 && a != -31 && a != -11) {
+ c = READ_LE_UINT16(pos);
+ pos += 2;
+ d = READ_LE_UINT16(pos);
+ pos += 2;
+ }
+
+ if (a == -13) {
+ // move monster from block c to block d
+ for (int i = 0; i < 30; i++) {
+ if (_vm->_monsters[i].block != c)
+ continue;
+ _vm->placeMonster(&_vm->_monsters[i], d, _vm->_monsters[i].pos);
+ }
+ debugC(5, kDebugLevelScript, " - move monsters on block '0x%.04X' to block '0x%.04X'", c, d);
+
+ } else if (a == -24) {
+ // move party to block d
+ int ba = _dlgResult;
+ int bb = _lastScriptFunc;
+ int bc = _lastScriptFlags;
+ int bd = _abortScript;
+ int be = _activeCharacter;
+ int bf = _subroutineStackPos;
+
+ _vm->moveParty(d);
+ debugC(5, kDebugLevelScript, " - move party to block '0x%.04X'", d);
+
+ _dlgResult = ba;
+ _lastScriptFunc = bb;
+ _lastScriptFlags = bc;
+ _abortScript = bd;
+ _activeCharacter = be;
+ if (!_abortAfterSubroutine)
+ _subroutineStackPos = bf;
+ _vm->_sceneDefaultUpdate = 0;
+
+ } else if ((a == -31 && _vm->game() == GI_EOB2) || a == -11) {
+ // move item
+ int8 e = _vm->_currentLevel;
+ int8 f = _vm->_currentLevel;
+
+ if (_vm->game() == GI_EOB2) {
+ e = (*pos++ == -21) ? _vm->_currentLevel : *pos++;
+ c = READ_LE_UINT16(pos);
+ pos += 2;
+ f = (*pos++ == -21) ? _vm->_currentLevel : *pos++;
+ d = READ_LE_UINT16(pos);
+ pos += 2;
+ }
+
+ if (e == _vm->_currentLevel) {
+ int i = _vm->countQueuedItems(_vm->_levelBlockProperties[c].drawObjects, -1, (int16)b, 0, 1);
+ while (i) {
+ int p = _vm->_items[i].pos;
+ _vm->getQueuedItem((Item *)&_vm->_levelBlockProperties[c].drawObjects, 0, i);
+ if (_vm->_currentLevel == f) {
+ _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[d].drawObjects, d, i, p);
+ } else {
+ _vm->_items[i].level = f;
+ _vm->_items[i].block = d;
+ if (p < 8)
+ _vm->_items[i].pos = p & 3;
+ }
+ i = _vm->countQueuedItems(_vm->_levelBlockProperties[c].drawObjects, -1, (int16)b, 0, 1);
+ }
+
+ for (i = 0; i < 10; i++) {
+ if (_vm->_flyingObjects[i].enable != 1 || _vm->_flyingObjects[i].curBlock != c)
+ continue;
+ if (f == _vm->_currentLevel || _vm->game() == GI_EOB1)
+ _vm->_flyingObjects[i].curBlock = d;
+ else
+ _vm->_flyingObjects[i].enable = 0;
+ }
+
+ } else {
+ for (int i = 0; i < 600; i++) {
+ if (_vm->_items[i].level != e || _vm->_items[i].block != c)
+ continue;
+ _vm->_items[i].level = f;
+ _vm->_items[i].block = d;
+ }
+ }
+ debugC(5, kDebugLevelScript, " - move items from level '%d', block '0x%.04X' to level '%d', block '0x%.04X'", c, e, d, f);
+ }
+
+ _vm->_sceneUpdateRequired = true;
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_moveInventoryItemToBlock(int8 *data) {
+ int8 *pos = data;
+ int8 c = *pos++;
+ uint16 block = READ_LE_UINT16(pos);
+ pos += 2;
+ int8 p = *pos++;
+
+ if (c == -1)
+ c = _vm->rollDice(1, 6, -1);
+
+ while (!(_vm->_characters[c].flags & 1)) {
+ if (++c == 5)
+ c = 0;
+ }
+
+ if (_vm->_currentControlMode && (_vm->_updateCharNum == c))
+ return pos - data;
+
+ int slot = _vm->rollDice(1, 27, 0);
+ int itm = 0;
+ int i = 0;
+
+ for (; i < 27; i++) {
+ if ((!_vm->_currentControlMode && slot > 1) || slot == 16)
+ continue;
+
+ itm = _vm->_characters[c].inventory[slot];
+
+ if (!itm)
+ continue;
+
+ if (_vm->_dscItemShapeMap[_vm->_items[itm].icon] >= 15)
+ break;
+
+ if (++slot == 27)
+ slot = 0;
+ }
+
+ if (i < 27 && itm) {
+ _vm->_characters[c].inventory[slot] = 0;
+ _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[block].drawObjects, block, itm, p);
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_printMessage_v1(int8 *data) {
+ static const char colorConfig[] = "\x6\x21\x2\x21";
+ char col[5];
+ int8 *pos = data;
+
+ strcpy(col, colorConfig);
+ const char *str = (const char *)pos;
+ pos += (strlen(str) + 1);
+
+ col[1] = *pos++;
+ col[3] = *pos++;
+ _vm->txt()->printMessage(col);
+ _vm->txt()->printMessage(str);
+
+ col[1] = _screen->_curDim->unk8;
+ col[3] = _screen->_curDim->unkA;
+ _vm->txt()->printMessage(col);
+ _vm->txt()->printMessage("\r");
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_printMessage_v2(int8 *data) {
+ int8 *pos = data;
+ uint16 str = READ_LE_UINT16(pos);
+ pos += 2;
+ uint8 col = (uint8)*pos;
+ pos += 2;
+
+ int c = 0;
+ if (_activeCharacter == -1) {
+ c = _vm->rollDice(1, 6, -1);
+ while (!_vm->testCharacter(c, 3))
+ c = (c + 1) % 6;
+ } else {
+ c = _activeCharacter;
+ }
+
+ _vm->txt()->printMessage(getString(str), col, _vm->_characters[c].name);
+ _vm->txt()->printMessage("\r");
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_setFlags(int8 *data) {
+ int8 *pos = data;
+ int8 b = 0;
+
+ switch (*pos++) {
+ case -47:
+ _preventRest = 0;
+ debugC(5, kDebugLevelScript, " - set preventRest to 0");
+ break;
+
+ case -28:
+ _dlgResult = 1;
+ debugC(5, kDebugLevelScript, " - set dlgResult to 1");
+ break;
+
+ case -17:
+ _flagTable[_vm->_currentLevel] |= (1 << (*pos++));
+ debugC(5, kDebugLevelScript, " - set level flag '%d' for current level (current level = '%d')", *(pos - 1), _vm->_currentLevel);
+ break;
+
+ case -16:
+ _flagTable[17] |= (1 << (*pos++));
+ debugC(5, kDebugLevelScript, " - set global flag '%d'", *(pos - 1));
+ break;
+
+ case -13:
+ b = *pos++;
+ _vm->_monsters[b].flags |= (1 << (*pos++));
+ _vm->_monsters[b].mode = 0;
+ debugC(5, kDebugLevelScript, " - set monster flag '%d' for monster '%d'", *(pos - 1), b);
+ break;
+
+ default:
+ break;
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_playSoundEffect(int8 *data) {
+ int8 *pos = data;
+ uint16 block = READ_LE_UINT16(pos + 1);
+
+ if (block) {
+ _vm->snd_processEnvironmentalSoundEffect(pos[0], block);
+ } else {
+ _vm->snd_playSoundEffect(pos[0]);
+ }
+
+ pos += 3;
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_removeFlags(int8 *data) {
+ int8 *pos = data;
+ int8 a = *pos++;
+
+ switch (a) {
+ case -47:
+ _preventRest = 1;
+ debugC(5, kDebugLevelScript, " - set preventRest to 1");
+ break;
+
+ case -28:
+ _dlgResult = 0;
+ debugC(5, kDebugLevelScript, " - set dlgResult to 0");
+ break;
+
+ case -17:
+ _flagTable[_vm->_currentLevel] &= ~(1 << (*pos++));
+ debugC(5, kDebugLevelScript, " - clear level flag '%d' for current level (current level = '%d')", *(pos - 1), _vm->_currentLevel);
+ break;
+
+ case -16:
+ _flagTable[17] &= ~(1 << (*pos++));
+ debugC(5, kDebugLevelScript, " - clear global flag '%d'", *(pos - 1));
+ break;
+
+ default:
+ break;
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_modifyCharacterHitPoints(int8 *data) {
+ int8 *pos = data;
+ int8 c = *pos++;
+ int8 p = *pos++;
+
+ if (c == -1) {
+ for (c = 0; c < 6; c++)
+ _vm->modifyCharacterHitpoints(c, p);
+ } else {
+ _vm->modifyCharacterHitpoints(c, p);
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_calcAndInflictCharacterDamage(int8 *data) {
+ int8 *pos = data;
+ int charIndex = *pos++;
+ int times = *pos++;
+ int itemOrPips = *pos++;
+ int useStrModifierOrBase = *pos++;
+
+ int flg = (charIndex == -1) ? 4 : 0;
+ int savingThrowType = 5;
+ int savingThrowEffect = 1;
+
+ if (_vm->game() == GI_EOB2) {
+ flg = *pos++;
+ savingThrowType = *pos++;
+ savingThrowEffect = *pos++;
+ } else if (!itemOrPips) {
+ useStrModifierOrBase = times;
+ times = 0;
+ }
+
+ if (charIndex == -1) {
+ for (int i = 0; i < 6; i++)
+ _vm->calcAndInflictCharacterDamage(i, times, itemOrPips, useStrModifierOrBase, flg, savingThrowType, savingThrowEffect);
+ } else {
+ _vm->calcAndInflictCharacterDamage(charIndex, times, itemOrPips, useStrModifierOrBase, flg, savingThrowType, savingThrowEffect);
+ }
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_jump(int8 *data) {
+ int8 *pos = data;
+ pos = _scriptData + READ_LE_UINT16(pos);
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_end(int8 *data) {
+ _abortScript = 1;
+ _subroutineStackPos = 0;
+ return 0;
+}
+
+int EoBInfProcessor::oeob_returnFromSubroutine(int8 *data) {
+ int8 *pos = data;
+
+ if (_subroutineStackPos)
+ pos = _subroutineStack[--_subroutineStackPos];
+ else
+ _abortScript = 1;
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_callSubroutine(int8 *data) {
+ int8 *pos = data;
+ uint16 offs = READ_LE_UINT16(pos);
+ assert(offs < _scriptSize);
+ pos += 2;
+
+ if (_subroutineStackPos < 10) {
+ _subroutineStack[_subroutineStackPos++] = pos;
+ pos = _scriptData + offs;
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_eval_v1(int8 *data) {
+ int8 *pos = data;
+ int8 cmd = *pos++;
+
+ int a = 0;
+ int b = 0;
+ int i = 0;
+ EoBItem *itm = &_vm->_items[_vm->_itemInHand];
+ Common::String tempString1;
+ Common::String tempString2;
+
+ while (cmd != -18) {
+ switch (cmd + 38) {
+ case 0:
+ a = 1;
+ for (i = 0; i < 6; i++) {
+ if (!(_vm->_characters[i].flags & 1))
+ continue;
+ if (_vm->_characters[i].effectFlags & 0x40)
+ continue;
+ a = 0;
+ break;
+ }
+ _stack[_stackIndex++] = a;
+ debugC(5, kDebugLevelScript, " - check if whole party is invisible - PUSH result: '%d'", a);
+ break;
+
+ case 1:
+ _stack[_stackIndex++] = _vm->rollDice(pos[0], pos[1], pos[2]);
+ debugC(9, kDebugLevelScript, " - throw dice(s): num = '%d', pips = '%d', offset = '%d' - PUSH result: '%d'", pos[0], pos[1], pos[2], _stack[_stackIndex - 1]);
+ pos += 3;
+ break;
+
+ case 2:
+ cmd = *pos++;
+ b = 0;
+ for (i = 0; i < 6; i++) {
+ if (!(_vm->_characters[i].flags & 1))
+ continue;
+ if (_vm->_classModifierFlags[_vm->_characters[i].cClass] & cmd) {
+ b = 1;
+ break;
+ }
+ }
+ _stack[_stackIndex++] = b;
+ debugC(5, kDebugLevelScript, " - check if character with class flags '0x%.02X' is present - PUSH result: '%d'", cmd, b);
+ break;
+
+ case 3:
+ cmd = *pos++;
+ b = 0;
+ for (i = 0; i < 6; i++) {
+ if (!(_vm->_characters[i].flags & 1))
+ continue;
+ if ((_vm->_characters[i].raceSex >> 1) == cmd) {
+ b = 1;
+ break;
+ }
+ }
+ _stack[_stackIndex++] = b;
+ debugC(5, kDebugLevelScript, " - check if character with race '%d' is present - PUSH result: '%d'", cmd, b);
+ break;
+
+ case 6:
+ _stack[_stackIndex++] = _lastScriptFlags;
+ debugC(5, kDebugLevelScript, " - get script execution flags - PUSH result: '%d'", _lastScriptFlags);
+ break;
+
+ case 13:
+ itm = &_vm->_items[_vm->_itemInHand];
+ switch (*pos++) {
+ case -31:
+ _stack[_stackIndex++] = itm->type;
+ debugC(5, kDebugLevelScript, " - get hand item type (hand item number = '%d') - PUSH result: '%d'", _vm->_itemInHand, itm->type);
+ break;
+
+ case -11:
+ _stack[_stackIndex++] = _vm->_itemInHand;
+ debugC(5, kDebugLevelScript, " - get hand item number - PUSH result: '%d'", _vm->_itemInHand);
+ break;
+
+ default:
+ _stack[_stackIndex++] = itm->value;
+ debugC(5, kDebugLevelScript, " - get hand item value (hand item number = '%d') - PUSH result: '%d'", _vm->_itemInHand, itm->value);
+ break;
+ }
+ break;
+
+ case 15:
+ _stack[_stackIndex++] = _vm->_levelBlockProperties[READ_LE_UINT16(pos + 1)].walls[pos[0]];
+ debugC(5, kDebugLevelScript, " - get wall index for block '0x%.04X', direction '%d' - PUSH result: '%d'", READ_LE_UINT16(pos + 1), pos[0], _stack[_stackIndex - 1]);
+ pos += 3;
+ break;
+
+ case 19:
+ _stack[_stackIndex++] = _vm->_currentDirection;
+ debugC(5, kDebugLevelScript, " - get current direction - PUSH result: '%d'", _vm->_currentDirection);
+ break;
+
+ case 21:
+ _stack[_stackIndex++] = (_flagTable[_vm->_currentLevel] & (1 << (*pos++))) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - test level flag '%d' (current level = '%d') - PUSH result: '%d'", *(pos - 1), _vm->_currentLevel, _stack[_stackIndex - 1]);
+ break;
+
+ case 22:
+ _stack[_stackIndex++] = (_flagTable[17] & (1 << (*pos++))) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - test global flag '%d' - PUSH result: '%d'", *(pos - 1), _stack[_stackIndex - 1]);
+ break;
+
+ case 23:
+ _stack[_stackIndex++] = (_vm->_currentBlock == READ_LE_UINT16(pos)) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - compare current block with block '0x%.04X' (current block = '0x%.04X') - PUSH result: '%d'", _vm->_currentBlock, READ_LE_UINT16(pos), _stack[_stackIndex - 1]);
+ pos += 2;
+ break;
+
+ case 24:
+ a = (int16)READ_LE_UINT16(pos);
+ pos += 2;
+ b = READ_LE_UINT16(pos);
+ pos += 2;
+ _stack[_stackIndex++] = _vm->countQueuedItems(_vm->_levelBlockProperties[b].drawObjects, a, -1, 0, 1);
+ debugC(5, kDebugLevelScript, " - find item number '%d' on block '0x%.04X' - PUSH result: '%d'", a, b, _stack[_stackIndex - 1]);
+ break;
+
+ case 25:
+ _stack[_stackIndex++] = (_vm->_levelBlockProperties[READ_LE_UINT16(pos)].flags & 1) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - test block flag '1' for block '0x%.04X' - PUSH result: '%d'", READ_LE_UINT16(pos), _stack[_stackIndex - 1]);
+ pos += 2;
+ break;
+
+ case 27:
+ b = *pos++;
+ i = READ_LE_UINT16(pos);
+ pos += 2;
+ _stack[_stackIndex++] = _vm->countQueuedItems(_vm->_levelBlockProperties[i].drawObjects, -1, b, 1, 1);
+ debugC(5, kDebugLevelScript, " - count items of type '%d' on block '0x%.04X' - PUSH result: '%d'", b, i, _stack[_stackIndex - 1]);
+ break;
+
+ case 29:
+ _stack[_stackIndex++] = _vm->_levelBlockProperties[READ_LE_UINT16(pos)].walls[0];
+ debugC(5, kDebugLevelScript, " - get wall index 0 for block '0x%.04X' - PUSH result: '%d'", READ_LE_UINT16(pos), _stack[_stackIndex - 1]);
+ pos += 2;
+ break;
+
+ case 30:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a || b) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - evaluate: POP('%d') || POP('%d') - PUSH result: '%d'", a, b, _stack[_stackIndex - 1]);
+ break;
+
+ case 31:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a && b) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - evaluate: POP('%d') && POP('%d') - PUSH result: '%d'", a, b, _stack[_stackIndex - 1]);
+ break;
+
+ case 32:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a <= b) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - evaluate: POP('%d') <= POP('%d') - PUSH result: '%d'", a, b, _stack[_stackIndex - 1]);
+ break;
+
+ case 33:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a < b) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - evaluate: POP('%d') < POP('%d') - PUSH result: '%d'", a, b, _stack[_stackIndex - 1]);
+ break;
+
+ case 34:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a >= b) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - evaluate: POP('%d') >= POP('%d') - PUSH result: '%d'", a, b, _stack[_stackIndex - 1]);
+ break;
+
+ case 35:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a > b) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - evaluate: POP('%d') > POP('%d') - PUSH result: '%d'", a, b, _stack[_stackIndex - 1]);
+ break;
+
+ case 36:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a != b) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - evaluate: POP('%d') != POP('%d') - PUSH result: '%d'", a, b, _stack[_stackIndex - 1]);
+ break;
+
+ case 37:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a == b) ? 1 : 0;
+ debugC(5, kDebugLevelScript, " - evaluate: POP('%d') == POP('%d') - PUSH result: '%d'", a, b, _stack[_stackIndex - 1]);
+ break;
+
+ default:
+ a = cmd;
+ if (a >= 0 && a < 128)
+ _stack[_stackIndex++] = a;
+ debugC(5, kDebugLevelScript, " - PUSH value: '%d'", a);
+ break;
+ }
+ cmd = *pos++;
+ }
+
+ cmd = _stack[--_stackIndex];
+ if (cmd)
+ pos += 2;
+ else
+ pos = _scriptData + READ_LE_UINT16(pos);
+ debugC(5, kDebugLevelScript, " - conditional jump depending on POP('%d')", cmd);
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_eval_v2(int8 *data) {
+ int8 *pos = data;
+ int8 cmd = *pos++;
+
+ int a = 0;
+ int b = 0;
+ int i = 0;
+ EoBItem *itm = (_vm->_itemInHand != -1) ? &_vm->_items[_vm->_itemInHand] : 0;
+ Common::String tempString1;
+ Common::String tempString2;
+
+ while (cmd != -18) {
+ switch (cmd + 50) {
+ case 0:
+ a = 0;
+ b = *pos++;
+
+ for (i = 0; i < 6; i++) {
+ if (!_vm->testCharacter(i, 5))
+ continue;
+
+ if (_vm->_characters[i].portrait != b) {
+ a = 1;
+ _activeCharacter = i;
+ break;
+ }
+ }
+
+ _stack[_stackIndex++] = a;
+ break;
+
+ case 4:
+ _stack[_stackIndex++] = (int16)READ_LE_UINT16(pos);
+ pos += 2;
+ break;
+
+ case 9:
+ switch (*pos++) {
+ case -36:
+ _stack[_stackIndex++] = _vm->_itemTypes[_vm->_items[_vm->_lastUsedItem].type].extraProperties & 0x7F;
+ break;
+ case -31:
+ _stack[_stackIndex++] = _vm->_items[_vm->_lastUsedItem].type;
+ break;
+ case -11:
+ _stack[_stackIndex++] = _vm->_lastUsedItem;
+ break;
+ case -10:
+ _stack[_stackIndex++] = _vm->_items[_vm->_lastUsedItem].value;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case 12:
+ a = 1;
+ for (i = 0; i < 6; i++) {
+ if (!(_vm->_characters[i].flags & 1))
+ continue;
+ if (_vm->_characters[i].effectFlags & 0x40)
+ continue;
+ a = 0;
+ break;
+ }
+ _stack[_stackIndex++] = a;
+ break;
+
+ case 13:
+ _stack[_stackIndex++] = _vm->rollDice(pos[0], pos[1], pos[2]);
+ pos += 3;
+ break;
+
+ case 14:
+ cmd = *pos++;
+ a = _vm->rollDice(1, 6);
+ b = 0;
+ for (i = 0; i < 6 && b == 0; i++) {
+ if (++a > 5)
+ a = 0;
+ if (_vm->testCharacter(a, 5)) {
+ if (_vm->_classModifierFlags[_vm->_characters[a].cClass] & cmd) {
+ _activeCharacter = a;
+ b = 1;
+ }
+ }
+ }
+ _stack[_stackIndex++] = b;
+ break;
+
+ case 15:
+ cmd = *pos++;
+ a = _vm->rollDice(1, 6);
+ b = 0;
+ for (i = 0; i < 6; i++) {
+ if (++a > 5)
+ a = 0;
+ if (_vm->testCharacter(a, 5)) {
+ if ((_vm->_characters[a].raceSex >> 1) == cmd) {
+ _activeCharacter = a;
+ b = 1;
+ }
+ }
+ }
+ _stack[_stackIndex++] = b;
+ break;
+
+ case 17:
+ _stack[_stackIndex++] = _vm->_activeSpell;
+ break;
+
+ case 18:
+ _stack[_stackIndex++] = _lastScriptFlags;
+ break;
+
+ case 22:
+ _stack[_stackIndex++] = _dlgResult;
+ break;
+
+ case 25:
+ itm = &_vm->_items[_vm->_itemInHand];
+
+ switch (*pos++) {
+ case -49:
+ a = *pos++;
+ tempString1 = _vm->_itemNames[itm->nameId];
+ tempString1.toUppercase();
+ tempString2 = (const char *)pos;
+ tempString2.toUppercase();
+ pos += a;
+ _stack[_stackIndex++] = tempString1.contains(tempString2) ? 1 : 0;
+ break;
+
+ case -48:
+ a = *pos++;
+ tempString1 = _vm->_itemNames[itm->nameUnid];
+ tempString1.toUppercase();
+ tempString2 = (const char *)pos;
+ tempString2.toUppercase();
+ pos += a;
+ _stack[_stackIndex++] = tempString1.contains(tempString2) ? 1 : 0;
+ break;
+
+ case -31:
+ _stack[_stackIndex++] = itm->type;
+ break;
+
+ case -11:
+ _stack[_stackIndex++] = _vm->_itemInHand;
+ break;
+
+ case -10:
+ _stack[_stackIndex++] = itm->value;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case 26:
+ a = 0;
+ for (i = 0; i < 6; i++) {
+ if (_vm->testCharacter(i, 0x0F))
+ a++;
+ }
+ _stack[_stackIndex++] = a;
+ break;
+
+ case 27:
+ _stack[_stackIndex++] = _vm->_levelBlockProperties[READ_LE_UINT16(pos + 1)].walls[pos[0]];
+ pos += 3;
+ break;
+
+ case 31:
+ _stack[_stackIndex++] = _vm->_currentDirection;
+ break;
+
+ case 33:
+ _stack[_stackIndex++] = (_flagTable[_vm->_currentLevel] & (1 << (*pos++))) ? 1 : 0;
+ break;
+
+ case 34:
+ _stack[_stackIndex++] = (_flagTable[17] & (1 << (*pos++))) ? 1 : 0;
+ break;
+
+ case 35:
+ if (*pos++ == -11) {
+ a = (int16)READ_LE_UINT16(pos);
+ pos += 2;
+ b = (int16)READ_LE_UINT16(pos);
+ pos += 2;
+ _stack[_stackIndex++] = _vm->countCharactersWithSpecificItems(a, b);
+ } else {
+ _stack[_stackIndex++] = (_vm->_currentBlock == READ_LE_UINT16(pos)) ? 1 : 0;
+ pos += 2;
+ }
+ break;
+
+ case 36:
+ a = (int16)READ_LE_UINT16(pos);
+ pos += 2;
+ b = READ_LE_UINT16(pos);
+ pos += 2;
+ _stack[_stackIndex++] = _vm->countQueuedItems(_vm->_levelBlockProperties[b].drawObjects, a, -1, 0, 0);
+ break;
+
+ case 37:
+ if (*pos++ == -1) {
+ _stack[_stackIndex++] = _vm->_levelBlockProperties[READ_LE_UINT16(pos)].flags & 7;
+ pos += 2;
+ } else {
+ do {
+ a += _vm->countSpecificMonsters(*pos++);
+ } while (*pos != -1);
+ pos++;
+ _stack[_stackIndex++] = a;
+ }
+ break;
+
+ case 39:
+ a = *pos++;
+ b = *pos++;
+ i = READ_LE_UINT16(pos);
+ pos += 2;
+ _stack[_stackIndex++] = _vm->countQueuedItems(_vm->_levelBlockProperties[i].drawObjects, -1, b, 1, a);
+ break;
+
+ case 41:
+ _stack[_stackIndex++] = _vm->_levelBlockProperties[READ_LE_UINT16(pos)].walls[0];
+ pos += 2;
+ break;
+
+ case 42:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a || b) ? 1 : 0;
+ break;
+
+ case 43:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a && b) ? 1 : 0;
+ break;
+
+ case 44:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a <= b) ? 1 : 0;
+ break;
+
+ case 45:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a < b) ? 1 : 0;
+ break;
+
+ case 46:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a >= b) ? 1 : 0;
+ break;
+
+ case 47:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a > b) ? 1 : 0;
+ break;
+
+ case 48:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a != b) ? 1 : 0;
+ break;
+
+ case 49:
+ a = _stack[--_stackIndex];
+ b = _stack[--_stackIndex];
+ _stack[_stackIndex++] = (a == b) ? 1 : 0;
+ break;
+
+ default:
+ break;
+ }
+ cmd = *pos++;
+ }
+
+ cmd = _stack[--_stackIndex];
+ if (cmd)
+ pos += 2;
+ else
+ pos = _scriptData + READ_LE_UINT16(pos);
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_deleteItem(int8 *data) {
+ int8 *pos = data;
+ int8 c = *pos++;
+
+ if (c == -1) {
+ _vm->deleteInventoryItem(0, -1);
+ debugC(5, kDebugLevelScript, " - delete hand item");
+ } else {
+ _vm->deleteBlockItem(READ_LE_UINT16(pos), (c == -2) ? -1 : c);
+ debugC(5, kDebugLevelScript, " - delete item(s) of type '%d' on block '0x%.04X'", (c == -2) ? -1 : c, READ_LE_UINT16(pos));
+ pos += 2;
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_loadNewLevelOrMonsters(int8 *data) {
+ int8 *pos = data;
+ _vm->gui_updateControls();
+
+ int8 cmd = *pos++;
+ int8 index = *pos++;
+ int res = 0;
+
+ if (cmd == -27 || _vm->game() == GI_EOB1) {
+ cmd = _vm->game() == GI_EOB2 ? *pos++ : 0;
+ _vm->_currentBlock = READ_LE_UINT16(pos);
+ pos += 2;
+ uint8 dir = (uint8)*pos++;
+
+ if (dir != 0xFF)
+ _vm->_currentDirection = dir;
+
+ for (int i = 0; i < 30; i++)
+ _vm->_monsters[i].curAttackFrame = 0;
+
+ for (int i = 0; i < 10; i++) {
+ EoBFlyingObject *fo = &_vm->_flyingObjects[i];
+ if (fo->enable == 1) {
+ _vm->_items[fo->item].pos &= 3;
+ run(_vm->_items[fo->item].block, 4);
+ }
+ fo->enable = 0;
+ }
+
+ _vm->completeDoorOperations();
+
+ _vm->generateTempData();
+ _vm->txt()->removePageBreakFlag();
+ _screen->setScreenDim(7);
+
+ _vm->loadLevel(index, cmd);
+ debugC(5, kDebugLevelScript, " - entering level '%d', sub level '%d', start block '0x%.04X', start direction '%d'", index, cmd, _vm->_currentBlock, _vm->_currentDirection);
+
+ if (_vm->_dialogueField)
+ _vm->restoreAfterDialogueSequence();
+
+ _vm->moveParty(_vm->_currentBlock);
+
+ _abortScript = 1;
+ _abortAfterSubroutine = 1;
+ _vm->_sceneUpdateRequired = true;
+
+ _vm->gui_drawAllCharPortraitsWithStats();
+ _subroutineStackPos = 0;
+
+ } else {
+ cmd = *pos++;
+ _vm->releaseMonsterShapes(cmd * 18, 18);
+ _vm->loadMonsterShapes((const char *)pos, cmd * 18, true, index * 18);
+ debugC(5, kDebugLevelScript, " - loading monster shapes '%s', monster number '%d', encode type '%d'", (const char *)pos, cmd, index);
+ pos += 13;
+ _vm->gui_restorePlayField();
+ res = pos - data;
+ }
+
+ return res;
+}
+
+int EoBInfProcessor::oeob_increasePartyExperience(int8 *data) {
+ int8 *pos = data;
+ if (*pos++ == -30) {
+ _vm->increasePartyExperience((int16)READ_LE_UINT16(pos));
+ debugC(5, kDebugLevelScript, " - award '%d' experience points", READ_LE_UINT16(pos));
+ pos += 2;
+ }
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_createItem_v1(int8 *data) {
+ int8 *pos = data;
+ uint16 itm = _vm->duplicateItem(READ_LE_UINT16(pos));
+ pos += 2;
+ uint16 block = READ_LE_UINT16(pos);
+ pos += 2;
+ uint8 itmPos = *pos++;
+
+ if (itm) {
+ if (block == 0xFFFF && !_vm->_itemInHand) {
+ _vm->setHandItem(itm);
+ debugC(5, kDebugLevelScript, " - create hand item '%d'", itm);
+ } else if (block != 0xFFFF) {
+ _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[block & 0x3FF].drawObjects, block, itm, itmPos);
+ debugC(5, kDebugLevelScript, " - create item '%d' on block '0x%.04X', position '%d'", itm, block, itmPos);
+ }
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_createItem_v2(int8 *data) {
+ static const uint8 _itemPos[] = { 0, 1, 2, 3, 1, 3, 0, 2, 3, 2, 1, 0, 2, 0, 3, 1 };
+ int8 *pos = data;
+
+ uint16 itm = _vm->duplicateItem(READ_LE_UINT16(pos));
+ pos += 2;
+ uint16 block = READ_LE_UINT16(pos);
+ pos += 2;
+ uint8 itmPos = *pos++;
+ uint8 flg = *pos++;
+
+ if (flg & 1)
+ _vm->_items[itm].value = *pos++;
+
+ if (flg & 2)
+ _vm->_items[itm].flags = *pos++;
+
+ if (flg & 4)
+ _vm->_items[itm].icon = *pos++;
+
+ if (!itm)
+ return pos - data;
+
+ if (block == 0xFFFF) {
+ if (!_vm->_itemInHand) {
+ _vm->setHandItem(itm);
+ debugC(5, kDebugLevelScript, " - create hand item '%d' (value '%d', flags '0x%X', icon number '%d')", itm, _vm->_items[itm].value, _vm->_items[itm].flags, _vm->_items[itm].icon);
+ } else {
+ _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[_vm->_currentBlock & 0x3FF].drawObjects, _vm->_currentBlock, itm, _itemPos[_vm->rollDice(1, 2, -1)]);
+ debugC(5, kDebugLevelScript, " - create item '%d' (value '%d', flags '0x%X', icon number '%d') on current block", itm, _vm->_items[itm].value, _vm->_items[itm].flags, _vm->_items[itm].icon);
+ }
+ } else if (block == 0xFFFE) {
+ _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[_vm->_currentBlock & 0x3FF].drawObjects, _vm->_currentBlock, itm, _itemPos[(_vm->_currentDirection << 2) + _vm->rollDice(1, 2, -1)]);
+ debugC(5, kDebugLevelScript, " - create item '%d' (value '%d', flags '0x%X', icon number '%d') on current block", itm, _vm->_items[itm].value, _vm->_items[itm].flags, _vm->_items[itm].icon);
+ } else {
+ _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[block & 0x3FF].drawObjects, block, itm, itmPos);
+ debugC(5, kDebugLevelScript, " - create item '%d' (value '%d', flags '0x%X', icon number '%d') on block '0x%.04X', position '%d'", itm, _vm->_items[itm].value, _vm->_items[itm].flags, _vm->_items[itm].icon, block, itmPos);
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_launchObject(int8 *data) {
+ static const uint8 startPos[] = { 2, 3, 0, 2, 1, 0, 3, 1 };
+
+ int8 *pos = data;
+ bool m = (*pos++ == -33);
+ int i = READ_LE_UINT16(pos);
+ pos += 2;
+ uint16 block = READ_LE_UINT16(pos);
+ pos += 2;
+ int dir = *pos++;
+ int dirOffs = *pos++;
+
+ if (m) {
+ uint8 openBookType = _vm->_openBookType;
+ _vm->_openBookType = 0;
+ _vm->launchMagicObject(-1, i, block, startPos[dir * 2 + dirOffs], dir);
+ _vm->_openBookType = openBookType;
+ } else {
+ Item itm = _vm->duplicateItem(i);
+ if (itm) {
+ if (!_vm->launchObject(-1, itm, block, startPos[dir * 2 + dirOffs], dir, _vm->_items[itm].type))
+ _vm->_items[itm].block = -1;
+ }
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_changeDirection(int8 *data) {
+ int8 *pos = data;
+
+ int8 cmd = *pos++;
+ int8 dir = *pos++;
+
+ if (cmd == -15) {
+ _vm->_currentDirection = (_vm->_currentDirection + dir) & 3;
+ //_vm->_keybControlUnk = -1;
+ _vm->_sceneUpdateRequired = true;
+
+ } else if (cmd == -11) {
+ for (int i = 0; i < 10; i++) {
+ if (_vm->_flyingObjects[i].enable)
+ _vm->_flyingObjects[i].direction = (_vm->_flyingObjects[i].direction + dir) & 3;
+ }
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_identifyItems(int8 *data) {
+ int8 *pos = data;
+ uint16 block = READ_LE_UINT16(pos);
+
+ if (block == _vm->_currentBlock) {
+ for (int i = 0; i < 6; i++) {
+ if (!(_vm->_characters[i].flags & 1))
+ continue;
+
+ for (int ii = 0; ii < 27; ii++) {
+ int inv = _vm->_characters[i].inventory[ii];
+ if (inv)
+ _vm->_items[inv].flags |= 0x40;
+ }
+
+ _vm->identifyQueuedItems(_vm->_characters[i].inventory[16]);
+ }
+ }
+
+ _vm->identifyQueuedItems(_vm->_levelBlockProperties[block].drawObjects);
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_sequence(int8 *data) {
+ int8 *pos = data;
+ _vm->_npcSequenceSub = -1;
+ _vm->txt()->setWaitButtonMode(0);
+ _vm->gui_updateControls();
+ _vm->drawScene(1);
+
+ int cmd = *pos++;
+
+ if (_vm->game() == GI_EOB1) {
+ if (cmd == 10)
+ cmd = -1;
+ else if (cmd == 9)
+ cmd = -3;
+ else if (cmd == 8)
+ cmd = -2;
+ }
+
+ switch (cmd) {
+ case -3:
+ _vm->seq_xdeath();
+ _vm->_runFlag = false;
+ _vm->_playFinale = true;
+ _abortScript = 1;
+ return 0;
+
+ case -2:
+ _vm->seq_portal();
+ break;
+
+ case -1:
+ if (_vm->gameFlags().platform == Common::kPlatformDOS)
+ _vm->_runFlag = _vm->checkPassword();
+ break;
+
+ default:
+ _vm->npcSequence(cmd);
+ break;
+ }
+ _vm->screen()->setScreenDim(7);
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_delay(int8 *data) {
+ int8 *pos = data;
+ _vm->delay(READ_LE_UINT16(pos) * _vm->tickLength());
+ pos += 2;
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_drawScene(int8 *data) {
+ _vm->drawScene(1);
+ return 0;
+}
+
+int EoBInfProcessor::oeob_dialogue(int8 *data) {
+ int8 *pos = data;
+
+ switch (*pos++) {
+ case -45:
+ _vm->drawSequenceBitmap((const char *)pos, pos[13], READ_LE_UINT16(pos + 14), READ_LE_UINT16(pos + 16), READ_LE_UINT16(pos + 18));
+ pos += 20;
+ break;
+
+ case -44:
+ _vm->restoreAfterDialogueSequence();
+ break;
+
+ case -43:
+ _vm->initDialogueSequence();
+ break;
+
+ case -42:
+ _vm->gui_drawDialogueBox();
+ break;
+
+ case -40:
+ _dlgResult = _vm->runDialogue(READ_LE_UINT16(pos), READ_LE_UINT16(pos + 6) == 0xFFFF ? 2 : 3, getString(READ_LE_UINT16(pos + 2)), getString(READ_LE_UINT16(pos + 4)), getString(READ_LE_UINT16(pos + 6)));
+ pos += 8;
+ break;
+
+ case -8:
+ _vm->txt()->printDialogueText(READ_LE_UINT16(pos), getString(READ_LE_UINT16(pos + 2)));
+ pos += 4;
+ break;
+
+ default:
+ break;
+ }
+
+ return pos - data;
+}
+
+int EoBInfProcessor::oeob_specialEvent(int8 *data) {
+ int8 *pos = data;
+ uint16 cmd = READ_LE_UINT16(pos);
+ pos += 2;
+
+ uint32 endTime = 0;
+ int i = 0;
+
+ switch (cmd) {
+ case 0:
+ _vm->drawScene(1);
+ _screen->_curPage = 2;
+ _screen->copyRegion(72, 0, 0, 0, 32, 120, 2, 12, Screen::CR_NO_P_CHECK);
+
+ for (; i < 4; i++) {
+ endTime = _vm->_system->getMillis() + _vm->_tickLength;
+ _vm->drawLightningColumn();
+ _screen->copyRegion(72, 0, 72, 0, 32, 120, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ _screen->copyRegion(0, 0, 72, 0, 32, 120, 12, 2, Screen::CR_NO_P_CHECK);
+ _vm->delayUntil(endTime);
+ }
+
+ _screen->_curPage = 0;
+ _vm->_sceneUpdateRequired = true;
+ break;
+
+ case 1:
+ _dlgResult = _vm->charSelectDialogue();
+ break;
+
+ case 2:
+ _vm->characterLevelGain(_dlgResult);
+ break;
+
+ case 3:
+ _dlgResult = _vm->resurrectionSelectDialogue();
+ break;
+
+ case 4:
+ if (_vm->prepareForNewPartyMember(33, 5))
+ _vm->initNpc(4);
+ break;
+
+ case 5:
+ _vm->deletePartyItems(46, 5);
+ _vm->deletePartyItems(46, 6);
+ break;
+
+ case 6:
+ _vm->loadVcnData(0, 0);
+ break;
+
+ default:
+ break;
+ }
+
+ return pos - data;
+}
+
+} // End of namespace Kyra
+
+#endif // ENABLE_EOB