From 510eba82270096063716f4611f4204eb65e72eee Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 9 Nov 2005 22:26:12 +0000 Subject: - fixed setCharactersPosition - fixed loadCharacterShapes - fixed anim shape drawing - corrected some tables - added debug drawing for the pathfinder (still a bit buggy) - gets a small script scene to work with some graphics glitches - corrected some drawShape drawing functions - started to implement cmd_walkPlayerToPoint and the needed functions svn-id: r19539 --- kyra/kyra.cpp | 403 ++++++++++++++++++++++++++++++++++++++++++++--------- kyra/kyra.h | 26 ++-- kyra/screen.cpp | 31 +++-- kyra/script_v1.cpp | 13 +- kyra/sprites.cpp | 16 +-- kyra/staticres.cpp | 2 +- 6 files changed, 392 insertions(+), 99 deletions(-) diff --git a/kyra/kyra.cpp b/kyra/kyra.cpp index f996c57343..9da78b8495 100644 --- a/kyra/kyra.cpp +++ b/kyra/kyra.cpp @@ -67,6 +67,8 @@ struct KyraGameSettings { }; static const KyraGameSettings kyra_games[] = { + { "kyra1", "Legend of Kyrandia (Floppy, English)", GI_KYRA1, GF_ENGLISH | GF_FLOPPY, // english floppy 1.0 from Malice + "3c244298395520bb62b5edfe41688879", "GEMCUT.EMC" }, { "kyra1", "Legend of Kyrandia (Floppy, English)", GI_KYRA1, GF_ENGLISH | GF_FLOPPY, "796e44863dd22fa635b042df1bf16673", "GEMCUT.EMC" }, { "kyra1", "Legend of Kyrandia (Floppy, French)", GI_KYRA1, GF_FRENCH | GF_FLOPPY, @@ -325,6 +327,8 @@ int KyraEngine::init(GameDetector &detector) { _exitListPtr = 0; _pathfinderFlag = 0; + _sceneChangeState = _loopFlag2 = 0; + _movFacingTable = new int[150]; assert(_movFacingTable); _movFacingTable[0] = 8; @@ -442,6 +446,9 @@ void KyraEngine::startup() { initAnimStateList(); setCharactersInDefaultScene(); + _gameSpeed = 50; + memset(_flagsTable, 0, sizeof(_flagsTable)); + if (!_scriptInterpreter->loadScript("_STARTUP.EMC", _npcScriptData, _opcodeTable, _opcodeTableSize, 0)) { error("Could not load \"_STARTUP.EMC\" script"); } @@ -459,10 +466,8 @@ void KyraEngine::startup() { } snd_playTheme(1); + snd_setSoundEffectFile(1); enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1); - - _gameSpeed = 50; - memset(_flagsTable, 0, sizeof(_flagsTable)); } void KyraEngine::delay(uint32 amount) { @@ -1031,7 +1036,7 @@ void KyraEngine::loadCharacterShapes() { loadBitmap(_characterImageTable[shape->imageIndex], 3, 3, 0); curImage = shape->imageIndex; } - _shapes[i+7+4] = _screen->encodeShape(shape->x, shape->y, shape->w, shape->h, 1); + _shapes[i+7+4] = _screen->encodeShape(shape->x<<3, shape->y, shape->w<<3, shape->h, 1); } _screen->_curPage = videoPage; } @@ -1327,7 +1332,7 @@ void KyraEngine::enterNewScene(int sceneId, int facing, int unk1, int unk2, int strcpy(datFileNameBuffer, _roomFilenameTable[tableId]); strcat(datFileNameBuffer, ".DAT"); _sprites->loadDAT(datFileNameBuffer); - + _scriptInterpreter->unloadScript(_scriptClickData); loadSceneMSC(); _walkBlockNorth = currentRoom->northExit; @@ -1413,16 +1418,16 @@ void KyraEngine::setCharacterPositionWithUpdate(int character) { } } -int KyraEngine::setCharacterPosition(int character, uint8 *unk1) { - debug(9, "setCharacterPosition(%d)", character); +int KyraEngine::setCharacterPosition(int character, int *facingTable) { + debug(9, "setCharacterPosition(%d, 0x%X)", character, facingTable); if (character == 0) { _currentCharacter->x1 += _charXPosTable[_currentCharacter->facing]; _currentCharacter->y1 += _charYPosTable[_currentCharacter->facing]; - setCharacterPositionHelper(0, unk1); + setCharacterPositionHelper(0, facingTable); return 1; } else { - _characterList[character].x1 += _charXPosTable[_currentCharacter->facing]; - _characterList[character].y1 += _charYPosTable[_currentCharacter->facing]; + _characterList[character].x1 += _charXPosTable[_characterList[character].facing]; + _characterList[character].y1 += _charYPosTable[_characterList[character].facing]; if (_characterList[character].sceneId == _currentCharacter->sceneId) { setCharacterPositionHelper(character, 0); } @@ -1430,14 +1435,18 @@ int KyraEngine::setCharacterPosition(int character, uint8 *unk1) { return 0; } -void KyraEngine::setCharacterPositionHelper(int character, uint8 *unk1) { - debug(9, "setCharacterPositionHelper(%d, 0x%X)", character, unk1); +void KyraEngine::setCharacterPositionHelper(int character, int *facingTable) { + debug(9, "setCharacterPositionHelper(%d, 0x%X)", character, facingTable); Character *ch = &_characterList[character]; ++ch->currentAnimFrame; int facing = ch->facing; - if (unk1) { - warning("unk1 handling is NOT implemented"); - // XXX + if (facingTable) { + if (*facingTable != *(facingTable - 1)) { + if (*(facingTable - 1) == *(facingTable + 1)) { + facing = getOppositeFacingDirection(*(facingTable - 1)); + *facingTable = *(facingTable - 1); + } + } } static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -1460,7 +1469,7 @@ void KyraEngine::setCharacterPositionHelper(int character, uint8 *unk1) { ++facingIsFour[character]; } } else { - if (facingIsZero[character] < 2) { + if (facingIsZero[character] > 2) { facing = 0; } resetTables = true; @@ -1473,7 +1482,7 @@ void KyraEngine::setCharacterPositionHelper(int character, uint8 *unk1) { } } - static uint16 maxAnimationFrame[] = { + static const uint16 maxAnimationFrame[] = { 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000, 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000, 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000, @@ -1484,27 +1493,27 @@ void KyraEngine::setCharacterPositionHelper(int character, uint8 *unk1) { }; if (facing == 0) { - if (maxAnimationFrame[36+character] > ch->currentAnimFrame) { + if (maxAnimationFrame[36+character] < ch->currentAnimFrame) { ch->currentAnimFrame = maxAnimationFrame[36+character]; } - if (maxAnimationFrame[30+character] > ch->currentAnimFrame) { + if (maxAnimationFrame[30+character] < ch->currentAnimFrame) { ch->currentAnimFrame = maxAnimationFrame[36+character]; } } else if (facing == 4) { - if (maxAnimationFrame[18+character] > ch->currentAnimFrame) { + if (maxAnimationFrame[18+character] < ch->currentAnimFrame) { ch->currentAnimFrame = maxAnimationFrame[18+character]; } - if (maxAnimationFrame[12+character] > ch->currentAnimFrame) { + if (maxAnimationFrame[12+character] < ch->currentAnimFrame) { ch->currentAnimFrame = maxAnimationFrame[18+character]; } } else { - if (maxAnimationFrame[18+character] > ch->currentAnimFrame) { + 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) { + if (maxAnimationFrame[character] < ch->currentAnimFrame) { ch->currentAnimFrame = maxAnimationFrame[6+character]+2; } } @@ -1640,23 +1649,23 @@ void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) { break; case 1: case 2: case 8: - xpos = _sceneExits.SouthXPos; - ypos = _sceneExits.SouthYPos; + xpos = _sceneExits.southXPos; + ypos = _sceneExits.southYPos; break; case 3: - xpos = _sceneExits.WestXPos; - ypos = _sceneExits.WestYPos; + xpos = _sceneExits.westXPos; + ypos = _sceneExits.westYPos; break; case 4: case 5: case 6: - xpos = _sceneExits.NorthXPos; - ypos = _sceneExits.NorthYPos; + xpos = _sceneExits.northXPos; + ypos = _sceneExits.northYPos; break; case 7: - xpos = _sceneExits.EastXPos; - ypos = _sceneExits.EastYPos; + xpos = _sceneExits.eastXPos; + ypos = _sceneExits.eastYPos; break; default: @@ -1870,8 +1879,8 @@ void KyraEngine::initSceneObjectList(int brandonAlive) { curAnimState->x1 += (_brandonScaleX * xOffset) >> 8; curAnimState->y1 += (_brandonScaleY * yOffset) >> 8; } else { - curAnimState->x1 += _currentCharacter->x1 + xOffset; - curAnimState->y1 += _currentCharacter->y1 + yOffset; + curAnimState->x1 = _currentCharacter->x1 + xOffset; + curAnimState->y1 = _currentCharacter->y1 + yOffset; } curAnimState->x2 = curAnimState->x1; curAnimState->y2 = curAnimState->y1; @@ -1907,8 +1916,8 @@ void KyraEngine::initSceneObjectList(int brandonAlive) { curAnimState->x1 += (_brandonScaleX * xOffset) >> 8; curAnimState->y1 += (_brandonScaleY * yOffset) >> 8; } else { - curAnimState->x1 += ch->x1 + xOffset; - curAnimState->y1 += ch->y1 + yOffset; + curAnimState->x1 = ch->x1 + xOffset; + curAnimState->y1 = ch->y1 + yOffset; } curAnimState->x2 = curAnimState->x1; curAnimState->y2 = curAnimState->y1; @@ -2021,6 +2030,7 @@ byte KyraEngine::findFreeItemInScene(int scene) { } byte KyraEngine::findItemAtPos(int x, int y) { + debug(9, "findItemAtPos(%d, %d)", x, y); assert(_currentCharacter->sceneId < _roomTableSize); uint8 *itemsTable = _roomTable[_currentCharacter->sceneId].itemsTable; uint16 *xposOffset = _roomTable[_currentCharacter->sceneId].itemsXPos; @@ -2154,7 +2164,7 @@ void KyraEngine::preserveAnyChangedBackgrounds() { void KyraEngine::preserveOrRestoreBackground(AnimObject *obj, bool restore) { debug(9, "preserveOrRestoreBackground(0x%X, restore)", obj, restore); - int x, y, width = obj->width, height = obj->height; + int x = 0, y = 0, width = obj->width << 3, height = obj->height; if (restore) { x = obj->x2; @@ -2181,9 +2191,9 @@ void KyraEngine::preserveOrRestoreBackground(AnimObject *obj, bool restore) { } if (restore) { - _screen->copyCurPageBlock(x >> 3, y, width, height, obj->background); - } else { _screen->copyBlockToPage(_screen->_curPage, x, y, width, height, obj->background); + } else { + _screen->copyRegionToBuffer(_screen->_curPage, x, y, width, height, obj->background); } } @@ -2270,12 +2280,12 @@ void KyraEngine::copyChangedObjectsForward(int refreshFlag) { if (curObject->active) { if (curObject->refreshFlag || refreshFlag) { int xpos = 0, ypos = 0, width = 0, height = 0; - xpos = curObject->x1; - ypos = curObject->y1; - width = curObject->width; - height = curObject->height; + xpos = curObject->x1 - (curObject->width2+1); + ypos = curObject->y1 - curObject->height2; + width = curObject->width + curObject->width2*2; + height = curObject->height + curObject->height2*2; - _screen->copyRegion(xpos, ypos, xpos, ypos, width, height, 2, 0, Screen::CR_CLIPPED); + _screen->copyRegion(xpos, ypos, xpos, ypos, width<<3, height, 2, 0, Screen::CR_CLIPPED); curObject->refreshFlag = 0; } } @@ -2302,9 +2312,9 @@ void KyraEngine::animRefreshNPC(int character) { animObj->bkgdChangeFlag = 1; int facing = ch->facing; if (facing >= 1 && facing <= 3) { - ch->inventoryItems[7] |= 1; + animObj->flags |= 1; } else if (facing >= 5 && facing <= 7) { - ch->inventoryItems[7] &= 0xFE; + animObj->flags &= 0xFFFFFFFE; } animObj->drawY = ch->y1; @@ -2324,8 +2334,8 @@ void KyraEngine::animRefreshNPC(int character) { } } - int xOffset = _defaultShapeTable[ch->currentAnimFrame].xOffset; - int yOffset = _defaultShapeTable[ch->currentAnimFrame].yOffset; + int xOffset = _defaultShapeTable[ch->currentAnimFrame-7].xOffset; + int yOffset = _defaultShapeTable[ch->currentAnimFrame-7].yOffset; if (_scaleMode) { animObj->x1 = ch->x1; @@ -2333,12 +2343,12 @@ void KyraEngine::animRefreshNPC(int character) { _brandonScaleX = _scaleTable[ch->y1]; _brandonScaleY = _scaleTable[ch->y1]; - + animObj->x1 += (_brandonScaleX * xOffset) >> 8; animObj->y1 += (_brandonScaleY * yOffset) >> 8; } else { - animObj->x1 += ch->x1 + xOffset; - animObj->y1 += ch->y1 + yOffset; + animObj->x1 = ch->x1 + xOffset; + animObj->y1 = ch->y1 + yOffset; } animObj->width2 = 4; animObj->height2 = 3; @@ -2422,12 +2432,14 @@ AnimObject *KyraEngine::objectQueue(AnimObject *queue, AnimObject *add) { #pragma mark - int16 KyraEngine::fetchAnimWidth(const uint8 *shape, int16 mult) { + debug(9, "fetchAnimWidth(0x%X, %d)", shape, mult); if (_features & GF_TALKIE) shape += 2; return ((int16)READ_LE_UINT16((shape+3))) * mult; } int8 KyraEngine::fetchAnimHeight(const uint8 *shape, int8 mult) { + debug(9, "fetchAnimHeight(0x%X, %d)", shape, mult); if (_features & GF_TALKIE) shape += 2; return ((int8)*(shape+2)) * mult; @@ -2473,6 +2485,12 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move delete [] pathTable2; return 0x7D00; } + // debug drawing + //if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) { + // _screen->setPagePixel(0, curX, curY, 11); + // _screen->updateScreen(); + // waitTicks(5); + //} moveTable[lastUsedEntry++] = newFacing; x = curX; y = curY; @@ -2483,6 +2501,12 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move while (true) { newFacing = getFacingFromPointToPoint(curX, curY, toX, toY); changePosTowardsFacing(curX, curY, newFacing); + // debug drawing + //if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) { + // _screen->setPagePixel(0, curX, curY, 8); + // _screen->updateScreen(); + // waitTicks(5); + //} if (!lineIsPassable(curX, curY)) { if (curX != toX || curY != toY) @@ -2497,7 +2521,7 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move } } - assert(pathTable1 && pathTable1); + assert(pathTable1 && pathTable2); temp = findSubPath(x, y, curX, curY, pathTable1, 1, 0x7D0); tempValue = findSubPath(x, y, curX, curY, pathTable2, 0, 0x7D0); if (curX == toX && curY == toY) { @@ -2508,8 +2532,9 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move } } - if (temp != 0x7D00 || tempValue != 0x7D00) + if (temp != 0x7D00 || tempValue != 0x7D00) { break; + } } if (temp < tempValue) { @@ -2524,12 +2549,10 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move if (lastUsedEntry + tempValue > moveTableSize) { delete [] pathTable1; delete [] pathTable2; - debug("[2] oh no"); return 0x7D00; } - memcpy(&moveTable[lastUsedEntry], pathTable2, temp); - debug("[2] temp: %d", temp); - lastUsedEntry += temp; + memcpy(&moveTable[lastUsedEntry], pathTable2, tempValue); + lastUsedEntry += tempValue; } x = curX; y = curY; @@ -2545,17 +2568,19 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) { debug(9, "findSubPath(%d, %d, %d, %d, 0x%X, %d, %d)", x, y, toX, toY, moveTable, start, end); - static uint16 unkTable[] = { 8, 5 }; + // only used for debug specific code + //static uint16 unkTable[] = { 8, 5 }; static const int8 facingTable1[] = { 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0 }; static const int8 facingTable2[] = { -1, 0, -1, 2, -1, 4, -1, 6, -1, 2, -1, 4, -1, 6, -1, 0 }; static const int8 facingTable3[] = { 2, 4, 4, 6, 6, 0, 0, 2, 6, 6, 0, 0, 2, 2, 4, 4 }; static const int8 addPosTable1[] = { -1, 0, -1, 4, -1, 0, -1, -4, -1, -4, -1, 0, -1, 4, -1, 0 }; static const int8 addPosTable2[] = { -1, 2, -1, 0, -1, -2, -1, 0, -1, 0, -1, 2, -1, 0, -1, -2 }; - ++unkTable[start]; - while (_screen->getPalette(0)[unkTable[start]] != 0x0F) { - ++unkTable[start]; - } + // debug specific + //++unkTable[start]; + //while (_screen->getPalette(0)[unkTable[start]] != 0x0F) { + // ++unkTable[start]; + //} int xpos1 = x, xpos2 = x; int ypos1 = y, ypos2 = y; @@ -2576,6 +2601,12 @@ int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int } break; } + // debug drawing + //if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) { + // _screen->setPagePixel(0, xpos1,ypos1, unkTable[start]); + // _screen->updateScreen(); + // waitTicks(5); + //} if (newFacing & 1) { int temp = xpos1 + addPosTable1[newFacing + start * 8]; if (toX == temp) { @@ -2675,7 +2706,7 @@ bool KyraEngine::lineIsPassable(int x, int y) { if (_pathfinderFlag2) { if (x <= 8 || x >= 312) return true; - if (y < _northExitHeight || y >= 135) + if (y < _northExitHeight || y > 135) return true; } @@ -2793,4 +2824,252 @@ int KyraEngine::getMoveTableSize(int *moveTable) { return retValue; } + +#pragma mark - +#pragma mark - Scene handling +#pragma mark - + +int KyraEngine::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) { + debug(9, "handleSceneChange(%d, %d, %d, %d)", xpos, ypos, unk1, 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+2) { + if (_roomTable[sceneId].northExit != 0xFFFF) { + xpos = _northExitHeight; + ypos = _sceneExits.northXPos; + _pathfinderFlag = 14; + } + } else if (ypos >= 136) { + if (_roomTable[sceneId].southExit != 0xFFFF) { + xpos = 136; + ypos = _sceneExits.southXPos; + _pathfinderFlag = 11; + } + } + + int temp = xpos - _currentCharacter->x1; + if (ABS(temp) < 4) { + temp = ypos - _currentCharacter->y1; + if (ABS(temp) < 2) { + return 0; + } + } + + int x = _currentCharacter->x1 & 0xFFFC; + int y = _currentCharacter->y1 & 0xFFFE; + xpos &= 0xFFFC; + 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::processSceneChange(int *table, int unk1, int frameReset) { + debug(9, "handleSceneChange(0x%X, %d, %d)", table, unk1, frameReset); + if (queryGameFlag(0xEF)) { + unk1 = 0; + } + int *tableStart = table; + _sceneChangeState = 0; + _loopFlag2 = 0; + bool running = true; + int returnValue = 0; + while (running) { + // XXX + 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; + break; + } + + returnValue = (changeScene(_currentCharacter->facing) != 0); + + if (unk1) { + // XXX + } + + if (forceContinue || !running) { + continue; + } + + int temp = 0; + if (table == tableStart) { + temp = setCharacterPosition(0, 0); + } else { + temp = setCharacterPosition(0, table); + } + if (!temp) + continue; + ++table; + // XXX updateAnimFlags + // XXX updateMousePointer + // XXX updateGameTimers + updateAllObjectShapes(); + // XXX processPalette + if (_currentCharacter->sceneId == 210) { + // XXX updateKyragemFading + // XXX playEnd + // XXX + } + } + + if (frameReset && !(_brandonStatusBit & 2)) { + _currentCharacter->currentAnimFrame = 7; + } + animRefreshNPC(0); + updateAllObjectShapes(); + return returnValue; +} + +int KyraEngine::changeScene(int facing) { + if (queryGameFlag(0xEF)) { + if (_currentCharacter->sceneId == 5) { + return 0; + } + } + + int xpos = _charXPosTable[facing] + _currentCharacter->x1; + int ypos = _charYPosTable[facing] + _currentCharacter->y1; + + if (xpos >= 12 && xpos <= 308) { + if (!lineIsPassable(xpos, ypos)) + return false; + } + + if (_exitListPtr) { + uint16 *ptr = _exitListPtr; + // this loop should be only entered on time, seems to be some hack in the original + while (true) { + if (*ptr == 0xFFFF) + break; + + if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < *(ptr + 1) || _currentCharacter->x1 > *(ptr + 2) || _currentCharacter->y1 > *(ptr + 3)) { + ptr += 10; + continue; + } + _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; + animRefreshNPC(0); + updateAllObjectShapes(); + enterNewScene(sceneId, facing, unk1, unk2, 0); + resetGameFlag(0xEF); + 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; + + int 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; + break; + } + + if (sceneId == 0xFFFF) + return 0; + + enterNewScene(sceneId, facing, 1, 1, 0); + return returnValue; +} } // End of namespace Kyra diff --git a/kyra/kyra.h b/kyra/kyra.h index d0e1c6d4e3..e90aada5de 100644 --- a/kyra/kyra.h +++ b/kyra/kyra.h @@ -121,14 +121,14 @@ struct SeqLoop { }; struct SceneExits { - int16 NorthXPos; - int8 NorthYPos; - int16 EastXPos; - int8 EastYPos; - int16 SouthXPos; - int8 SouthYPos; - int16 WestXPos; - int8 WestYPos; + uint16 northXPos; + uint8 northYPos; + uint16 eastXPos; + uint8 eastYPos; + uint16 southXPos; + uint8 southYPos; + uint16 westXPos; + uint8 westYPos; }; struct WSAMovieV1; @@ -387,8 +387,8 @@ protected: void enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive); void moveCharacterToPos(int character, int facing, int xpos, int ypos); void setCharacterPositionWithUpdate(int character); - int setCharacterPosition(int character, uint8 *unk1); - void setCharacterPositionHelper(int character, uint8 *unk1); + int setCharacterPosition(int character, int *facingTable); + void setCharacterPositionHelper(int character, int *facingTable); int getOppositeFacingDirection(int dir); void loadSceneMSC(); void blockInRegion(int x, int y, int width, int height); @@ -417,6 +417,9 @@ protected: void changePosTowardsFacing(int &x, int &y, int facing); bool lineIsPassable(int x, int y); int getMoveTableSize(int *moveTable); + int handleSceneChange(int xpos, int ypos, int unk1, int frameReset); + int processSceneChange(int *table, int unk1, int frameReset); + int changeScene(int facing); AnimObject *objectRemoveQueue(AnimObject *queue, AnimObject *rem); AnimObject *objectAddHead(AnimObject *queue, AnimObject *head); @@ -517,6 +520,9 @@ protected: uint16 _currentRoom; uint8 *_maskBuffer; + int _sceneChangeState; + int _loopFlag2; + int _pathfinderFlag; int _pathfinderFlag2; int _lastFindWayRet; diff --git a/kyra/screen.cpp b/kyra/screen.cpp index 9a7a694bb3..342763dd4b 100644 --- a/kyra/screen.cpp +++ b/kyra/screen.cpp @@ -323,8 +323,8 @@ void Screen::copyCurPageBlock(int x, int y, int h, int w, uint8 *dst) { } const uint8 *src = getPagePtr(_curPage) + y * SCREEN_W + x * 8; while (h--) { - memcpy(dst, src, w); - dst += SCREEN_W; + memcpy(dst, src, w*8); + dst += w*8; src += SCREEN_H; } } @@ -569,7 +569,7 @@ void Screen::setScreenDim(int dim) { } void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) { - debug(9, "Screen::drawShape(%d, %d, %d, %d, %d, ...)", pageNum, x, y, sd, flags); + debug(9, "Screen::drawShape(%d, 0x%X, %d, %d, %d, 0x%.04X, ...)", pageNum, shapeData, x, y, sd, flags); assert(shapeData); va_list args; va_start(args, flags); @@ -744,6 +744,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W + x; + uint8 *dstStart = getPagePtr(pageNum) + y * SCREEN_W + x; int scaleYTable[SCREEN_H]; assert(y1 >= 0 && y2 < SCREEN_H); @@ -833,7 +834,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } break; case 8: { - int offset = dst - shapeBuffer; + int offset = dst - dstStart; uint8 pixel = *(_shapePages[0] + offset); pixel &= 0x7F; pixel &= 0x87; @@ -843,7 +844,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } break; case 9: { - int offset = dst - shapeBuffer; + int offset = dst - dstStart; uint8 pixel = *(_shapePages[0] + offset); pixel &= 0x7F; pixel &= 0x87; @@ -857,7 +858,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } break; case 10: { - int offset = dst - shapeBuffer; + int offset = dst - dstStart; uint8 pixel = *(_shapePages[0] + offset); pixel &= 0x7F; pixel &= 0x87; @@ -877,7 +878,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int case 15: case 11: { - int offset = dst - shapeBuffer; + int offset = dst - dstStart; uint8 pixel = *(_shapePages[0] + offset); pixel &= 0x7F; pixel &= 0x87; @@ -892,7 +893,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } break; case 12: { - int offset = dst - shapeBuffer; + int offset = dst - dstStart; uint8 pixel = *(_shapePages[0] + offset); pixel &= 0x7F; pixel &= 0x87; @@ -904,7 +905,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } break; case 13: { - int offset = dst - shapeBuffer; + int offset = dst - dstStart; uint8 pixel = *(_shapePages[0] + offset); pixel &= 0x7F; pixel &= 0x87; @@ -919,7 +920,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } break; case 14: { - int offset = dst - shapeBuffer; + int offset = dst - dstStart; uint8 pixel = *(_shapePages[0] + offset); pixel &= 0x7F; pixel &= 0x87; @@ -1034,7 +1035,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } break; case 24: { - int offset = dst - shapeBuffer; + int offset = dst - dstStart; uint8 pixel = *(_shapePages[0] + offset); pixel &= 0x7F; pixel &= 0x87; @@ -1780,11 +1781,11 @@ byte Screen::getShapeFlag1(int x, int y) { uint8 color = _shapePages[0][y * SCREEN_W + x]; color &= 0x80; color ^= 0x80; - + if (color & 0x80) { - return (color << 1) + 1; - } - return (color << 1); + return 1; + } + return 0; } } // End of namespace Kyra diff --git a/kyra/script_v1.cpp b/kyra/script_v1.cpp index 51615a4c43..caaecfaf51 100644 --- a/kyra/script_v1.cpp +++ b/kyra/script_v1.cpp @@ -314,7 +314,7 @@ int KyraEngine::cmd_pauseTicks(ScriptState *script) { int KyraEngine::cmd_drawSceneAnimShape(ScriptState *script) { debug(9, "cmd_drawSceneAnimShape(0x%X)", script); - _screen->drawShape( stackPos(4), _sprites->getSceneShape(stackPos(0)), stackPos(1), stackPos(2), 0, stackPos(3) ); + _screen->drawShape(stackPos(4), _sprites->getSceneShape(stackPos(0)), stackPos(1), stackPos(2), 0, stackPos(3)); return 0; } @@ -362,7 +362,14 @@ int KyraEngine::cmd_blockOutWalkableRegion(ScriptState *script) { } int KyraEngine::cmd_walkPlayerToPoint(ScriptState *script) { - warning("STUB: cmd_walkPlayerToPoint"); + debug(9, "cmd_walkPlayerToPoint(0x%X)", script); + // if !stackPos(2) + // XXX + int reinitScript = handleSceneChange(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + // XXX + if (reinitScript) { + _scriptInterpreter->initScript(script, script->dataPtr); + } return 0; } @@ -842,7 +849,7 @@ int KyraEngine::cmd_setCharactersLocation(ScriptState *script) { int KyraEngine::cmd_walkCharacterToPoint(ScriptState *script) { debug(9, "cmd_walkCharacterToPoint(0x%X)", script); - int character = stackPos(0) - 1; + int character = stackPos(0); int toX = stackPos(1); int toY = stackPos(2); _pathfinderFlag2 = 1; diff --git a/kyra/sprites.cpp b/kyra/sprites.cpp index 62fb5ff26f..8f95789459 100644 --- a/kyra/sprites.cpp +++ b/kyra/sprites.cpp @@ -448,14 +448,14 @@ void Sprites::loadDAT(const char *filename) { //TODO: Read in character entry coords here SceneExits &exits = _engine->sceneExits(); - exits.NorthXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; - exits.NorthYPos = *data++ & 0xFFFE; - exits.EastXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; - exits.EastYPos = *data++ & 0xFFFE; - exits.SouthXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; - exits.SouthYPos = *data++ & 0xFFFE; - exits.WestXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; - exits.WestYPos = *data++ & 0xFFFE; + exits.northXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; + exits.northYPos = *data++ & 0xFFFE; + exits.eastXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; + exits.eastYPos = *data++ & 0xFFFE; + exits.southXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; + exits.southYPos = *data++ & 0xFFFE; + exits.westXPos = READ_LE_UINT16(data) & 0xFFFC; data += 2; + exits.westYPos = *data++ & 0xFFFE; } void Sprites::freeSceneShapes() { diff --git a/kyra/staticres.cpp b/kyra/staticres.cpp index 4d70f9ae5b..bbb85c7c98 100644 --- a/kyra/staticres.cpp +++ b/kyra/staticres.cpp @@ -582,7 +582,7 @@ const int8 KyraEngine::_addXPosTable[] = { }; const int8 KyraEngine::_charYPosTable[] = { - -2, -2, 0, 3, 2, 2, 0, -2 + -2, -2, 0, 2, 2, 2, 0, -2 }; const int8 KyraEngine::_addYPosTable[] = { -- cgit v1.2.3