From 2db899d1c70ddb703b39555ca59d6402fb3a96ae Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 20 Apr 2008 02:11:10 +0000 Subject: - fixed various glitches - implemented some input code for kyra3 svn-id: r31588 --- engines/kyra/animator_v3.cpp | 14 ++-- engines/kyra/kyra_v3.cpp | 149 +++++++++++++++++++++++++++++++++++++-- engines/kyra/kyra_v3.h | 15 +++- engines/kyra/scene_v3.cpp | 161 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 321 insertions(+), 18 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/animator_v3.cpp b/engines/kyra/animator_v3.cpp index 6ba5d29003..e28d6ab8ec 100644 --- a/engines/kyra/animator_v3.cpp +++ b/engines/kyra/animator_v3.cpp @@ -224,7 +224,7 @@ void KyraEngine_v3::drawCharacterAnimObject(AnimObj *obj, int x, int y, int laye if (obj->shapeIndex == 0xFFFF || _mainCharacter.animFrame == 87) return; - _screen->drawShape(2, getShapePtr(421), _mainCharacter.x3, _mainCharacter.y3, 2, obj->flags | 304, _paletteOverlay, 3, layer, _charScale, _charScale); + _screen->drawShape(2, getShapePtr(421), _mainCharacter.x3, _mainCharacter.y3, 2, obj->flags | 0x304, _paletteOverlay, 3, layer, _charScale, _charScale); uint8 *shape = getShapePtr(_mainCharacter.animFrame); if (shape) _screen->drawShape(2, shape, x, y, 2, obj->flags | 4, layer, _charScale, _charScale); @@ -307,11 +307,13 @@ void KyraEngine_v3::updateCharacterAnim(int charId) { obj->shapeIndex = obj->shapeIndex2 = _mainCharacter.animFrame; int shapeOffsetX = 0, shapeOffsetY = 0; - //XXX if (_mainCharacter.animFrame >= 50 && _mainCharacter.animFrame <= 87) { + if (_mainCharacter.animFrame >= 50 && _mainCharacter.animFrame <= 87) { shapeOffsetX = _malcolmShapeXOffset; shapeOffsetY = _malcolmShapeYOffset; - //} else { - //} + } else { + shapeOffsetX = _newShapeXAdd; + shapeOffsetY = _newShapeYAdd; + } obj->xPos2 = _mainCharacter.x1; obj->yPos2 = _mainCharacter.y1; @@ -320,10 +322,10 @@ void KyraEngine_v3::updateCharacterAnim(int charId) { obj->yPos2 += (shapeOffsetY * _charScale) >> 8; _mainCharacter.x3 = _mainCharacter.x1 - (_charScale >> 4) - 1; _mainCharacter.y3 = _mainCharacter.y1 - (_charScale >> 6) - 1; - //if (_charSpecialWidth2 == -1) { + if (_charBackUpWidth2 == -1) { obj->width2 = 4; obj->height2 = 10; - //} + } for (int i = 1; i <= 16; ++i) { if (_animObjects[i].enabled && _animObjects[i].unk8) diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index dc59d1966f..b87cd8b9a2 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -108,6 +108,9 @@ KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngi _curStudioSFX = 283; _badConscienceShown = false; _curChapter = 1; + _deathHandler = -1; + _moveFacingTable = 0; + _unkHandleSceneChangeFlag = false; } KyraEngine_v3::~KyraEngine_v3() { @@ -151,6 +154,7 @@ KyraEngine_v3::~KyraEngine_v3() { delete [] _sceneStrings; delete [] _talkObjectList; + delete [] _moveFacingTable; } int KyraEngine_v3::init() { @@ -219,6 +223,7 @@ int KyraEngine_v3::go() { fadeOutMusic(60); _screen->fadeToBlack(); + _musicSoundChannel = -1; startup(); runLoop(); running = false; @@ -499,7 +504,7 @@ void KyraEngine_v3::startup() { //XXX musicUpdate(0); - //XXX + _moveFacingTable = new int[600]; _costPalBuffer = new uint8[864]; //XXX _animObjects = new AnimObj[67]; @@ -840,18 +845,19 @@ void KyraEngine_v3::updateCharPosWithUpdate() { update(); } -void KyraEngine_v3::updateCharPos(uint8 *table, int force) { - debugC(9, kDebugLevelMain, "KyraEngine_v3::updateCharPos(%p, %d)", table, force); - if (!force || (_updateCharPosNextUpdate > _system->getMillis())) - return; +int KyraEngine_v3::updateCharPos(int *table, int force) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::updateCharPos(%p, %d)", (const void*)table, force); + if (_updateCharPosNextUpdate > _system->getMillis() && !force) + return 0; _mainCharacter.x1 += _updateCharPosXTable[_mainCharacter.facing]; _mainCharacter.y1 += _updateCharPosYTable[_mainCharacter.facing]; updateCharAnimFrame(0, table); _updateCharPosNextUpdate = _system->getMillis() + _mainCharacter.walkspeed * _tickLength; + return 1; } -void KyraEngine_v3::updateCharAnimFrame(int character, uint8 *table) { - debugC(9, kDebugLevelMain, "KyraEngine_v3::updateCharPos(%d, %p)", character, table); +void KyraEngine_v3::updateCharAnimFrame(int character, int *table) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::updateCharPos(%d, %p)", character, (const void*)table); ++_mainCharacter.animFrame; int facing = _mainCharacter.facing; @@ -952,6 +958,23 @@ void KyraEngine_v3::updateCharPal(int unk1) { } } +bool KyraEngine_v3::checkCharCollision(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::checkCharCollision(%d, %d)", x, y); + + int scale = getScale(_mainCharacter.x1, _mainCharacter.y1); + int width = (scale * 37) >> 8; + int height = (scale * 76) >> 8; + + int x1 = _mainCharacter.x1 - width/2; + int x2 = _mainCharacter.x2 + width/2; + int y1 = _mainCharacter.y1 - height; + int y2 = _mainCharacter.y2; + + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) + return true; + return false; +} + #pragma mark - void KyraEngine_v3::runLoop() { @@ -979,6 +1002,118 @@ void KyraEngine_v3::runLoop() { void KyraEngine_v3::handleInput(int x, int y) { debugC(9, kDebugLevelMain, "KyraEngine_v3::handleInput(%d, %d)", x, y); + if (_inventoryState) + return; + //setNextIdleAnimTimer(); + + if (_unk5) { + _unk5 = 0; + return; + } + + if (!_screen->isMouseVisible()) + return; + + if (_unk3 == -3) { + playSoundEffect(0x0D, 0x80); + return; + } + + //setNextIdleAnimTimer(); + + int skip = 0; + + if (checkCharCollision(x, y) && _unk3 >= -1 && runSceneScript2()) { + return; + } else if (_itemInHand == 27) { + return; + } else if (checkItemCollision(x, y) == -1) { + resetGameFlag(1); + skip = runSceneScript1(x, y); + + if (queryGameFlag(1)) { + resetGameFlag(1); + return; + } else if (_unk5) { + _unk5 = 0; + return; + } + } + + if (_deathHandler >= 0) + skip = 1; + + if (skip) + return; + + if (checkCharCollision(x, y)) { + if (runSceneScript2()) + return; + } else if (_itemInHand >= 0 && _unk3 >= 0) { + //XXX + return; + } else if (_unk3 != -3) { + if (y > 187 && _unk3 > -4) + return; + if (_unk5) { + _unk5 = 0; + return; + } + } + + inputSceneChange(x, y, 1, 1); +} + +int KyraEngine_v3::inputSceneChange(int x, int y, int unk1, int unk2) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::inputSceneChange(%d, %d, %d, %d)", x, y, unk1, unk2); + uint16 curScene = _mainCharacter.sceneId; + _pathfinderFlag = 15; + + if (!_unkHandleSceneChangeFlag) { + if (_unk3 == -4) { + if (_sceneList[curScene].exit4 != 0xFFFF) { + x = 4; + y = _sceneEnterY4; + _pathfinderFlag = 7; + } + } else if (_unk3 == -6) { + if (_sceneList[curScene].exit2 != 0xFFFF) { + x = 316; + y = _sceneEnterY2; + _pathfinderFlag = 7; + } + } else if (_unk3 == -7) { + if (_sceneList[curScene].exit1 != 0xFFFF) { + x = _sceneEnterX1; + y = _sceneEnterY1 - 2; + _pathfinderFlag = 14; + } + } else if (_unk3 == -5) { + if (_sceneList[curScene].exit3 != 0xFFFF) { + x = _sceneEnterX3; + y = 191; + _pathfinderFlag = 11; + } + } + } + + if (ABS(_mainCharacter.x1 - x) < 4 && ABS(_mainCharacter.y1 - y) < 2) { + _pathfinderFlag = 0; + return 0; + } + + int x1 = _mainCharacter.x1 & (~3); + int y1 = _mainCharacter.y1 & (~1); + x &= ~3; + y &= ~1; + + int size = findWay(x1, y1, x, y, _moveFacingTable, 600); + _pathfinderFlag = 0; + + if (!size || size == 0x7D00) + return 0; + + return trySceneChange(_moveFacingTable, unk1, unk2); } void KyraEngine_v3::update() { diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 7f6e556d7a..1ce2cbe47e 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -71,9 +71,12 @@ private: // run bool _runFlag; + int _deathHandler; void runLoop(); void handleInput(int x, int y); + bool _unkHandleSceneChangeFlag; + int inputSceneChange(int x, int y, int unk1, int unk2); void update(); void updateWithText(); @@ -158,8 +161,10 @@ private: void timerFleaDeath(int arg); // pathfinder + int *_moveFacingTable; int _pathfinderFlag; + int findWay(int x1, int y1, int x2, int y2, int *moveTable, int moveTableSize); bool lineIsPassable(int x, int y); private: @@ -360,6 +365,8 @@ private: void initSceneAnims(int unk1); void initSceneScreen(int unk1); + int runSceneScript1(int x, int y); + int runSceneScript2(); bool _noStartupChat; void runSceneScript4(int unk1); void runSceneScript8(); @@ -379,6 +386,9 @@ private: void updateSpecialSceneScripts(); + int trySceneChange(int *moveTable, int unk1, int unk2); + int checkSceneChange(); + int8 _sceneDatPalette[45]; int8 _sceneDatLayerTable[15]; @@ -411,13 +421,13 @@ private: void moveCharacter(int facing, int x, int y); void updateCharPosWithUpdate(); - void updateCharPos(uint8 *table, int force); + int updateCharPos(int *table, int force); uint32 _updateCharPosNextUpdate; static const int8 _updateCharPosXTable[]; static const int8 _updateCharPosYTable[]; - void updateCharAnimFrame(int character, uint8 *table); + void updateCharAnimFrame(int character, int *table); int8 _characterAnimTable[2]; static const uint8 _characterFrameTable[]; @@ -427,6 +437,7 @@ private: int _lastCharPalLayer; bool _charPalUpdate; + bool checkCharCollision(int x, int y); // talk object struct TalkObject { diff --git a/engines/kyra/scene_v3.cpp b/engines/kyra/scene_v3.cpp index ee4c2ecd6d..e08b3e2bf6 100644 --- a/engines/kyra/scene_v3.cpp +++ b/engines/kyra/scene_v3.cpp @@ -116,7 +116,7 @@ void KyraEngine_v3::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 //XXX resetMaskPage(); for (int i = 0; i < 4; ++i) { - if (i == _musicSoundChannel || i == _fadeOutMusicChannel) + if (i != _musicSoundChannel && i != _fadeOutMusicChannel) _soundDigital->stopSound(i); } _fadeOutMusicChannel = -1; @@ -136,9 +136,11 @@ void KyraEngine_v3::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 _sceneExit3 = _sceneList[sceneId].exit3; _sceneExit4 = _sceneList[sceneId].exit4; - while (_system->getMillis() > waitUntilTimer) + + while (_system->getMillis() < waitUntilTimer) _system->delayMillis(10); + musicUpdate(0); initSceneScript(unk3); musicUpdate(0); @@ -658,6 +660,151 @@ void KyraEngine_v3::updateSpecialSceneScripts() { } } +int KyraEngine_v3::trySceneChange(int *moveTable, int unk1, int updateChar) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::trySceneChange(%p, %d, %d)", (const void*)moveTable, unk1, updateChar); + bool running = true; + bool unkFlag = false; + int changedScene = 0; + const int *moveTableStart = moveTable; + _unk4 = 0; + + while (running && !_quitFlag) { + if (*moveTable >= 0 && *moveTable <= 7) { + _mainCharacter.facing = getOppositeFacingDirection(*moveTable); + unkFlag = true; + } else { + if (*moveTable == 8) { + running = false; + } else { + ++moveTable; + unkFlag = false; + } + } + + if (checkSceneChange()) { + running = false; + changedScene = 1; + } + + if (unk1) { + if (skipFlag()) { + resetSkipFlag(false); + running = false; + _unk4 = 1; + } + } + + if (!unkFlag || !running) + continue; + + int ret = 0; + if (moveTable == moveTableStart || moveTable[1] == 8) + ret = updateCharPos(0, 0); + else + ret = updateCharPos(moveTable, 0); + + if (ret) + ++moveTable; + + update(); + } + + if (updateChar) + _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing]; + + updateCharacterAnim(0); + refreshAnimObjectsIfNeed(); + + return changedScene; +} + +int KyraEngine_v3::checkSceneChange() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::checkSceneChange()"); + const SceneDesc &curScene = _sceneList[_mainCharacter.sceneId]; + int charX = _mainCharacter.x1, charY = _mainCharacter.y1; + int facing = 0; + int process = 0; + + if (_screen->getLayer(charX, charY) == 1 && _unk3 == -7) { + facing = 0; + process = 1; + } else if (charX >= 316 && _unk3 == -6) { + facing = 2; + process = 1; + } else if (charY >= 186 && _unk3 == -5) { + facing = 4; + process = 1; + } else if (charX <= 4 && _unk3 == -4) { + facing = 6; + process = 1; + } + + if (!process) + return 0; + + uint16 newScene = 0xFFFF; + switch (facing) { + case 0: + newScene = curScene.exit1; + break; + + case 2: + newScene = curScene.exit2; + break; + + case 4: + newScene = curScene.exit3; + break; + + case 6: + newScene = curScene.exit4; + break; + + default: + newScene = _mainCharacter.sceneId; + break; + } + + if (newScene == 0xFFFF) + return 0; + + enterNewScene(newScene, facing, 1, 1, 0); + return 1; +} +int KyraEngine_v3::runSceneScript1(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::runSceneScript1(%d, %d)", x, y); + if (y > 187 && _unk3 > -4) + return 0; + if (_deathHandler >= 0) + return 0; + + _scriptInterpreter->initScript(&_sceneScriptState, &_sceneScriptData); + _sceneScriptState.regs[1] = x; + _sceneScriptState.regs[2] = y; + _sceneScriptState.regs[3] = 0; + _sceneScriptState.regs[4] = _itemInHand; + + _scriptInterpreter->startScript(&_sceneScriptState, 1); + while (_scriptInterpreter->validScript(&_sceneScriptState)) + _scriptInterpreter->runScript(&_sceneScriptState); + + return _sceneScriptState.regs[3]; +} + +int KyraEngine_v3::runSceneScript2() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::runSceneScript2()"); + _sceneScriptState.regs[1] = _mouseX; + _sceneScriptState.regs[2] = _mouseY; + _sceneScriptState.regs[3] = 0; + _sceneScriptState.regs[4] = _itemInHand; + + _scriptInterpreter->startScript(&_sceneScriptState, 2); + while (_scriptInterpreter->validScript(&_sceneScriptState)) + _scriptInterpreter->runScript(&_sceneScriptState); + + return _sceneScriptState.regs[3]; +} + void KyraEngine_v3::runSceneScript4(int unk1) { debugC(9, kDebugLevelMain, "KyraEngine_v3::runSceneScript4(%d)", unk1); _sceneScriptState.regs[4] = _itemInHand; @@ -691,6 +838,14 @@ bool KyraEngine_v3::checkSpecialSceneExit(int index, int x, int y) { return false; } +int KyraEngine_v3::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize); + int ret = KyraEngine::findWay(x, y, toX, toY, moveTable, moveTableSize); + if (ret == 0x7D00) + return 0; + return getMoveTableSize(moveTable); +} + bool KyraEngine_v3::lineIsPassable(int x, int y) { debugC(9, kDebugLevelMain, "KyraEngine_v3::lineIsPassable(%d, %d)", x, y); static const uint8 widthTable[] = { 1, 1, 1, 1, 1, 2, 4, 6, 8 }; @@ -716,7 +871,7 @@ bool KyraEngine_v3::lineIsPassable(int x, int y) { x2 = 320; for (; x < x2; ++x) { - if (y < _maskPageMinY || y > _maskPageMinY) + if (y < _maskPageMinY || y > _maskPageMaxY) return false; if (!_screen->getShapeFlag1(x, y)) -- cgit v1.2.3