aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/engine/scene_lok.cpp
diff options
context:
space:
mode:
authorathrxx2019-01-26 01:31:34 +0100
committerathrxx2019-03-06 20:48:15 +0100
commit1dfdcc7252ac83643cae7a7447c025da2af63843 (patch)
treeb6736d006bf67d5264dd171c336f0915695d1f88 /engines/kyra/engine/scene_lok.cpp
parent8b53d20b51771680c3d31aa02c0285b7a8be4e85 (diff)
downloadscummvm-rg350-1dfdcc7252ac83643cae7a7447c025da2af63843.tar.gz
scummvm-rg350-1dfdcc7252ac83643cae7a7447c025da2af63843.tar.bz2
scummvm-rg350-1dfdcc7252ac83643cae7a7447c025da2af63843.zip
KYRA: cleanup dir
Reorganize all files in sub directories. The file placement isn't as intuitive as it might be for other engines, which is probably the reason why this hasn't been done before.
Diffstat (limited to 'engines/kyra/engine/scene_lok.cpp')
-rw-r--r--engines/kyra/engine/scene_lok.cpp1301
1 files changed, 1301 insertions, 0 deletions
diff --git a/engines/kyra/engine/scene_lok.cpp b/engines/kyra/engine/scene_lok.cpp
new file mode 100644
index 0000000000..51348c5392
--- /dev/null
+++ b/engines/kyra/engine/scene_lok.cpp
@@ -0,0 +1,1301 @@
+/* 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 "kyra/engine/kyra_lok.h"
+#include "kyra/resource/resource.h"
+#include "kyra/sound/sound.h"
+#include "kyra/engine/sprites.h"
+#include "kyra/graphics/animator_lok.h"
+#include "kyra/engine/timer.h"
+
+#include "common/system.h"
+
+namespace Kyra {
+
+void KyraEngine_LoK::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) {
+ int unkVar1 = 1;
+ _screen->hideMouse();
+
+ // TODO: Check how the original handled sfx still playing
+ _sound->stopAllSoundEffects();
+
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ int newSfxFile = -1;
+ if (_currentCharacter->sceneId == 7 && sceneId == 24)
+ newSfxFile = 2;
+ else if (_currentCharacter->sceneId == 25 && sceneId == 109)
+ newSfxFile = 3;
+ else if (_currentCharacter->sceneId == 120 && sceneId == 37)
+ newSfxFile = 4;
+ else if (_currentCharacter->sceneId == 52 && sceneId == 199)
+ newSfxFile = 5;
+ else if (_currentCharacter->sceneId == 37 && sceneId == 120)
+ newSfxFile = 3;
+ else if (_currentCharacter->sceneId == 109 && sceneId == 25)
+ newSfxFile = 2;
+ else if (_currentCharacter->sceneId == 24 && sceneId == 7)
+ newSfxFile = 1;
+
+ if (newSfxFile != -1) {
+ _curSfxFile = newSfxFile;
+ _sound->loadSoundFile(_curSfxFile);
+ }
+ }
+
+ switch (_currentCharacter->sceneId) {
+ case 1:
+ if (sceneId == 0) {
+ moveCharacterToPos(0, 0, _currentCharacter->x1, 84);
+ unkVar1 = 0;
+ }
+ break;
+
+ case 3:
+ if (sceneId == 2) {
+ moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
+ unkVar1 = 0;
+ }
+ break;
+
+ case 26:
+ if (sceneId == 27) {
+ moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
+ unkVar1 = 0;
+ }
+ break;
+
+ case 44:
+ if (sceneId == 45) {
+ moveCharacterToPos(0, 2, 192, _currentCharacter->y1);
+ unkVar1 = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (unkVar1 && unk1) {
+ int xpos = _currentCharacter->x1;
+ int ypos = _currentCharacter->y1;
+ switch (facing) {
+ case 0:
+ ypos = _currentCharacter->y1 - 6;
+ break;
+
+ case 2:
+ xpos = 336;
+ break;
+
+ case 4:
+ ypos = 143;
+ break;
+
+ case 6:
+ xpos = -16;
+ break;
+
+ default:
+ break;
+ }
+
+ moveCharacterToPos(0, facing, xpos, ypos);
+ }
+
+ for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i)
+ _movieObjects[i]->close();
+
+ if (!brandonAlive) {
+ _emc->init(&_scriptClick, &_scriptClickData);
+ _emc->start(&_scriptClick, 5);
+ while (_emc->isValid(&_scriptClick))
+ _emc->run(&_scriptClick);
+ }
+
+ memset(_entranceMouseCursorTracks, 0xFF, sizeof(_entranceMouseCursorTracks));
+ _currentCharacter->sceneId = sceneId;
+
+ assert(sceneId < _roomTableSize);
+ assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize);
+
+ Room *currentRoom = &_roomTable[sceneId];
+
+ setupSceneResource(sceneId);
+
+ _currentRoom = sceneId;
+
+ int tableId = _roomTable[sceneId].nameIndex;
+ char fileNameBuffer[32];
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".DAT");
+ _sprites->loadDat(fileNameBuffer, _sceneExits);
+ _sprites->setupSceneAnims();
+ _emc->unload(&_scriptClickData);
+ loadSceneMsc();
+
+ _walkBlockNorth = currentRoom->northExit;
+ _walkBlockEast = currentRoom->eastExit;
+ _walkBlockSouth = currentRoom->southExit;
+ _walkBlockWest = currentRoom->westExit;
+
+ if (_walkBlockNorth == 0xFFFF)
+ _screen->blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF) + 3);
+ if (_walkBlockEast == 0xFFFF)
+ _screen->blockOutRegion(312, 0, 8, 139);
+ if (_walkBlockSouth == 0xFFFF)
+ _screen->blockOutRegion(0, 135, 320, 8);
+ if (_walkBlockWest == 0xFFFF)
+ _screen->blockOutRegion(0, 0, 8, 139);
+
+ if (!brandonAlive)
+ updatePlayerItemsForScene();
+
+ startSceneScript(brandonAlive);
+ setupSceneItems();
+
+ initSceneData(facing, unk2, brandonAlive);
+
+ _loopFlag2 = 0;
+ _screen->showMouse();
+ if (!brandonAlive)
+ seq_poisonDeathNow(0);
+ updateMousePointer(true);
+ _changedScene = true;
+}
+
+void KyraEngine_LoK::transcendScenes(int roomIndex, int roomName) {
+ assert(roomIndex < _roomTableSize);
+
+ if (_flags.isTalkie) {
+ char file[32];
+ assert(roomIndex < _roomTableSize);
+ int tableId = _roomTable[roomIndex].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".VRM");
+ _res->unloadPakFile(file);
+ }
+
+ _roomTable[roomIndex].nameIndex = roomName;
+ _unkScreenVar2 = 1;
+ _unkScreenVar3 = 1;
+ _unkScreenVar1 = 0;
+ _brandonPosX = _currentCharacter->x1;
+ _brandonPosY = _currentCharacter->y1;
+ enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0);
+ _unkScreenVar1 = 1;
+ _unkScreenVar2 = 0;
+ _unkScreenVar3 = 0;
+}
+
+void KyraEngine_LoK::setSceneFile(int roomIndex, int roomName) {
+ assert(roomIndex < _roomTableSize);
+ _roomTable[roomIndex].nameIndex = roomName;
+}
+
+void KyraEngine_LoK::moveCharacterToPos(int character, int facing, int xpos, int ypos) {
+ Character *ch = &_characterList[character];
+ ch->facing = facing;
+ _screen->hideMouse();
+ xpos = (int16)(xpos & 0xFFFC);
+ ypos = (int16)(ypos & 0xFFFE);
+ _timer->disable(19);
+ _timer->disable(14);
+ _timer->disable(18);
+ uint32 nextFrame = 0;
+
+ switch (facing) {
+ case 0:
+ while (ypos < ch->y1) {
+ nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ delayUntil(nextFrame, true);
+ }
+ break;
+
+ case 2:
+ while (ch->x1 < xpos) {
+ nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ delayUntil(nextFrame, true);
+ }
+ break;
+
+ case 4:
+ while (ypos > ch->y1) {
+ nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ delayUntil(nextFrame, true);
+ }
+ break;
+
+ case 6:
+ while (ch->x1 > xpos) {
+ nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ delayUntil(nextFrame, true);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ _timer->enable(19);
+ _timer->enable(14);
+ _timer->enable(18);
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::setCharacterPositionWithUpdate(int character) {
+ setCharacterPosition(character, 0);
+ _sprites->updateSceneAnims();
+ _timer->update();
+ _animator->updateAllObjectShapes();
+ updateTextFade();
+
+ if (_currentCharacter->sceneId == 210)
+ updateKyragemFading();
+}
+
+int KyraEngine_LoK::setCharacterPosition(int character, int *facingTable) {
+ if (character == 0) {
+ _currentCharacter->x1 += _charAddXPosTable[_currentCharacter->facing];
+ _currentCharacter->y1 += _charAddYPosTable[_currentCharacter->facing];
+ setCharacterPositionHelper(0, facingTable);
+ return 1;
+ } else {
+ _characterList[character].x1 += _charAddXPosTable[_characterList[character].facing];
+ _characterList[character].y1 += _charAddYPosTable[_characterList[character].facing];
+ if (_characterList[character].sceneId == _currentCharacter->sceneId)
+ setCharacterPositionHelper(character, 0);
+ }
+ return 0;
+}
+
+void KyraEngine_LoK::setCharacterPositionHelper(int character, int *facingTable) {
+ Character *ch = &_characterList[character];
+ ++ch->currentAnimFrame;
+ int facing = ch->facing;
+ if (facingTable) {
+ if (*facingTable != *(facingTable - 1)) {
+ if (*(facingTable - 1) == *(facingTable + 1)) {
+ facing = getOppositeFacingDirection(*(facingTable - 1));
+ *facingTable = *(facingTable - 1);
+ }
+ }
+ }
+
+ if (facing == 0) {
+ ++_characterFacingZeroCount[character];
+ } else {
+ bool resetTables = false;
+ if (facing != 7) {
+ if (facing - 1 != 0) {
+ if (facing != 4) {
+ if (facing == 3 || facing == 5) {
+ if (_characterFacingFourCount[character] > 2)
+ facing = 4;
+ resetTables = true;
+ }
+ } else {
+ ++_characterFacingFourCount[character];
+ }
+ } else {
+ if (_characterFacingZeroCount[character] > 2)
+ facing = 0;
+ resetTables = true;
+ }
+ } else {
+ if (_characterFacingZeroCount[character] > 2)
+ facing = 0;
+ resetTables = true;
+ }
+
+ if (resetTables) {
+ _characterFacingZeroCount[character] = 0;
+ _characterFacingFourCount[character] = 0;
+ }
+ }
+
+ static const uint16 maxAnimationFrame[] = {
+ 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000,
+ 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000,
+ 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000,
+ 0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000,
+ 0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000,
+ 0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000,
+ 0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000
+ };
+
+ if (facing == 0) {
+ if (maxAnimationFrame[36 + character] > ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[36 + character];
+ if (maxAnimationFrame[30 + character] < ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[36 + character];
+ } else if (facing == 4) {
+ if (maxAnimationFrame[18 + character] > ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[18 + character];
+ if (maxAnimationFrame[12 + character] < ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[18 + character];
+ } else {
+ if (maxAnimationFrame[18 + character] < ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[30 + character];
+ if (maxAnimationFrame[character] == ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[6 + character];
+ if (maxAnimationFrame[character] < ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[6 + character] + 2;
+ }
+
+ if (character == 0 && (_brandonStatusBit & 0x10))
+ ch->currentAnimFrame = 88;
+
+ _animator->animRefreshNPC(character);
+}
+
+void KyraEngine_LoK::loadSceneMsc() {
+ assert(_currentCharacter->sceneId < _roomTableSize);
+ int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+ char fileNameBuffer[32];
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".MSC");
+ _screen->fillRect(0, 0, 319, 199, 0, 5);
+ _res->exists(fileNameBuffer, true);
+ _screen->loadBitmap(fileNameBuffer, 3, 5, 0);
+}
+
+void KyraEngine_LoK::startSceneScript(int brandonAlive) {
+ assert(_currentCharacter->sceneId < _roomTableSize);
+ int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+ char fileNameBuffer[32];
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".CPS");
+ _screen->clearPage(3);
+ _res->exists(fileNameBuffer, true);
+ // FIXME: check this hack for amiga version
+ _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? &_screen->getPalette(0) : 0));
+ _sprites->loadSceneShapes();
+ _exitListPtr = 0;
+
+ _scaleMode = 1;
+ for (int i = 0; i < 145; ++i)
+ _scaleTable[i] = 256;
+
+ clearNoDropRects();
+ _emc->init(&_scriptClick, &_scriptClickData);
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".EMC");
+ _res->exists(fileNameBuffer, true);
+ _emc->unload(&_scriptClickData);
+ _emc->load(fileNameBuffer, &_scriptClickData, &_opcodes);
+ _emc->start(&_scriptClick, 0);
+ _scriptClick.regs[0] = _currentCharacter->sceneId;
+ _scriptClick.regs[7] = brandonAlive;
+
+ while (_emc->isValid(&_scriptClick))
+ _emc->run(&_scriptClick);
+}
+
+void KyraEngine_LoK::initSceneData(int facing, int unk1, int brandonAlive) {
+ int16 xpos2 = 0;
+ int setFacing = 1;
+
+ int16 xpos = 0, ypos = 0;
+
+ if (_brandonPosX == -1 && _brandonPosY == -1) {
+ switch (facing + 1) {
+ case 0:
+ xpos = ypos = -1;
+ break;
+
+ case 1: case 2: case 8:
+ xpos = _sceneExits.southXPos;
+ ypos = _sceneExits.southYPos;
+ break;
+
+ case 3:
+ xpos = _sceneExits.westXPos;
+ ypos = _sceneExits.westYPos;
+ break;
+
+ case 4: case 5: case 6:
+ xpos = _sceneExits.northXPos;
+ ypos = _sceneExits.northYPos;
+ break;
+
+ case 7:
+ xpos = _sceneExits.eastXPos;
+ ypos = _sceneExits.eastYPos;
+ break;
+
+ default:
+ break;
+ }
+
+ if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos)
+ ypos = (_northExitHeight & 0xFF) + 4;
+ if (xpos >= 308)
+ xpos = 304;
+ if ((uint8)(_northExitHeight >> 8) - 2 <= ypos)
+ ypos = (_northExitHeight >> 8) - 4;
+ if (xpos <= 12)
+ xpos = 16;
+ }
+
+ if (_brandonPosX > -1)
+ xpos = _brandonPosX;
+ if (_brandonPosY > -1)
+ ypos = _brandonPosY;
+
+ int16 ypos2 = 0;
+ if (_brandonPosX > -1 && _brandonPosY > -1) {
+ switch (_currentCharacter->sceneId) {
+ case 1:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 4;
+ xpos2 = 192;
+ ypos2 = 104;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 3:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 2;
+ xpos2 = 204;
+ ypos2 = 94;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 26:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 2;
+ xpos2 = 192;
+ ypos2 = 128;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 44:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 6;
+ xpos2 = 156;
+ ypos2 = 96;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 37:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 2;
+ xpos2 = 148;
+ ypos2 = 114;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ _brandonPosX = _brandonPosY = -1;
+
+ if (unk1 && setFacing) {
+ ypos2 = ypos;
+ xpos2 = xpos;
+ switch (facing) {
+ case 0:
+ ypos = 142;
+ break;
+
+ case 2:
+ xpos = -16;
+ break;
+
+ case 4:
+ ypos = (uint8)(_northExitHeight & 0xFF) - 4;
+ break;
+
+ case 6:
+ xpos = 336;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ xpos2 = (int16)(xpos2 & 0xFFFC);
+ ypos2 = (int16)(ypos2 & 0xFFFE);
+ xpos = (int16)(xpos & 0xFFFC);
+ ypos = (int16)(ypos & 0xFFFE);
+ _currentCharacter->facing = facing;
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+
+ initSceneObjectList(brandonAlive);
+
+ if (unk1 && brandonAlive == 0)
+ moveCharacterToPos(0, facing, xpos2, ypos2);
+
+ _scriptClick.regs[4] = _itemInHand;
+ _scriptClick.regs[7] = brandonAlive;
+ _emc->start(&_scriptClick, 3);
+ while (_emc->isValid(&_scriptClick))
+ _emc->run(&_scriptClick);
+}
+
+void KyraEngine_LoK::initSceneObjectList(int brandonAlive) {
+ for (int i = 0; i < 28; ++i)
+ _animator->actors()[i].active = 0;
+
+ int startAnimFrame = 0;
+
+ Animator_LoK::AnimObject *curAnimState = _animator->actors();
+ curAnimState->active = 1;
+ curAnimState->drawY = _currentCharacter->y1;
+ curAnimState->sceneAnimPtr = _shapes[_currentCharacter->currentAnimFrame];
+ curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame;
+ startAnimFrame = _currentCharacter->currentAnimFrame - 7;
+ int xOffset = _defaultShapeTable[startAnimFrame].xOffset;
+ int yOffset = _defaultShapeTable[startAnimFrame].yOffset;
+
+ if (_scaleMode) {
+ curAnimState->x1 = _currentCharacter->x1;
+ curAnimState->y1 = _currentCharacter->y1;
+
+ _animator->_brandonScaleX = _scaleTable[_currentCharacter->y1];
+ _animator->_brandonScaleY = _scaleTable[_currentCharacter->y1];
+
+ curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8;
+ curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8;
+ } else {
+ curAnimState->x1 = _currentCharacter->x1 + xOffset;
+ curAnimState->y1 = _currentCharacter->y1 + yOffset;
+ }
+
+ curAnimState->x2 = curAnimState->x1;
+ curAnimState->y2 = curAnimState->y1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+ _animator->clearQueue();
+ _animator->addObjectToQueue(curAnimState);
+
+ int listAdded = 0;
+ int addedObjects = 1;
+
+ for (int i = 1; i < 5; ++i) {
+ Character *ch = &_characterList[i];
+ curAnimState = &_animator->actors()[addedObjects];
+ if (ch->sceneId != _currentCharacter->sceneId) {
+ curAnimState->active = 0;
+ curAnimState->refreshFlag = 0;
+ curAnimState->bkgdChangeFlag = 0;
+ ++addedObjects;
+ continue;
+ }
+
+ curAnimState->drawY = ch->y1;
+ curAnimState->sceneAnimPtr = _shapes[ch->currentAnimFrame];
+ curAnimState->animFrameNumber = ch->currentAnimFrame;
+ startAnimFrame = ch->currentAnimFrame - 7;
+ xOffset = _defaultShapeTable[startAnimFrame].xOffset;
+ yOffset = _defaultShapeTable[startAnimFrame].yOffset;
+ if (_scaleMode) {
+ curAnimState->x1 = ch->x1;
+ curAnimState->y1 = ch->y1;
+
+ _animator->_brandonScaleX = _scaleTable[ch->y1];
+ _animator->_brandonScaleY = _scaleTable[ch->y1];
+
+ curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8;
+ curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8;
+ } else {
+ curAnimState->x1 = ch->x1 + xOffset;
+ curAnimState->y1 = ch->y1 + yOffset;
+ }
+ curAnimState->x2 = curAnimState->x1;
+ curAnimState->y2 = curAnimState->y1;
+ curAnimState->active = 1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+
+ if (ch->facing >= 1 && ch->facing <= 3)
+ curAnimState->flags |= 1;
+ else if (ch->facing >= 5 && ch->facing <= 7)
+ curAnimState->flags &= 0xFFFFFFFE;
+
+ _animator->addObjectToQueue(curAnimState);
+
+ ++addedObjects;
+ ++listAdded;
+ if (listAdded < 2)
+ i = 5;
+ }
+
+ for (int i = 0; i < 11; ++i) {
+ curAnimState = &_animator->sprites()[i];
+
+ if (_sprites->_anims[i].play) {
+ curAnimState->active = 1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+ } else {
+ curAnimState->active = 0;
+ curAnimState->refreshFlag = 0;
+ curAnimState->bkgdChangeFlag = 0;
+ }
+ curAnimState->height = _sprites->_anims[i].height;
+ curAnimState->height2 = _sprites->_anims[i].height2;
+ curAnimState->width = _sprites->_anims[i].width + 1;
+ curAnimState->width2 = _sprites->_anims[i].width2;
+ curAnimState->drawY = _sprites->_anims[i].drawY;
+ curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x;
+ curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y;
+ curAnimState->background = _sprites->_anims[i].background;
+ curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite];
+
+ curAnimState->disable = _sprites->_anims[i].disable;
+
+ if (_sprites->_anims[i].unk2)
+ curAnimState->flags = 0x800;
+ else
+ curAnimState->flags = 0;
+
+ if (_sprites->_anims[i].flipX)
+ curAnimState->flags |= 0x1;
+
+ _animator->addObjectToQueue(curAnimState);
+ }
+
+ for (int i = 0; i < 12; ++i) {
+ curAnimState = &_animator->items()[i];
+ Room *curRoom = &_roomTable[_currentCharacter->sceneId];
+ byte curItem = curRoom->itemsTable[i];
+ if (curItem != 0xFF) {
+ curAnimState->drawY = curRoom->itemsYPos[i];
+ curAnimState->sceneAnimPtr = _shapes[216 + curItem];
+ curAnimState->animFrameNumber = (int16)0xFFFF;
+ curAnimState->y1 = curRoom->itemsYPos[i];
+ curAnimState->x1 = curRoom->itemsXPos[i];
+
+ curAnimState->x1 -= (_animator->fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1;
+ curAnimState->y1 -= _animator->fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]);
+
+ curAnimState->x2 = curAnimState->x1;
+ curAnimState->y2 = curAnimState->y1;
+
+ curAnimState->active = 1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+
+ _animator->addObjectToQueue(curAnimState);
+ } else {
+ curAnimState->active = 0;
+ curAnimState->refreshFlag = 0;
+ curAnimState->bkgdChangeFlag = 0;
+ }
+ }
+
+ _animator->preserveAnyChangedBackgrounds();
+ curAnimState = _animator->actors();
+ curAnimState->bkgdChangeFlag = 1;
+ curAnimState->refreshFlag = 1;
+ for (int i = 1; i < 28; ++i) {
+ curAnimState = &_animator->objects()[i];
+ if (curAnimState->active) {
+ curAnimState->bkgdChangeFlag = 1;
+ curAnimState->refreshFlag = 1;
+ }
+ }
+ _animator->restoreAllObjectBackgrounds();
+ _animator->preserveAnyChangedBackgrounds();
+ _animator->prepDrawAllObjects();
+ initSceneScreen(brandonAlive);
+ _animator->copyChangedObjectsForward(0);
+}
+
+void KyraEngine_LoK::initSceneScreen(int brandonAlive) {
+ if (_flags.platform == Common::kPlatformAmiga) {
+ if (_unkScreenVar1 && !queryGameFlag(0xF0)) {
+ _screen->getPalette(2).clear();
+ if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3))
+ _screen->setScreenPalette(_screen->getPalette(2));
+ }
+
+ if (_unkScreenVar2 == 1)
+ _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
+ else
+ _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0, Screen::CR_NO_P_CHECK);
+
+ if (_unkScreenVar1 && !queryGameFlag(0xA0)) {
+ if (_currentCharacter->sceneId == 45 && _cauldronState)
+ _screen->getPalette(0).copy(_screen->getPalette(4), 12, 1);
+
+ if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1))
+ _screen->copyPalette(0, 10);
+
+ _screen->setScreenPalette(_screen->getPalette(0));
+ }
+ } else {
+ if (_unkScreenVar1 && !queryGameFlag(0xA0)) {
+ for (int i = 0; i < 60; ++i) {
+ uint16 col = _screen->getPalette(0)[684 + i];
+ col += _screen->getPalette(1)[684 + i] << 1;
+ col >>= 2;
+ _screen->getPalette(0)[684 + i] = col;
+ }
+ _screen->setScreenPalette(_screen->getPalette(0));
+ }
+
+ if (_unkScreenVar2 == 1)
+ _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
+ else
+ _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
+
+ if (_unkScreenVar1 && _paletteChanged) {
+ if (!queryGameFlag(0xA0)) {
+ _screen->getPalette(0).copy(_screen->getPalette(1), 228, 20);
+ _screen->setScreenPalette(_screen->getPalette(0));
+ } else {
+ _screen->getPalette(0).clear();
+ }
+ }
+ }
+
+ if (!_emc->start(&_scriptClick, 2))
+ error("Could not start script function 2 of scene script");
+
+ _scriptClick.regs[7] = brandonAlive;
+
+ while (_emc->isValid(&_scriptClick))
+ _emc->run(&_scriptClick);
+
+ setTextFadeTimerCountdown(-1);
+
+ if (_currentCharacter->sceneId == 210) {
+ if (_itemInHand != kItemNone)
+ magicOutMouseItem(2, -1);
+
+ _screen->hideMouse();
+ for (int i = 0; i < 10; ++i) {
+ if (_currentCharacter->inventoryItems[i] != kItemNone)
+ magicOutMouseItem(2, i);
+ }
+ _screen->showMouse();
+ }
+}
+
+int KyraEngine_LoK::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) {
+ if (queryGameFlag(0xEF))
+ unk1 = 0;
+
+ int sceneId = _currentCharacter->sceneId;
+ _pathfinderFlag = 0;
+
+ if (xpos < 12) {
+ if (_roomTable[sceneId].westExit != 0xFFFF) {
+ xpos = 12;
+ ypos = _sceneExits.westYPos;
+ _pathfinderFlag = 7;
+ }
+ } else if (xpos >= 308) {
+ if (_roomTable[sceneId].eastExit != 0xFFFF) {
+ xpos = 307;
+ ypos = _sceneExits.eastYPos;
+ _pathfinderFlag = 13;
+ }
+ }
+
+ if (ypos <= (_northExitHeight & 0xFF) + 2) {
+ if (_roomTable[sceneId].northExit != 0xFFFF) {
+ xpos = _sceneExits.northXPos;
+ ypos = _northExitHeight & 0xFF;
+ _pathfinderFlag = 14;
+ }
+ } else if (ypos >= 136) {
+ if (_roomTable[sceneId].southExit != 0xFFFF) {
+ xpos = _sceneExits.southXPos;
+ ypos = 136;
+ _pathfinderFlag = 11;
+ }
+ }
+
+ int temp = xpos - _currentCharacter->x1;
+ if (ABS(temp) < 4) {
+ temp = ypos - _currentCharacter->y1;
+ if (ABS(temp) < 2)
+ return 0;
+ }
+
+ int x = (int16)(_currentCharacter->x1 & 0xFFFC);
+ int y = (int16)(_currentCharacter->y1 & 0xFFFE);
+ xpos = (int16)(xpos & 0xFFFC);
+ ypos = (int16)(ypos & 0xFFFE);
+
+ int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150);
+ _pathfinderFlag = 0;
+
+ if (ret >= _lastFindWayRet)
+ _lastFindWayRet = ret;
+
+ if (ret == 0x7D00 || ret == 0)
+ return 0;
+
+ return processSceneChange(_movFacingTable, unk1, frameReset);
+}
+
+int KyraEngine_LoK::processSceneChange(int *table, int unk1, int frameReset) {
+ if (queryGameFlag(0xEF))
+ unk1 = 0;
+
+ int *tableStart = table;
+ _sceneChangeState = 0;
+ _loopFlag2 = 0;
+ bool running = true;
+ int returnValue = 0;
+ uint32 nextFrame = 0;
+
+ while (running) {
+ bool forceContinue = false;
+ switch (*table) {
+ case 0: case 1: case 2:
+ case 3: case 4: case 5:
+ case 6: case 7:
+ _currentCharacter->facing = getOppositeFacingDirection(*table);
+ break;
+
+ case 8:
+ forceContinue = true;
+ running = false;
+ break;
+
+ default:
+ ++table;
+ forceContinue = true;
+ }
+
+ returnValue = changeScene(_currentCharacter->facing);
+ if (returnValue)
+ running = false;
+
+ if (unk1) {
+ if (skipFlag()) {
+ resetSkipFlag(false);
+ running = false;
+ _sceneChangeState = 1;
+ }
+ }
+
+ if (forceContinue || !running)
+ continue;
+
+ int temp = 0;
+ if (table == tableStart || table[1] == 8)
+ temp = setCharacterPosition(0, 0);
+ else
+ temp = setCharacterPosition(0, table);
+
+ if (temp)
+ ++table;
+
+ nextFrame = _timer->getDelay(5) * _tickLength + _system->getMillis();
+ while (_system->getMillis() < nextFrame) {
+ _timer->update();
+
+ if (_currentCharacter->sceneId == 210) {
+ updateKyragemFading();
+ if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) {
+ *table = 8;
+ running = false;
+ break;
+ }
+ }
+
+ if ((nextFrame - _system->getMillis()) >= 10)
+ delay(10, true);
+ }
+ }
+
+ if (frameReset && !(_brandonStatusBit & 2))
+ _currentCharacter->currentAnimFrame = 7;
+
+ _animator->animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ return returnValue;
+}
+
+int KyraEngine_LoK::changeScene(int facing) {
+ if (queryGameFlag(0xEF)) {
+ if (_currentCharacter->sceneId == 5)
+ return 0;
+ }
+
+ int xpos = _charAddXPosTable[facing] + _currentCharacter->x1;
+ int ypos = _charAddYPosTable[facing] + _currentCharacter->y1;
+
+ if (xpos >= 12 && xpos <= 308) {
+ if (!lineIsPassable(xpos, ypos))
+ return false;
+ }
+
+ if (_exitListPtr) {
+ int16 *ptr = _exitListPtr;
+ // this loop should be only entered one time, seems to be some hack in the original
+ while (true) {
+ if (*ptr == -1)
+ break;
+
+ if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) {
+ ptr += 10;
+ break;
+ }
+
+ _brandonPosX = ptr[6];
+ _brandonPosY = ptr[7];
+ uint16 sceneId = ptr[5];
+ facing = ptr[4];
+ int unk1 = ptr[8];
+ int unk2 = ptr[9];
+
+ if (sceneId == 0xFFFF) {
+ switch (facing) {
+ case 0:
+ sceneId = _roomTable[_currentCharacter->sceneId].northExit;
+ break;
+
+ case 2:
+ sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
+ break;
+
+ case 4:
+ sceneId = _roomTable[_currentCharacter->sceneId].southExit;
+ break;
+
+ case 6:
+ sceneId = _roomTable[_currentCharacter->sceneId].westExit;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ _currentCharacter->facing = facing;
+ _animator->animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ enterNewScene(sceneId, facing, unk1, unk2, 0);
+ resetGameFlag(0xEE);
+ return 1;
+ }
+ }
+
+ int returnValue = 0;
+ facing = 0;
+
+ if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) {
+ facing = 0;
+ returnValue = 1;
+ }
+
+ if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) {
+ facing = 2;
+ returnValue = 1;
+ }
+
+ if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) {
+ facing = 4;
+ returnValue = 1;
+ }
+
+ if (xpos <= 12 || _currentCharacter->y1 <= 12) {
+ facing = 6;
+ returnValue = 1;
+ }
+
+ if (!returnValue)
+ return 0;
+
+ uint16 sceneId = 0xFFFF;
+ switch (facing) {
+ case 0:
+ sceneId = _roomTable[_currentCharacter->sceneId].northExit;
+ break;
+
+ case 2:
+ sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
+ break;
+
+ case 4:
+ sceneId = _roomTable[_currentCharacter->sceneId].southExit;
+ break;
+
+ default:
+ sceneId = _roomTable[_currentCharacter->sceneId].westExit;
+ }
+
+ if (sceneId == 0xFFFF)
+ return 0;
+
+ enterNewScene(sceneId, facing, 1, 1, 0);
+ return returnValue;
+}
+
+void KyraEngine_LoK::setCharactersInDefaultScene() {
+ static const uint32 defaultSceneTable[][4] = {
+ { 0xFFFF, 0x0004, 0x0003, 0xFFFF },
+ { 0xFFFF, 0x0022, 0xFFFF, 0x0000 },
+ { 0xFFFF, 0x001D, 0x0021, 0xFFFF },
+ { 0xFFFF, 0x0000, 0x0000, 0xFFFF }
+ };
+
+ for (int i = 1; i < 5; ++i) {
+ Character *cur = &_characterList[i];
+ //cur->field_20 = 0;
+
+ const uint32 *curTable = defaultSceneTable[i - 1];
+ cur->sceneId = curTable[0];
+
+ if (cur->sceneId == _currentCharacter->sceneId)
+ //++cur->field_20;
+ cur->sceneId = curTable[1/*cur->field_20*/];
+
+ //cur->field_23 = curTable[cur->field_20+1];
+ }
+}
+
+void KyraEngine_LoK::setCharactersPositions(int character) {
+ static const uint16 initXPosTable[] = {
+ 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B,
+ 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042
+ };
+ static const uint8 initYPosTable[] = {
+ 0x00, 0xA2, 0x00, 0x42, 0x00,
+ 0x67, 0x67, 0x60, 0x5A, 0x71,
+ 0x76
+ };
+
+ assert(character < ARRAYSIZE(initXPosTable));
+ Character *edit = &_characterList[character];
+ edit->x1 = edit->x2 = initXPosTable[character];
+ edit->y1 = edit->y2 = initYPosTable[character];
+}
+
+#pragma mark -
+#pragma mark - Pathfinder
+#pragma mark -
+
+int KyraEngine_LoK::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
+ int ret = KyraEngine_v1::findWay(x, y, toX, toY, moveTable, moveTableSize);
+ if (ret == 0x7D00)
+ return 0;
+ return getMoveTableSize(moveTable);
+}
+
+bool KyraEngine_LoK::lineIsPassable(int x, int y) {
+ if (queryGameFlag(0xEF)) {
+ if (_currentCharacter->sceneId == 5)
+ return true;
+ }
+
+ if (_pathfinderFlag & 2) {
+ if (x >= 312)
+ return false;
+ }
+
+ if (_pathfinderFlag & 4) {
+ if (y >= 136)
+ return false;
+ }
+
+ if (_pathfinderFlag & 8) {
+ if (x < 8)
+ return false;
+ }
+
+ if (_pathfinderFlag2) {
+ if (x <= 8 || x >= 312)
+ return true;
+ if (y < (_northExitHeight & 0xFF) || y > 135)
+ return true;
+ }
+
+ if (y > 137)
+ return false;
+
+ if (y < 0)
+ y = 0;
+
+ int ypos = 8;
+ if (_scaleMode) {
+ ypos = (_scaleTable[y] >> 5) + 1;
+ if (8 < ypos)
+ ypos = 8;
+ }
+
+ x -= (ypos >> 1);
+
+ int xpos = x;
+ int xtemp = xpos + ypos - 1;
+ if (x < 0)
+ xpos = 0;
+
+ if (xtemp > 319)
+ xtemp = 319;
+
+ for (; xpos < xtemp; ++xpos) {
+ if (!_screen->getShapeFlag1(xpos, y))
+ return false;
+ }
+ return true;
+}
+
+#pragma mark -
+
+void KyraEngine_LoK::setupZanthiaPalette(int pal) {
+ uint8 r, g, b;
+
+ switch (pal - 17) {
+ case 0:
+ // 0x88F
+ r = 33;
+ g = 33;
+ b = 63;
+ break;
+
+ case 1:
+ // 0x00F
+ r = 0;
+ g = 0;
+ b = 63;
+ break;
+
+ case 2:
+ // 0xF88
+ r = 63;
+ g = 33;
+ b = 33;
+ break;
+
+ case 3:
+ // 0xF00
+ r = 63;
+ g = 0;
+ b = 0;
+ break;
+
+ case 4:
+ // 0xFF9
+ r = 63;
+ g = 63;
+ b = 37;
+ break;
+
+ case 5:
+ // 0xFF1
+ r = 63;
+ g = 63;
+ b = 4;
+ break;
+
+ default:
+ // 0xFFF
+ r = 63;
+ g = 63;
+ b = 63;
+ }
+
+ _screen->getPalette(4)[12 * 3 + 0] = r;
+ _screen->getPalette(4)[12 * 3 + 1] = g;
+ _screen->getPalette(4)[12 * 3 + 2] = b;
+}
+
+#pragma mark -
+
+void KyraEngine_LoK::setupSceneResource(int sceneId) {
+ if (!_flags.isTalkie)
+ return;
+
+ if (_currentRoom != 0xFFFF) {
+ assert(_currentRoom < _roomTableSize);
+ int tableId = _roomTable[_currentRoom].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+
+ // unload our old room
+ char file[64];
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".VRM");
+ _res->unloadPakFile(file);
+
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".PAK");
+ _res->unloadPakFile(file);
+
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".APK");
+ _res->unloadPakFile(file);
+ }
+
+ assert(sceneId < _roomTableSize);
+ int tableId = _roomTable[sceneId].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+
+ // load our new room
+ char file[64];
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".VRM");
+ if (_res->exists(file))
+ _res->loadPakFile(file);
+
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".PAK");
+ if (_res->exists(file))
+ _res->loadPakFile(file);
+
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".APK");
+ if (_res->exists(file))
+ _res->loadPakFile(file);
+}
+
+} // End of namespace Kyra