diff options
42 files changed, 1245 insertions, 505 deletions
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat Binary files differindex eb6314e7d3..d7fbd60c03 100644 --- a/dists/engine-data/kyra.dat +++ b/dists/engine-data/kyra.dat diff --git a/engines/kyra/animator_hof.cpp b/engines/kyra/animator_hof.cpp index 5cc44f1b38..410bbaafa9 100644 --- a/engines/kyra/animator_hof.cpp +++ b/engines/kyra/animator_hof.cpp @@ -298,10 +298,7 @@ void KyraEngine_HoF::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) y = obj->yPos2; } - _sceneAnimMovie[obj->animNum]->setX(x); - _sceneAnimMovie[obj->animNum]->setY(y); - _sceneAnimMovie[obj->animNum]->setDrawPage(2); - _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, int(flags | layer), 0, 0); + _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, int(flags | layer), 0, 0); } } diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp index 5a26f9bcfd..20c84ced11 100644 --- a/engines/kyra/animator_mr.cpp +++ b/engines/kyra/animator_mr.cpp @@ -125,10 +125,7 @@ void KyraEngine_MR::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) { flags |= 0x8000; x = obj->xPos2 - _sceneAnimMovie[obj->animNum]->xAdd(); y = obj->yPos2 - _sceneAnimMovie[obj->animNum]->yAdd(); - _sceneAnimMovie[obj->animNum]->setDrawPage(2); - _sceneAnimMovie[obj->animNum]->setX(x); - _sceneAnimMovie[obj->animNum]->setY(y); - _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, flags | layer); + _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, flags | layer); } } } diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp index 259cf88965..28d5bbd11d 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui.cpp @@ -404,7 +404,7 @@ void MainMenu::updateAnimation() { if (now > _nextUpdate) { _nextUpdate = now + _anim.delay * _vm->tickLength(); - _anim.anim->displayFrame(_animIntern.curFrame, 0); + _anim.anim->displayFrame(_animIntern.curFrame, 0, 0, 0); _animIntern.curFrame += _animIntern.direction ; if (_animIntern.curFrame < _anim.startFrame) { _animIntern.curFrame = _anim.startFrame; diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index 7930dbf2a0..4d2046c35d 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -284,15 +284,11 @@ void KyraEngine_HoF::scrollInventoryWheel() { _screen->showMouse(); snd_playSoundEffect(0x25); - movie.setDrawPage(0); - movie.setX(0); - movie.setY(0); - bool breakFlag = false; for (int i = 0; i <= 6 && !breakFlag; ++i) { if (movie.opened()) { _screen->hideMouse(); - movie.displayFrame(i % frames, 0, 0); + movie.displayFrame(i % frames, 0, 0, 0, 0); _screen->showMouse(); _screen->updateScreen(); } diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index baf39c0954..3f289784f3 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -962,7 +962,7 @@ int GUI_LoK::controlsChangeMusic(Button *button) { debugC(9, kDebugLevelGUI, "GUI_LoK::controlsChangeMusic()"); updateMenuButton(button); - _vm->_configMusic = ++_vm->_configMusic % (_vm->gameFlags().platform == Common::kPlatformFMTowns ? 3 : 2); + _vm->_configMusic = ++_vm->_configMusic % ((_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 3 : 2); setupControls(_menu[5]); return 0; } diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp index ade70c8a85..e8a9526793 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -124,8 +124,15 @@ void LoLEngine::gui_drawScroll() { } } -void LoLEngine::gui_highlightSelectedSpell(int unk) { - +void LoLEngine::gui_highlightSelectedSpell(bool mode) { + int y = 15; + for (int i = 0; i < 7; i++) { + if (_availableSpells[i] == -1) + continue; + uint8 col = (mode && (i == _selectedSpell)) ? 132 : 1; + _screen->fprintString(getLangString(_spellProperties[_availableSpells[i]].spellNameCode), 24, y, col, 0, 0); + y += 9; + } } void LoLEngine::gui_displayCharInventory(int charNum) { @@ -160,8 +167,8 @@ void LoLEngine::gui_displayCharInventory(int charNum) { _screen->fprintString(getLangString(0x4033), 182, 103, 172, 0, 5); static const uint16 skillFlags[] = { 0x0080, 0x0000, 0x1000, 0x0002, 0x100, 0x0001, 0x0000, 0x0000 }; - uint16 tmp[6]; - memset(tmp, -1, 6); + + memset(_invSkillFlags, -1, 6); int x = 0; int32 c = 0; @@ -172,7 +179,7 @@ void LoLEngine::gui_displayCharInventory(int charNum) { uint8 *shp = _gameShapes[skillFlags[(i << 1) + 1]]; _screen->drawShape(_screen->_curPage, shp, 108 + x, 98, 0, 0); x += (shp[3] + 2); - tmp[c] = skillFlags[(i << 1) + 1]; + _invSkillFlags[c] = skillFlags[(i << 1) + 1]; c++; } @@ -354,7 +361,7 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) { if (_availableSpells[_selectedSpell] != -1) { for (int i = 0; i < 4; i++) { if (_spellProperties[_availableSpells[_selectedSpell]].mpRequired[i] <= _characters[charNum].magicPointsCur && - _spellProperties[_availableSpells[_selectedSpell] + 1].unkArr[i] <= _characters[charNum].hitPointsCur) + _spellProperties[_availableSpells[_selectedSpell]].hpRequired[i] <= _characters[charNum].hitPointsCur) spellLevels++; } } @@ -386,7 +393,7 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) { _screen->drawShape(_screen->_curPage, _gameShapes[72 + _characters[charNum].field_41], 44, 17, 0, 0); if (spellLevels == 0) - _screen->drawGridBox(44, 17, 22, 15, 1); + _screen->drawGridBox(44, 17, 22, 16, 1); } uint16 f = _characters[charNum].flags & 0x314C; @@ -726,10 +733,10 @@ void LoLEngine::gui_updateInput() { if (_weaponsDisabled || _availableSpells[1] == -1) return; - gui_highlightSelectedSpell(0); + gui_highlightSelectedSpell(false); if (_availableSpells[++_selectedSpell] == -1) _selectedSpell = 0; - gui_highlightSelectedSpell(1); + gui_highlightSelectedSpell(true); gui_drawAllCharPortraitsWithStats(); break; @@ -887,7 +894,11 @@ void LoLEngine::gui_initCharInventorySpecialButtons(int charNum) { } void LoLEngine::gui_initMagicScrollButtons() { - + for (int i = 0; i < 7; i++) { + if (_availableSpells[i] == -1) + continue; + gui_initButton(71 + i, -1, -1, i); + } } void LoLEngine::gui_initMagicSubmenu(int charNum) { @@ -1110,16 +1121,14 @@ int LoLEngine::clickedMagicSubmenu(Button *button) { } else { _characters[c].flags |= 4; _characters[c].flags &= 0xffef; - /// - // TODO - /// - /*if (processSpellcast(c, _availableSpells[_selectedSpell], spellLevel)) { + + if (castSpell(c, _availableSpells[_selectedSpell], spellLevel)) { setCharacterUpdateEvent(c, 1, 8, 1); - sub_718F(c, 2, spellLevel * spellLevel); - } else {*/ + increaseExperience(c, 2, spellLevel * spellLevel); + } else { _characters[c].flags &= 0xfffb; gui_drawCharPortraitWithStats(c); - //} + } } _unkCharNum = -1; @@ -1345,9 +1354,6 @@ int LoLEngine::clickedInventorySlot(Button *button) { WSAMovie_v2 *wsa = new WSAMovie_v2(this, _screen); wsa->open("truth.wsa", 0, 0); - wsa->setDrawPage(2); - wsa->setX(0); - wsa->setY(0); _screen->hideMouse(); @@ -1359,7 +1365,7 @@ int LoLEngine::clickedInventorySlot(Button *button) { for (int i = 0; i < 25; i++) { _smoothScrollTimer = _system->getMillis() + 7 * _tickLength; _screen->copyRegion(button->x, button->y - 3, 0, 0, 25, 27, 2, 2); - wsa->displayFrame(i, 0x4000); + wsa->displayFrame(i, 2, 0, 0, 0x4000); _screen->copyRegion(0, 0, button->x, button->y - 3, 25, 27, 2, 0); _screen->updateScreen(); delayUntil(_smoothScrollTimer); @@ -1454,14 +1460,45 @@ int LoLEngine::clickedSequenceWindow(Button *button) { } int LoLEngine::clickedScroll(Button *button) { + if (_selectedSpell == button->data2Val2) + return 1; + + gui_highlightSelectedSpell(false); + _selectedSpell = button->data2Val2; + gui_highlightSelectedSpell(true); + gui_drawAllCharPortraitsWithStats(); + return 1; } -int LoLEngine::clickedUnk23(Button *button) { +int LoLEngine::clickedSpellTargetCharacter(Button *button) { + int t = button->data2Val2; + _txt->printMessage(0, "%s.\r", _characters[t].name); + + if ((_spellProperties[_activeSpell.spell].flags & 0xff) == 1) { + _activeSpell.target = t; + castHealOnSingleCharacter(&_activeSpell); + } + + gui_enableDefaultPlayfieldButtons(); return 1; } -int LoLEngine::clickedUnk24(Button *button) { +int LoLEngine::clickedSpellTargetScene(Button *button) { + LoLCharacter *c = &_characters[_activeSpell.charNum]; + _txt->printMessage(0, getLangString(0x4041)); + + c->magicPointsCur += _activeSpell.p->mpRequired[_activeSpell.level]; + if (c->magicPointsCur > c->magicPointsMax) + c->magicPointsCur = c->magicPointsMax; + + c->hitPointsCur += _activeSpell.p->hpRequired[_activeSpell.level]; + if (c->hitPointsCur > c->hitPointsMax) + c->hitPointsCur = c->hitPointsMax; + + gui_drawCharPortraitWithStats(_activeSpell.charNum); + gui_enableDefaultPlayfieldButtons(); + return 1; } diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index 38b8c5a5a3..902977bdf6 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -363,16 +363,10 @@ void KyraEngine_MR::drawMalcolmsMoodPointer(int frame, int page) { frame = 13; if (page == 0) { - _invWsa->setX(0); - _invWsa->setY(0); - _invWsa->setDrawPage(0); - _invWsa->displayFrame(frame, 0); + _invWsa->displayFrame(frame, 0, 0, 0, 0); _screen->updateScreen(); } else if (page == 30) { - _invWsa->setX(0); - _invWsa->setY(-144); - _invWsa->setDrawPage(2); - _invWsa->displayFrame(frame, 0); + _invWsa->displayFrame(frame, 2, 0, -144, 0); } _invWsaFrame = frame; @@ -713,20 +707,11 @@ void KyraEngine_MR::showAlbum() { loadAlbumPage(); loadAlbumPageWSA(); - if (_album.leftPage.wsa->opened()) { - _album.leftPage.wsa->setX(_albumWSAX[_album.nextPage+0]); - _album.leftPage.wsa->setY(_albumWSAY[_album.nextPage+0]); - _album.leftPage.wsa->setDrawPage(2); + if (_album.leftPage.wsa->opened()) + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000); - _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 0x4000); - } - if (_album.rightPage.wsa->opened()) { - _album.rightPage.wsa->setX(_albumWSAX[_album.nextPage+1]); - _album.rightPage.wsa->setY(_albumWSAY[_album.nextPage+1]); - _album.rightPage.wsa->setDrawPage(2); - - _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000); - } + if (_album.rightPage.wsa->opened()) + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000); printAlbumPageText(); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); @@ -887,20 +872,11 @@ void KyraEngine_MR::processAlbum() { loadAlbumPage(); loadAlbumPageWSA(); - if (_album.leftPage.wsa->opened()) { - _album.leftPage.wsa->setX(_albumWSAX[_album.nextPage+0]); - _album.leftPage.wsa->setY(_albumWSAY[_album.nextPage+0]); - _album.leftPage.wsa->setDrawPage(2); - - _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 0x4000); - } - if (_album.rightPage.wsa->opened()) { - _album.rightPage.wsa->setX(_albumWSAX[_album.nextPage+1]); - _album.rightPage.wsa->setY(_albumWSAY[_album.nextPage+1]); - _album.rightPage.wsa->setDrawPage(2); + if (_album.leftPage.wsa->opened()) + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000); - _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000); - } + if (_album.rightPage.wsa->opened()) + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000); printAlbumPageText(); @@ -955,11 +931,7 @@ void KyraEngine_MR::albumUpdateAnims() { nextRun = _album.leftPage.timer + 5 * _tickLength; if (nextRun < _system->getMillis() && _album.leftPage.wsa->opened()) { - _album.leftPage.wsa->setX(_albumWSAX[_album.nextPage+0]); - _album.leftPage.wsa->setY(_albumWSAY[_album.nextPage+0]); - _album.leftPage.wsa->setDrawPage(2); - - _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 0x4000); + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000); _screen->copyRegion(40, 17, 40, 17, 87, 73, 2, 0, Screen::CR_NO_P_CHECK); ++_album.leftPage.curFrame; @@ -978,11 +950,7 @@ void KyraEngine_MR::albumUpdateAnims() { nextRun = _album.rightPage.timer + 5 * _tickLength; if (nextRun < _system->getMillis() && _album.rightPage.wsa->opened()) { - _album.rightPage.wsa->setX(_albumWSAX[_album.nextPage+1]); - _album.rightPage.wsa->setY(_albumWSAY[_album.nextPage+1]); - _album.rightPage.wsa->setDrawPage(2); - - _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000); + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000); _screen->copyRegion(194, 20, 194, 20, 85, 69, 2, 0, Screen::CR_NO_P_CHECK); ++_album.rightPage.curFrame; @@ -999,32 +967,26 @@ void KyraEngine_MR::albumUpdateAnims() { void KyraEngine_MR::albumAnim1() { debugC(9, kDebugLevelMain, "KyraEngine_MR::albumAnim1()"); - _album.wsa->setX(-100); - _album.wsa->setY(90); - _album.wsa->setDrawPage(2); for (int i = 6; i >= 3; --i) { albumRestoreRect(); - _album.wsa->displayFrame(i, 0x4000); + _album.wsa->displayFrame(i, 2, -100, 90, 0x4000); albumUpdateRect(); delayWithTicks(1); } albumRestoreRect(); - _album.wsa->displayFrame(14, 0x4000); + _album.wsa->displayFrame(14, 2, -100, 90, 0x4000); albumUpdateRect(); delayWithTicks(1); } void KyraEngine_MR::albumAnim2() { debugC(9, kDebugLevelMain, "KyraEngine_MR::albumAnim2()"); - _album.wsa->setX(-100); - _album.wsa->setY(90); - _album.wsa->setDrawPage(2); for (int i = 3; i <= 6; ++i) { albumRestoreRect(); - _album.wsa->displayFrame(i, 0x4000); + _album.wsa->displayFrame(i, 2, -100, 90, 0x4000); albumUpdateRect(); delayWithTicks(1); } diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp index 02c8e50410..765747f687 100644 --- a/engines/kyra/items_lol.cpp +++ b/engines/kyra/items_lol.cpp @@ -44,7 +44,7 @@ void LoLEngine::giveCredits(int credits, int redraw) { if (t > credits) t = credits; - if (_credits < 60 && t >= 0) { + if (_credits < 60 && t > 0) { cnt = 0; do { @@ -86,7 +86,7 @@ void LoLEngine::takeCredits(int credits, int redraw) { if (t > credits) t = credits; - if (_credits - t < 60 && t >= 0) { + if (_credits - t < 60 && t > 0) { cnt = 0; do { @@ -97,7 +97,7 @@ void LoLEngine::takeCredits(int credits, int redraw) { _moneyColumnHeight[d]--; } } while (++cnt < t); - } else if (_credits - t < 60) { + } else if (_credits - t >= 60) { _credits -= t; } @@ -343,7 +343,7 @@ void LoLEngine::removeLevelItem(int item, int block) { } bool LoLEngine::launchObject(int objectType, int item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c) { - int sp = checkDrawObjectSpace(_partyPosX, _partyPosX, startX, startY); + int sp = checkDrawObjectSpace(_partyPosX, _partyPosY, startX, startY); FlyingObject *t = _flyingObjects; int slot = -1; int i = 0; @@ -354,7 +354,7 @@ bool LoLEngine::launchObject(int objectType, int item, int startX, int startY, i break; } - int csp = checkDrawObjectSpace(_partyPosX, _partyPosX, t->x, t->y); + int csp = checkDrawObjectSpace(_partyPosX, _partyPosY, t->x, t->y); if (csp > sp){ sp = csp; slot = i; @@ -490,7 +490,8 @@ void LoLEngine::updateFlyingObject(FlyingObject *t) { int x = 0; int y = 0; getNextStepCoords(t->x, t->y, x, y, t->direction); - int objectOnNextBlock = checkBlockBeforeObjectPlacement(x, y, _itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000 ? 256 : 63, t->flags, t->wallFlags); + // WORKAROUND: The next line seems to be bugged in the original code. I have fixed it in a way that at least seems to work fine. + int objectOnNextBlock = checkBlockBeforeObjectPlacement(x, y, _itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000 ? 127 : 63, t->flags, t->wallFlags); if (objectOnNextBlock) { endObjectFlight(t, x, y, objectOnNextBlock); } else { diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index c040f3ab3d..ff0ee80456 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -1612,10 +1612,7 @@ void KyraEngine_HoF::updateInvWsa() { if (_invWsa.timer > _system->getMillis()) return; - _invWsa.wsa->setX(0); - _invWsa.wsa->setY(0); - _invWsa.wsa->setDrawPage(_invWsa.page); - _invWsa.wsa->displayFrame(_invWsa.curFrame, 0, 0, 0); + _invWsa.wsa->displayFrame(_invWsa.curFrame, _invWsa.page, 0, 0, 0, 0, 0); if (_invWsa.page) _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, _invWsa.page, 0, Screen::CR_NO_P_CHECK); @@ -1653,10 +1650,7 @@ void KyraEngine_HoF::displayInvWsaLastFrame() { if (!_invWsa.wsa) return; - _invWsa.wsa->setX(0); - _invWsa.wsa->setY(0); - _invWsa.wsa->setDrawPage(_invWsa.page); - _invWsa.wsa->displayFrame(_invWsa.lastFrame-1, 0, 0, 0); + _invWsa.wsa->displayFrame(_invWsa.lastFrame-1, _invWsa.page, 0, 0, 0, 0, 0); if (_invWsa.page) _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, _invWsa.page, 0, Screen::CR_NO_P_CHECK); diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 6baa90ea8f..a227d16937 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -274,14 +274,14 @@ Common::Error KyraEngine_MR::go() { for (int i = 0; i < 64 && !shouldQuit(); ++i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; - _menuAnim->displayFrame(i, 0); + _menuAnim->displayFrame(i, 0, 0, 0, 0); _screen->updateScreen(); delayUntil(nextRun); } for (int i = 64; i > 29 && !shouldQuit(); --i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; - _menuAnim->displayFrame(i, 0); + _menuAnim->displayFrame(i, 0, 0, 0, 0); _screen->updateScreen(); delayUntil(nextRun); } @@ -330,9 +330,6 @@ Common::Error KyraEngine_MR::go() { void KyraEngine_MR::initMainMenu() { _menuAnim = new WSAMovie_v2(this, _screen); _menuAnim->open("REVENGE.WSA", 1, _screen->getPalette(0)); - _menuAnim->setX(0); - _menuAnim->setY(0); - _menuAnim->setDrawPage(0); memset(_screen->getPalette(0), 0, 3); _menu = new MainMenu(this); diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index acf4be35dc..bdc0364c5a 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -72,6 +72,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy break; } + _chargenFrameTable = _flags.isTalkie ? _chargenFrameTableTalkie : _chargenFrameTableFloppy; _chargenWSA = 0; _lastUsedStringBuffer = 0; _landsFile = 0; @@ -89,6 +90,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _itemProperties = 0; _itemInHand = 0; memset(_inventory, 0, sizeof(_inventory)); + memset(_invSkillFlags, 0, sizeof(_invSkillFlags)); _inventoryCurItem = 0; _currentControlMode = 0; _specialSceneFlag = 0; @@ -102,6 +104,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy memset(_monsterAnimType, 0, 3); _pageSavedFlag = false; _healOverlay = 0; + _swarmSpellStatus = 0; _ingameMT32SoundIndex = _ingameGMSoundIndex = /*_ingameADLSoundIndex =*/ 0; @@ -110,7 +113,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _spellProperties = 0; _updateFlags = 0; _selectedSpell = 0; - _updateCharNum = _updatePortraitSpeechAnimDuration = _portraitSpeechAnimMode = _updateCharV3 = _textColourFlag = _needSceneRestore = 0; + _updateCharNum = _updatePortraitSpeechAnimDuration = _portraitSpeechAnimMode = _updateCharV3 = _textColorFlag = _needSceneRestore = 0; _fadeText = false; _palUpdateTimer = _updatePortraitNext = 0; _lampStatusTimer = 0xffffffff; @@ -155,7 +158,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _flyingObjects = 0; _monsters = 0; _lastMouseRegion = 0; - _monsterLastWalkDirection = _monsterCountUnk = _monsterShiftAlt = 0; + _objectLastDirection = _monsterCountUnk = _monsterShiftAlt = 0; _monsterCurBlock = 0; _seqWindowX1 = _seqWindowY1 = _seqWindowX2 = _seqWindowY2 = _seqTrigger = 0; _spsWindowX = _spsWindowY = _spsWindowW = _spsWindowH = 0; @@ -200,6 +203,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy memset(_activeTim, 0, sizeof(_activeTim)); memset(_activeVoiceFile, 0, sizeof(_activeVoiceFile)); memset(_openDoorState, 0, sizeof(_openDoorState)); + memset(&_activeSpell, 0, sizeof(_activeSpell)); _activeVoiceFileTotalTime = 0; _pageBuffer1 = _pageBuffer2 = 0; @@ -221,7 +225,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _floatingCursorsEnabled = false; memset(_lvlTempData, 0, sizeof(_lvlTempData)); - _unkIceSHpFlag = 0; + _freezeStateFlags = 0; _mapOverlay = 0; _automapShapes = 0; @@ -389,6 +393,7 @@ LoLEngine::~LoLEngine() { delete[] _defaultLegendData; delete[] _mapCursorOverlay; delete[] _mapOverlay; + _spellProcs.clear(); } Screen *LoLEngine::screen() { @@ -499,6 +504,24 @@ Common::Error LoLEngine::init() { _automapShapes = new const uint8*[109]; _mapOverlay = new uint8[256]; + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castSpark)); + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castHeal)); + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castIce)); + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castFireball)); + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castHandOfFate)); + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castMistOfDoom)); + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castLightning)); + _spellProcs.push_back(new SpellProc(this, 0)); + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castFog)); + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castSwarm)); + _spellProcs.push_back(new SpellProc(this, 0)); + _spellProcs.push_back(new SpellProc(this, 0)); + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castUnk)); + _spellProcs.push_back(new SpellProc(this, 0)); + _spellProcs.push_back(new SpellProc(this, 0)); + _spellProcs.push_back(new SpellProc(this, 0)); + _spellProcs.push_back(new SpellProc(this, &LoLEngine::castGuardian)); + return Common::kNoError; } @@ -736,7 +759,7 @@ int LoLEngine::mainMenu() { assert(menu); menu->init(data[dataIndex], MainMenu::Animation()); - int selection = menu->handle(_flags.isTalkie ? (hasSave ? 12 : 6) : (hasSave ? 6 : 13)); + int selection = menu->handle(_flags.isTalkie ? (hasSave ? 17 : 6) : (hasSave ? 6 : 18)); delete menu; _screen->setScreenDim(0); @@ -1153,7 +1176,7 @@ void LoLEngine::updatePortraits() { } void LoLEngine::initTextFading(int textType, int clearField) { - if (_textColourFlag == textType || !textType) { + if (_textColorFlag == textType || !textType) { _fadeText = true; _palUpdateTimer = _system->getMillis(); } @@ -1546,7 +1569,7 @@ void LoLEngine::fadeText() { if (!_fadeText) return; - if (_screen->fadeColour(192, 252, _system->getMillis() - _palUpdateTimer, 60 * _tickLength)) + if (_screen->fadeColor(192, 252, _system->getMillis() - _palUpdateTimer, 60 * _tickLength)) return; if (_needSceneRestore) @@ -1567,7 +1590,7 @@ void LoLEngine::setPaletteBrightness(uint8 *palette, int brightness, int modifie void LoLEngine::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier) { memcpy(dst, src, 0x300); - _screen->loadSpecialColours(dst); + _screen->loadSpecialColors(dst); brightness = (8 - brightness) << 5; if (modifier >= 0 && modifier < 8 && _gameFlags[15] & 0x800) { brightness = 256 - ((((modifier & 0xfffe) << 5) * (256 - brightness)) >> 8); @@ -1690,10 +1713,11 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { if (playList.empty()) return false; - while (_sound->voiceIsPlaying(_activeVoiceFile)) { - update(); - delay(_tickLength); - }; + while (_sound->voiceIsPlaying(_activeVoiceFile)) + delay(_tickLength, true, false); + + while (_sound->allVoiceChannelsPlaying()) + delay(_tickLength, false, true); strcpy(_activeVoiceFile, *playList.begin()); _activeVoiceFileTotalTime = _sound->voicePlayFromList(playList); @@ -1826,6 +1850,12 @@ void LoLEngine::snd_queueEnvironmentalSoundEffect(int soundId, int block) { } } +void LoLEngine::snd_playQueuedEffects() { + for (int i = 0; i < _envSfxNumTracksInQueue; i++) + snd_processEnvironmentalSoundEffect(_envSfxQueuedTracks[i], _envSfxQueuedBlocks[i]); + _envSfxNumTracksInQueue = 0; +} + void LoLEngine::snd_loadSoundFile(int track) { if (_sound->musicEnabled()) { char filename[13]; @@ -1969,7 +1999,7 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str } } - _fadeText = 0; + _fadeText = false; if (!skipAnim) updatePortraitSpeechAnim(); @@ -1996,12 +2026,26 @@ uint16 *LoLEngine::getCharacterOrMonsterProtectionAgainstItems(int id) { return (id & 0x8000) ? _monsters[id & 0x7fff].properties->protectionAgainstItems : _characters[id].protectionAgainstItems; } -void LoLEngine::delay(uint32 millis, bool cUpdate, bool isMainLoop) { - uint32 endTime = _system->getMillis() + millis; - while (endTime > _system->getMillis()) { +void LoLEngine::delay(uint32 millis, bool cUpdate, bool iUpdate) { + int del = (int)(millis); + while (del > 0) { if (cUpdate) update(); - _system->delayMillis(4); + if (iUpdate) + updateInput(); + int step = del >= _tickLength ? _tickLength : del; + _system->delayMillis(step); + del -= step; + } +} + +void LoLEngine::delayUntil(uint32 timeStamp) { + int del = (int)(timeStamp - _system->getMillis()); + while (del > 0) { + updateInput(); + int step = del >= _tickLength ? _tickLength : del; + _system->delayMillis(step); + del -= step; } } @@ -2035,7 +2079,181 @@ void LoLEngine::updateEnvironmentalSfx(int soundId) { snd_processEnvironmentalSoundEffect(soundId, _currentBlock); } -void LoLEngine::processMagicHeal(int charNum, int points) { +// spells + +int LoLEngine::castSpell(int charNum, int spellType, int spellLevel) { + _activeSpell.charNum = charNum; + _activeSpell.spell = spellType; + _activeSpell.p = &_spellProperties[spellType]; + + _activeSpell.level = spellLevel < 0 ? -spellLevel : spellLevel; + + if ((_spellProperties[spellType].flags & 0x100) && testWallFlag(calcNewBlockPosition(_currentBlock, _currentDirection), _currentDirection, 1)) { + _txt->printMessage(2, getLangString(0x4257)); + return 0; + } + + if (charNum < 0) { + _activeSpell.charNum = (charNum * -1) - 1; + if (_spellProcs[spellType]->isValid()) + return (*_spellProcs[spellType])(&_activeSpell); + } else { + if (_activeSpell.p->mpRequired[spellLevel] > _characters[charNum].magicPointsCur) + return 0; + + if (_activeSpell.p->hpRequired[spellLevel] >= _characters[charNum].hitPointsCur) + return 0; + + setCharacterMagicOrHitPoints(charNum, 1, -_activeSpell.p->mpRequired[spellLevel], 1); + setCharacterMagicOrHitPoints(charNum, 0, -_activeSpell.p[1].hpRequired[spellLevel], 1); + gui_drawCharPortraitWithStats(charNum); + + if (_spellProcs[spellType]->isValid()) + (*_spellProcs[spellType])(&_activeSpell); + } + + return 1; +} + +int LoLEngine::castSpark(ActiveSpell *a) { + processMagicSpark(a->charNum, a->level); + return 1; +} + +int LoLEngine::castHeal(ActiveSpell *a) { + if (a->level < 3) + processMagicHealSelectTarget(); + else + processMagicHeal(-1, a->level); + + return 1; +} + +int LoLEngine::castIce(ActiveSpell *a) { + processMagicIce(a->charNum, a->level); + return 1; +} + +int LoLEngine::castFireball(ActiveSpell *a) { + processMagicFireball(a->charNum, a->level); + return 1; +} + +int LoLEngine::castHandOfFate(ActiveSpell *a) { + return 1; +} + +int LoLEngine::castMistOfDoom(ActiveSpell *a) { + processMagicMistOfDoom(a->charNum, a->level); + return 1; +} + +int LoLEngine::castLightning(ActiveSpell *a) { + return 1; +} + +int LoLEngine::castFog(ActiveSpell *a) { + return 1; +} + +int LoLEngine::castSwarm(ActiveSpell *a) { + processMagicSwarm(a->charNum, 10); + return 1; +} + +int LoLEngine::castUnk(ActiveSpell *a) { + return 1; +} + +int LoLEngine::castGuardian(ActiveSpell *a) { + return 1; +} + +int LoLEngine::castHealOnSingleCharacter(ActiveSpell *a) { + processMagicHeal(a->target, a->level); + return 1; +} + +void LoLEngine::processMagicSpark(int charNum, int spellLevel) { + WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + _screen->copyPage(0, 12); + + mov->open("spark1.wsa", 0, 0); + if (!mov->opened()) + error("SPARK: Unable to load SPARK1.WSA"); + snd_playSoundEffect(72, -1); + playSpellAnimation(mov, 0, 7, 4, _activeCharsXpos[charNum] - 2, 138, 0, 0, 0, 0, false); + mov->close(); + + _screen->copyPage(12, 0); + _screen->updateScreen(); + + uint16 targetBlock = 0; + int dist = getSpellTargetBlock(_currentBlock, _currentDirection, 4, targetBlock); + uint16 target = getNearestMonsterFromCharacterForBlock(targetBlock, charNum); + + static const uint8 dmg[] = { 7, 15, 25, 60 }; + if (target != 0xffff) { + inflictMagicalDamage(target, charNum, dmg[spellLevel], 5, 0); + updateDrawPage2(); + gui_drawScene(0); + _screen->copyPage(0, 12); + } + + int numFrames = mov->open("spark2.wsa", 0, 0); + if (!mov->opened()) + error("SPARK: Unable to load SPARK2.WSA"); + + uint16 wX[6]; + uint16 wY[6]; + uint16 wFrames[6]; + const uint16 width = mov->width(); + const uint16 height = mov->height(); + + for (int i = 0; i < 6; i++) { + wX[i] = (_rnd.getRandomNumber(0x7fff) % 64) + ((176 - width) >> 1) + 80; + wY[i] = (_rnd.getRandomNumber(0x7fff) % 32) + ((120 - height) >> 1) - 16; + wFrames[i] = i << 1; + } + + for (int i = 0, d = ((spellLevel << 1) + 12); i < d; i++) { + _smoothScrollTimer = _system->getMillis() + 4 * _tickLength; + _screen->copyPage(12, 2); + + for (int ii = 0; ii <= spellLevel; ii++) { + if (wFrames[ii] >= i || wFrames[ii] + 13 <= i) + continue; + + if ((i - wFrames[ii]) == 1) + snd_playSoundEffect(162, -1); + + mov->displayFrame(((i - wFrames[ii]) + (dist << 4)) % numFrames, 2, wX[ii], wY[ii], 0x5000, _trueLightTable1, _trueLightTable2); + _screen->copyRegion(wX[ii], wY[ii], wX[ii], wY[ii], width, height, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + } + + if (i < d - 1) + delayUntil(_smoothScrollTimer); + } + + mov->close(); + + _screen->copyPage(12, 2); + updateDrawPage2(); + + _sceneUpdateRequired = true; + + delete mov; +} + +void LoLEngine::processMagicHealSelectTarget() { + _txt->printMessage(0, getLangString(0x4040)); + gui_resetButtonList(); + gui_setFaceFramesControlButtons(81, 0); + gui_initButtonsFromList(_buttonList8); +} + +void LoLEngine::processMagicHeal(int charNum, int spellLevel) { if (!_healOverlay) { _healOverlay = new uint8[256]; _screen->generateGrayOverlay(_screen->getPalette(1), _healOverlay, 52, 22, 20, 0, 256, true); @@ -2043,28 +2261,28 @@ void LoLEngine::processMagicHeal(int charNum, int points) { const uint8 *healShpFrames = 0; const uint8 *healiShpFrames = 0; - bool resetFlag = false; - int maxDiff = 0; + bool curePoison = false; + int points = 0; - if (points == 0) { - maxDiff = 25; + if (spellLevel == 0) { + points = 25; healShpFrames = _healShapeFrames; healiShpFrames = _healShapeFrames + 32; - } else if (points == 1) { - maxDiff = 45; + } else if (spellLevel == 1) { + points = 45; healShpFrames = _healShapeFrames + 16; healiShpFrames = _healShapeFrames + 48; - } else if (points > 3) { - resetFlag = true; - maxDiff = points; + } else if (spellLevel > 3) { + curePoison = true; + points = spellLevel; healShpFrames = _healShapeFrames + 16; healiShpFrames = _healShapeFrames + 64; } else { - resetFlag = true; - maxDiff = 10000; + curePoison = true; + points = 10000; healShpFrames = _healShapeFrames + 16; healiShpFrames = _healShapeFrames + 64; @@ -2087,13 +2305,15 @@ void LoLEngine::processMagicHeal(int charNum, int points) { memset(pts, 0, sizeof(pts)); while (charNum < n) { - if (!(_characters[charNum].flags & 1)) + if (!(_characters[charNum].flags & 1)) { + charNum++; continue; + } pX[charNum] = _activeCharsXpos[charNum] - 6; _characters[charNum].damageSuffered = 0; int dmg = _characters[charNum].hitPointsMax - _characters[charNum].hitPointsCur; - diff[charNum] = (dmg < maxDiff) ? dmg : maxDiff; + diff[charNum] = (dmg < points) ? dmg : points; _screen->copyRegion(pX[charNum], pY, charNum * 77, 32, 77, 44, 0, 2, Screen::CR_NO_P_CHECK); charNum++; } @@ -2125,20 +2345,17 @@ void LoLEngine::processMagicHeal(int charNum, int points) { _screen->updateScreen(); } - while ((int)(_smoothScrollTimer - _system->getMillis()) > 0) { - updateInput(); - delay(_tickLength); - } + delayUntil(_smoothScrollTimer); } for (charNum = ch; charNum < n; charNum++) { if (!(_characters[charNum].flags & 1)) - continue; + continue; _screen->copyRegion(charNum * 77, 32, pX[charNum], pY, 77, 44, 2, 2, Screen::CR_NO_P_CHECK); - if (resetFlag) - resetCharacterState(&_characters[charNum], 4, 4); + if (curePoison) + removeCharacterEffects(&_characters[charNum], 4, 4); gui_drawCharPortraitWithStats(charNum); _screen->copyRegion(pX[charNum], pY, pX[charNum], pY, 77, 44, 2, 0, Screen::CR_NO_P_CHECK); @@ -2149,12 +2366,317 @@ void LoLEngine::processMagicHeal(int charNum, int points) { updateDrawPage2(); } +void LoLEngine::processMagicIce(int charNum, int spellLevel) { + int cp = _screen->setCurPage(2); + + disableSysTimer(2); + + gui_drawScene(0); + _screen->copyPage(0, 12); + + //uint8 pal2[768]; + //uint8 pal3[768]; + + if (_currentLevel = 11 && !(_freezeStateFlags & 4)) { + for (int i = 1; i < 384; i++) { + + ///////// TODO + + } + + _freezeStateFlags |= 4; + static const uint8 freezeTimes[] = { 20, 28, 40, 60 }; + setCharacterUpdateEvent(charNum, 8, freezeTimes[spellLevel], 1); + } + + ////////// TODO + generateBrightnessPalette(_screen->_currentPalette, _screen->getPalette(1), _brightness, _lampEffect); + + ////////// TODO + + _screen->setCurPage(cp); +} + +void LoLEngine::processMagicFireball(int charNum, int spellLevel) { + +} + +void LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) { + +} + +void LoLEngine::processMagicSwarm(int charNum, int damage) { + int cp = _screen->setCurPage(2); + _screen->copyPage(0, 12); + snd_playSoundEffect(74, -1); + + uint16 destIds[6]; + uint8 destModes[6]; + int8 destTicks[6]; + + memset(destIds, 0, sizeof(destIds)); + memset(destModes, 8, sizeof(destModes)); + memset(destTicks, 0, sizeof(destTicks)); + + int t = 0; + uint16 o = _levelBlockProperties[calcNewBlockPosition(_currentBlock, _currentDirection)].assignedObjects; + while (o & 0x8000) { + o &= 0x7fff; + if (_monsters[o].mode != 13) { + destIds[t++] = o; + + if (!(_monsters[o].flags & 0x2000)) { + _envSfxUseQueue = true; + inflictMagicalDamage(o | 0x8000, charNum, damage, 0, 0); + _envSfxUseQueue = false; + _monsters[o].flags &= 0xffef; + } + } + o = _monsters[o].nextAssignedObject; + } + + for (int i = 0; i < t; i++) { + SWAP(destModes[i], _monsters[destIds[i]].mode); + SWAP(destTicks[i], _monsters[destIds[i]].fightCurTick); + } + + gui_drawScene(_screen->_curPage); + _screen->copyRegion(112, 0, 112, 0, 176, 120, _screen->_curPage, 7); + + for (int i = 0; i < t; i++) { + _monsters[destIds[i]].mode = destModes[i]; + _monsters[destIds[i]].fightCurTick = destTicks[i]; + } + + WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + + mov->open("swarm.wsa", 0, 0); + if (!mov->opened()) + error("Swarm: Unable to load SWARM.WSA"); + _screen->hideMouse(); + playSpellAnimation(mov, 0, 37, 2, 0, 0, 0, 0, 0, 0, false); + playSpellAnimation(mov, 38, 41, 8, 0, 0, &LoLEngine::callbackProcessMagicSwarm, 0, 0, 0, false); + _screen->showMouse(); + mov->close(); + + _screen->copyPage(12, 0); + updateDrawPage2(); + + snd_playQueuedEffects(); + + _screen->setCurPage(cp); + delete mov; +} + +void LoLEngine::callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y) { + if (_swarmSpellStatus) + _screen->copyRegion(112, 0, 112, 0, 176, 120, 6, _screen->_curPage); + _swarmSpellStatus ^= 1; +} + +void LoLEngine::addSpellToScroll(int spell, int charNum) { + bool assigned = false; + int slot = 0; + for (int i = 0; i < 7; i++) { + if (!assigned && _availableSpells[i] == -1) { + assigned = true; + slot = i; + } + + if (_availableSpells[i] == spell) { + _txt->printMessage(2, getLangString(0x42d0)); + return; + } + } + + if (spell > 1) + transferSpellToScollAnimation(charNum, spell, slot - 1); + + _availableSpells[slot] = spell; + gui_enableDefaultPlayfieldButtons(); +} + +void LoLEngine::transferSpellToScollAnimation(int charNum, int spell, int slot) { + int cX = 16 + _activeCharsXpos[charNum]; + + if (slot != 1) { + _screen->loadBitmap("playfld.cps", 3, 3, 0); + _screen->copyRegion(8, 0, 216, 0, 96, 120, 3, 3, Screen::CR_NO_P_CHECK); + _screen->copyPage(3, 10); + for (int i = 0; i < 9; i++) { + int h = (slot + 1) * 9 + i + 1; + _smoothScrollTimer = _system->getMillis() + _tickLength; + _screen->copyPage(10, 3); + _screen->copyRegion(216, 0, 8, 0, 96, 120, 3, 3, Screen::CR_NO_P_CHECK); + _screen->copyRegion(112, 0, 12, 0, 87, 15, 2, 2, Screen::CR_NO_P_CHECK); + _screen->copyRegion(201, 1, 17, 15, 6, h, 2, 2, Screen::CR_NO_P_CHECK); + _screen->copyRegion(208, 1, 89, 15, 6, h, 2, 2, Screen::CR_NO_P_CHECK); + int cp = _screen->setCurPage(2); + _screen->fillRect(21, 15, 89, h + 15, 206); + _screen->copyRegion(112, 16, 12, h + 15, 87, 14, 2, 2, Screen::CR_NO_P_CHECK); + + int y = 15; + for (int ii = 0; ii < 7; ii++) { + if (_availableSpells[ii] == -1) + continue; + uint8 col = (ii == _selectedSpell) ? 132 : 1; + _screen->fprintString(getLangString(_spellProperties[_availableSpells[ii]].spellNameCode), 24, y, col, 0, 0); + y += 9; + } + + _screen->setCurPage(cp); + _screen->copyRegion(8, 0, 8, 0, 96, 120, 3, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + + delayUntil(_smoothScrollTimer); + } + } + + _screen->hideMouse(); + + _screen->copyPage(0, 12); + int vX = _updateSpellBookCoords[slot << 1] + 32; + int vY = _updateSpellBookCoords[(slot << 1) + 1] + 5; + + char wsaFile[13]; + snprintf(wsaFile, 13, "write%0d%c.wsa", spell, (_lang == 1) ? 'f' : (_lang == 0 ? 'e' : 'g')); + snd_playSoundEffect(_updateSpellBookAnimData[(spell << 2) + 3], -1); + snd_playSoundEffect(95, -1); + + WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + + mov->open("getspell.wsa", 0, 0); + if (!mov->opened()) + error("SpellBook: Unable to load getspell anim"); + snd_playSoundEffect(128, -1); + playSpellAnimation(mov, 0, 25, 5, _activeCharsXpos[charNum], 148, 0, 0, 0, 0, true); + snd_playSoundEffect(128, -1); + playSpellAnimation(mov, 26, 52, 5, _activeCharsXpos[charNum], 148, 0, 0, 0, 0, true); + + for (int i = 16; i > 0; i--) { + _smoothScrollTimer = _system->getMillis() + _tickLength; + _screen->copyPage(12, 2); + + int wsaX = vX + (((((cX - vX) << 8) / 16) * i) >> 8) - 16; + int wsaY = vY + (((((160 - vY) << 8) / 16) * i) >> 8) - 16; + + mov->displayFrame(51, 2, wsaX, wsaY, 0x5000, _trueLightTable1, _trueLightTable2); + + _screen->copyRegion(wsaX, wsaY, wsaX, wsaY, mov->width() + 48, mov->height() + 48, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + + delayUntil(_smoothScrollTimer); + } + + mov->close(); + + mov->open("spellexp.wsa", 0, 0); + if (!mov->opened()) + error("SpellBook: Unable to load spellexp anim"); + snd_playSoundEffect(168, -1); + playSpellAnimation(mov, 0, 8, 3, vX - 44, vY - 38, 0, 0, 0, 0, true); + mov->close(); + + mov->open("writing.wsa", 0, 0); + if (!mov->opened()) + error("SpellBook: Unable to load writing anim"); + playSpellAnimation(mov, 0, 6, 5, _updateSpellBookCoords[slot << 1], _updateSpellBookCoords[(slot << 1) + 1], 0, 0, 0, 0, false); + mov->close(); + + mov->open(wsaFile, 0, 0); + if (!mov->opened()) + error("SpellBook: Unable to load spellbook anim"); + snd_playSoundEffect(_updateSpellBookAnimData[(spell << 2) + 3], -1); + playSpellAnimation(mov, _updateSpellBookAnimData[(spell << 2) + 1], _updateSpellBookAnimData[(spell << 2) + 2], _updateSpellBookAnimData[spell << 2], _updateSpellBookCoords[slot << 1], _updateSpellBookCoords[(slot << 1) + 1], 0, 0, 0, 0, false); + mov->close(); + + gui_drawScene(2); + updateDrawPage2(); + + _screen->showMouse(); + + delete mov; +} + +void LoLEngine::playSpellAnimation(WSAMovie_v2 *mov, int firstFrame, int lastFrame, int frameDelay, int x, int y, SpellProcCallback callback, uint8 *pal1, uint8 *pal2, int fadeDelay, bool restoreScreen) { + int w = 0; + int h = 0; + + if (mov) { + w = mov->width(); + h = mov->height(); + } + + int w2 = w; + int h2 = h; + uint32 startTime = _system->getMillis(); + + if (x < 0) + w2 += x; + if (y < 0) + h2 += y; + + int dir = lastFrame >= firstFrame ? 1 : -1; + int curFrame = firstFrame; + + bool fin = false; + + while (!fin) { + _smoothScrollTimer = _system->getMillis() + _tickLength * frameDelay; + + if (mov || callback) + _screen->copyPage(12, 2); + + if (callback) + (this->*callback)(mov, x, y); + + if (mov) + mov->displayFrame(curFrame % mov->frames(), 2, x, y, 0x5000, _trueLightTable1, _trueLightTable2); + + if (mov || callback) { + _screen->copyRegion(x, y, x, y, w2, h2, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + } + + int del = _smoothScrollTimer - _system->getMillis(); + do { + + int step = del > _tickLength ? _tickLength : del; + + if (!pal1 || !pal2) { + delay(step); + del -= step; + continue; + } + + if (!_screen->fadePalSpecial(pal1, pal2, _system->getMillis() - startTime, _tickLength * fadeDelay) && !mov) + return; + + delay(step); + del -= step; + } while (del > 0); + + if (!mov) + continue; + + curFrame += dir; + if (curFrame == lastFrame) + fin = true; + } + + if (restoreScreen && (mov || callback)) { + _screen->copyPage(12, 2); + _screen->copyRegion(x, y, x, y, w2, h2, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + } +} + int LoLEngine::checkMagic(int charNum, int spellNum, int spellLevel) { if (_spellProperties[spellNum].mpRequired[spellLevel] > _characters[charNum].magicPointsCur) { if (characterSays(0x4043, _characters[charNum].id, true)) _txt->printMessage(6, getLangString(0x4043), _characters[charNum].name); return 1; - } else if (_spellProperties[spellNum + 1].unkArr[spellLevel] >= _characters[charNum].hitPointsCur) { + } else if (_spellProperties[spellNum].hpRequired[spellLevel] >= _characters[charNum].hitPointsCur) { _txt->printMessage(2, getLangString(0x4179), _characters[charNum].name); return 1; } @@ -2162,6 +2684,35 @@ int LoLEngine::checkMagic(int charNum, int spellNum, int spellLevel) { return 0; } +int LoLEngine::getSpellTargetBlock(int currentBlock, int direction, int maxDistance, uint16 &targetBlock) { + targetBlock = 0xffff; + uint16 c = calcNewBlockPosition(currentBlock, direction); + + int i = 0; + for (; i < maxDistance; i++) { + if (_levelBlockProperties[currentBlock].assignedObjects & 0x8000) { + targetBlock = currentBlock; + return i; + } + + if (_wllWallFlags[_levelBlockProperties[c].walls[direction ^ 2]] & 7) { + targetBlock = c; + return i; + } + + currentBlock = c; + c = calcNewBlockPosition(currentBlock, direction); + } + + return i; +} + +void LoLEngine::inflictMagicalDamage(int target, int attacker, int damage, int index, int hitType) { + hitType = hitType ? 1 : 2; + damage = calcInflictableDamagePerItem(attacker, target, damage, index, hitType); + inflictDamage(target, damage, attacker, 2, index); +} + // fight int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) { @@ -2296,11 +2847,11 @@ void LoLEngine::characterHitpointsZero(int16 charNum, int deathFlag) { LoLCharacter *c = &_characters[charNum]; c->hitPointsCur = 0; c->flags |= 8; - resetCharacterState(c, 1, 5); + removeCharacterEffects(c, 1, 5); _partyDeathFlag = deathFlag; } -void LoLEngine::resetCharacterState(LoLCharacter *c, int first, int last) { +void LoLEngine::removeCharacterEffects(LoLCharacter *c, int first, int last) { for (int i = first; i <= last; i++) { switch (i - 1) { case 0: @@ -2614,13 +3165,16 @@ uint16 LoLEngine::getNearestMonsterFromCharacter(int charNum) { return getNearestMonsterFromCharacterForBlock(calcNewBlockPosition(_currentBlock, _currentDirection), charNum); } -uint16 LoLEngine::getNearestMonsterFromCharacterForBlock(int block, int charNum) { +uint16 LoLEngine::getNearestMonsterFromCharacterForBlock(uint16 block, int charNum) { uint16 cX = 0; uint16 cY = 0; uint16 id = 0xffff; int minDist = 0x7fff; + if (block == 0xffff) + return id; + calcCoordinatesForSingleCharacter(charNum, cX, cY); int o = _levelBlockProperties[block].assignedObjects; diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index dce5a81a25..495641fa04 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -78,7 +78,11 @@ struct LoLCharacter { struct SpellProperty { uint16 spellNameCode; uint16 mpRequired[4]; - uint16 unkArr[8]; + uint16 field_a; + uint16 field_c; + uint16 hpRequired[4]; + uint16 field_16; + uint16 field_18; uint16 flags; }; @@ -209,6 +213,14 @@ struct OpenDoorState { int8 state; }; +struct ActiveSpell { + uint8 spell; + const SpellProperty *p; + uint8 charNum; + uint8 level; + uint8 target; +}; + struct FlyingObject { uint8 enable; uint8 objectType; @@ -311,7 +323,9 @@ private: static const CharacterPrev _charPreviews[]; WSAMovie_v2 *_chargenWSA; - static const uint8 _chargenFrameTable[]; + static const uint8 _chargenFrameTableTalkie[]; + static const uint8 _chargenFrameTableFloppy[]; + const uint8 *_chargenFrameTable; int chooseCharacter(); void kingSelectionIntro(); @@ -377,6 +391,7 @@ private: void snd_playSoundEffect(int track, int volume); void snd_processEnvironmentalSoundEffect(int soundId, int block); void snd_queueEnvironmentalSoundEffect(int soundId, int block); + void snd_playQueuedEffects(); void snd_loadSoundFile(int track); int snd_playTrack(int track); int snd_stopMusic(); @@ -430,7 +445,7 @@ private: void gui_drawInventoryItem(int index); void gui_drawCompass(); void gui_drawScroll(); - void gui_highlightSelectedSpell(int unk); + void gui_highlightSelectedSpell(bool mode); void gui_displayCharInventory(int charNum); void gui_printCharInventoryStats(int charNum); void gui_printCharacterStats(int index, int redraw, int value); @@ -502,8 +517,8 @@ private: int clickedWall(Button *button); int clickedSequenceWindow(Button *button); int clickedScroll(Button *button); - int clickedUnk23(Button *button); - int clickedUnk24(Button *button); + int clickedSpellTargetCharacter(Button *button); + int clickedSpellTargetScene(Button *button); int clickedSceneThrowItem(Button *button); int clickedOptions(Button *button); int clickedRestParty(Button *button); @@ -559,6 +574,7 @@ private: int olol_setWallType(EMCState *script); int olol_getWallType(EMCState *script); int olol_drawScene(EMCState *script); + int olol_moveParty(EMCState *script); int olol_delay(EMCState *script); int olol_setGameFlag(EMCState *script); int olol_testGameFlag(EMCState *script); @@ -580,6 +596,7 @@ private: int olol_playAnimationPart(EMCState *script); int olol_freeAnimStruct(EMCState *script); int olol_getDirection(EMCState *script); + int olol_characterSurpriseFeedback(EMCState *script); int olol_setMusicTrack(EMCState *script); int olol_setSequenceButtons(EMCState *script); int olol_setDefaultButtonState(EMCState *script); @@ -635,12 +652,15 @@ private: int olol_changeMonsterStat(EMCState *script); int olol_getMonsterStat(EMCState *script); int olol_playCharacterScriptChat(EMCState *script); + int olol_playEnvironmentalSfx(EMCState *script); int olol_update(EMCState *script); int olol_healCharacter(EMCState *script); int olol_drawExitButton(EMCState *script); int olol_loadSoundFile(EMCState *script); int olol_playMusicTrack(EMCState *script); int olol_countBlockItems(EMCState *script); + int olol_characterSkillTest(EMCState *script); + int olol_countActiveMonsters(EMCState *script); int olol_stopCharacterSpeech(EMCState *script); int olol_setPaletteBrightness(EMCState *script); int olol_calcInflictableDamage(EMCState *script); @@ -649,12 +669,17 @@ private: int olol_printMessage(EMCState *script); int olol_deleteLevelItem(EMCState *script); int olol_calcInflictableDamagePerItem(EMCState *script); + int olol_distanceAttack(EMCState *script); + int olol_removeCharacterEffects(EMCState *script); int olol_objectLeavesLevel(EMCState *script); + int olol_addSpellToScroll(EMCState *script); int olol_playDialogueTalkText(EMCState *script); int olol_checkMonsterTypeHostility(EMCState *script); int olol_setNextFunc(EMCState *script); int olol_dummy1(EMCState *script); int olol_suspendMonster(EMCState *script); + int olol_triggerEventOnMouseButtonRelease(EMCState *script); + int olol_printWindowText(EMCState *script); int olol_setUnkDoorVar(EMCState *script); int olol_resetTimDialogueState(EMCState *script); int olol_savePage5(EMCState *script); @@ -668,6 +693,7 @@ private: int olol_resetPortraitsAndDisableSysTimer(EMCState *script); int olol_enableSysTimer(EMCState *script); int olol_checkNeedSceneRestore(EMCState *script); + int olol_castSpell(EMCState *script); int olol_disableControls(EMCState *script); int olol_enableControls(EMCState *script); int olol_characterSays(EMCState *script); @@ -785,7 +811,7 @@ private: int _updatePortraitSpeechAnimDuration; int _portraitSpeechAnimMode; int _updateCharV3; - int _textColourFlag; + int _textColorFlag; bool _fadeText; int _needSceneRestore; uint32 _palUpdateTimer; @@ -1070,6 +1096,7 @@ private: int _currentControlMode; int _specialSceneFlag; int _lastCharInventory; + uint16 _invSkillFlags[6]; FlyingObject *_flyingObjects; @@ -1107,7 +1134,7 @@ private: int checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, int testFlag, int wallFlag); int checkBlockForWallsAndSufficientSpace(int block, int x, int y, int objectWidth, int testFlag, int wallFlag); int calcMonsterSkillLevel(int id, int a); - bool checkBlockOccupiedByParty(int x, int y, int testFlag); + int checkBlockOccupiedByParty(int x, int y, int testFlag); const uint16 *getCharacterOrMonsterStats(int id); uint16 *getCharacterOrMonsterItemsMight(int id); uint16 *getCharacterOrMonsterProtectionAgainstItems(int id); @@ -1145,7 +1172,7 @@ private: uint8 **_monsterShapesEx; uint8 _monsterAnimType[3]; uint16 _monsterCurBlock; - int _monsterLastWalkDirection; + int _objectLastDirection; int _monsterCountUnk; int _monsterShiftAlt; @@ -1163,7 +1190,8 @@ private: int _monsterScaleWHSize; // misc - void delay(uint32 millis, bool cUpdate = false, bool isMainLoop = false); + void delay(uint32 millis, bool cUpdate = false, bool iUpdate = false); + void delayUntil(uint32 timeStamp); uint8 getRandomNumberSpecial(); uint8 _compassBroken; @@ -1175,17 +1203,53 @@ private: uint32 _rndSpecial; // spells - void processMagicHeal(int charNum, int points); - int checkMagic(int charNum, int spellNum, int spellLevel); - + typedef Common::Functor1Mem<ActiveSpell*, int, LoLEngine> SpellProc; + Common::Array<const SpellProc*> _spellProcs; + typedef void (LoLEngine::*SpellProcCallback)(WSAMovie_v2*, int, int); + + int castSpell(int charNum, int spellType, int spellLevel); + + int castSpark(ActiveSpell *a); + int castHeal(ActiveSpell *a); + int castIce(ActiveSpell *a); + int castFireball(ActiveSpell *a); + int castHandOfFate(ActiveSpell *a); + int castMistOfDoom(ActiveSpell *a); + int castLightning(ActiveSpell *a); + int castFog(ActiveSpell *a); + int castSwarm(ActiveSpell *a); + int castUnk(ActiveSpell *a); + int castGuardian(ActiveSpell *a); + int castHealOnSingleCharacter(ActiveSpell *a); + + void processMagicSpark(int charNum, int spellLevel); + void processMagicHealSelectTarget(); + void processMagicHeal(int charNum, int spellLevel); + void processMagicIce(int charNum, int spellLevel); + void processMagicFireball(int charNum, int spellLevel); + void processMagicMistOfDoom(int charNum, int spellLevel); + void processMagicSwarm(int charNum, int damage); + + void callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y); + + void addSpellToScroll(int spell, int charNum); + void transferSpellToScollAnimation(int charNum, int spell, int slot); + + void playSpellAnimation(WSAMovie_v2 *mov, int firstFrame, int lastFrame, int frameDelay, int x, int y, SpellProcCallback callback, uint8 *pal1, uint8 *pal2, int fadeDelay, bool restoreScreen); + int checkMagic(int charNum, int spellNum, int spellLevel); + int getSpellTargetBlock(int currentBlock, int direction, int maxDistance, uint16 &targetBlock); + void inflictMagicalDamage(int target, int attacker, int damage, int index, int hitType); + + ActiveSpell _activeSpell; int8 _availableSpells[7]; int _selectedSpell; const SpellProperty *_spellProperties; int _spellPropertiesSize; int _subMenuIndex; - uint16 _unkIceSHpFlag; + uint16 _freezeStateFlags; uint8 *_healOverlay; + uint8 _swarmSpellStatus; uint8 **_fireballShapes; int _numFireballShapes; @@ -1194,6 +1258,10 @@ private: uint8 **_healiShapes; int _numHealiShapes; + const uint8 *_updateSpellBookCoords; + int _updateSpellBookCoordsSize; + const uint8 *_updateSpellBookAnimData; + int _updateSpellBookAnimDataSize; const uint8 *_healShapeFrames; int _healShapeFramesSize; @@ -1202,7 +1270,7 @@ private: int calcInflictableDamage(int16 attacker, int16 target, int hitType); int inflictDamage(uint16 target, int damage, uint16 attacker, int skill, int deathFlag); void characterHitpointsZero(int16 charNum, int a); - void resetCharacterState(LoLCharacter *c, int first, int last); + void removeCharacterEffects(LoLCharacter *c, int first, int last); int calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 itemMight, int index, int hitType); void checkForPartyDeath(); @@ -1220,7 +1288,7 @@ private: void attackWall(int a, int b); uint16 getNearestMonsterFromCharacter(int charNum); - uint16 getNearestMonsterFromCharacterForBlock(int block, int charNum); + uint16 getNearestMonsterFromCharacterForBlock(uint16 block, int charNum); uint16 getNearestMonsterFromPos(int x, int y); uint16 getNearestPartyMemberFromPos(int x, int y); diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 99e0c9981d..98d929d406 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -287,6 +287,8 @@ enum kKyraResources { lolMapStringId, //lolMapPal, + lolSpellbookAnim, + lolSpellbookCoords, lolHealShapeFrames, #endif // ENABLE_LOL diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 2508a3062a..38227cfae5 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -398,7 +398,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight memcpy(_screen->getPalette(2) + 0x180, _screen->_currentPalette, 384); delete[] swampPal; - if (_unkIceSHpFlag & 4) { + if (_freezeStateFlags & 4) { uint8 *pal0 = _screen->_currentPalette; uint8 *pal2 = _screen->getPalette(2); for (int i = 1; i < 768; i++) @@ -870,24 +870,23 @@ bool LoLEngine::clickedShape(int shapeIndex) { return false; } -void LoLEngine::processDoorSwitch(uint16 block, int unk) { +void LoLEngine::processDoorSwitch(uint16 block, int openClose) { if ((block == _currentBlock) || (_levelBlockProperties[block].assignedObjects & 0x8000)) return; - int s = 0; - if (!unk) { + if (openClose == 0) { for (int i = 0; i < 3; i++) { if (_openDoorState[i].block != block) continue; - s = -_openDoorState[i].state; + openClose = -_openDoorState[i].state; break; } } - if (s == 0) - s = (_wllWallFlags[_levelBlockProperties[block].walls[_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8 ? 0 : 1]] & 1) ? 1 : -1; + if (openClose == 0) + openClose = (_wllWallFlags[_levelBlockProperties[block].walls[_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8 ? 0 : 1]] & 1) ? 1 : -1; - openCloseDoor(block, s); + openCloseDoor(block, openClose); } void LoLEngine::openCloseDoor(uint16 block, int openClose) { @@ -1255,6 +1254,7 @@ void LoLEngine::drawScene(int pageNum) { drawScriptShapes(_sceneDrawPage1); _screen->copyRegion(112, 0, 112, 0, 176, 120, _sceneDrawPage1, _sceneDrawPage2, Screen::CR_NO_P_CHECK); _screen->copyRegion(112, 0, 112, 0, 176, 120, _sceneDrawPage1, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); SWAP(_sceneDrawPage1, _sceneDrawPage2); } @@ -1316,7 +1316,7 @@ void LoLEngine::prepareSpecialScene(int fieldType, int hasDialogue, int suspendG if (fadeFlag) { memcpy(_screen->getPalette(3) + 384, _screen->_currentPalette + 384, 384); - _screen->loadSpecialColours(_screen->getPalette(3)); + _screen->loadSpecialColors(_screen->getPalette(3)); _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; } diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index f24d3a4472..4559edcc09 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -148,7 +148,7 @@ void Screen_LoL::fprintStringIntro(const char *format, int x, int y, uint8 c1, u printText(buffer, x, y, c1, c2); } -void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColours) { +void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors) { uint8 tmpPal[768]; for (int i = 0; i != lastColor; i++) { @@ -161,7 +161,7 @@ void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, in } for (int i = 0; i < lastColor; i++) - grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor, skipSpecialColours); + grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor, skipSpecialColors); } uint8 *Screen_LoL::generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight) { @@ -290,7 +290,7 @@ void Screen_LoL::fadeClearSceneWindow(int delay) { memcpy(tpal, _currentPalette, 768); memset(tpal, 0, 384); - loadSpecialColours(tpal); + loadSpecialColors(tpal); fadePalette(tpal, delay); fillRect(112, 0, 288, 120, 0); delete[] tpal; @@ -658,13 +658,13 @@ void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) { _fadeFlag = 2; } -void Screen_LoL::loadSpecialColours(uint8 *destPalette) { +void Screen_LoL::loadSpecialColors(uint8 *destPalette) { memcpy(destPalette + 0x240, _screenPalette + 0x240, 12); } -void Screen_LoL::copyColour(int dstColourIndex, int srcColourIndex) { - uint8 *s = _screenPalette + srcColourIndex * 3; - uint8 *d = _screenPalette + dstColourIndex * 3; +void Screen_LoL::copyColor(int dstColorIndex, int srcColorIndex) { + uint8 *s = _screenPalette + srcColorIndex * 3; + uint8 *d = _screenPalette + dstColorIndex * 3; memcpy(d, s, 3); uint8 ci[4]; @@ -673,13 +673,13 @@ void Screen_LoL::copyColour(int dstColourIndex, int srcColourIndex) { ci[2] = (d[2] << 2) | (d[2] & 3); ci[3] = 0; - _system->setPalette(ci, dstColourIndex, 1); + _system->setPalette(ci, dstColorIndex, 1); } -bool Screen_LoL::fadeColour(int dstColourIndex, int srcColourIndex, uint32 elapsedTime, uint32 targetTime) { - uint8 *dst = _screenPalette + 3 * dstColourIndex; - uint8 *src = _screenPalette + 3 * srcColourIndex; - uint8 *p = getPalette(1) + 3 * dstColourIndex; +bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime) { + uint8 *dst = _screenPalette + 3 * dstColorIndex; + uint8 *src = _screenPalette + 3 * srcColorIndex; + uint8 *p = getPalette(1) + 3 * dstColorIndex; bool res = false; @@ -714,7 +714,35 @@ bool Screen_LoL::fadeColour(int dstColourIndex, int srcColourIndex, uint32 elaps uint8 tpal[768]; memcpy(tpal, _screenPalette, 768); - memcpy(tpal + dstColourIndex * 3, tmpPalEntry, 3); + memcpy(tpal + dstColorIndex * 3, tmpPalEntry, 3); + setScreenPalette(tpal); + updateScreen(); + + return res; +} + +bool Screen_LoL::fadePalSpecial(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime) { + uint8 tpal[768]; + uint8 *p1 = _palettes[1]; + + bool res = false; + for (int i = 0; i < 768; i++) { + uint8 out = 0; + if (elapsedTime < targetTime) { + int d = (pal2[i] & 0x3f) - (pal1[i] & 0x3f); + if (d) + res = true; + + int val = ((((d << 8) / targetTime) * elapsedTime) >> 8) & 0xff; + out = ((pal1[i] & 0x3f) + val) & 0xff; + } else { + out = p1[i] = (pal2[i] & 0x3f); + res = false; + } + + tpal[i] = out; + } + setScreenPalette(tpal); updateScreen(); diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index d7580e1ff8..1c2b6a3b93 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -64,11 +64,12 @@ public: // palette stuff void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0); - void loadSpecialColours(uint8 *destPalette); - void copyColour(int dstColourIndex, int srcColourIndex); - bool fadeColour(int dstColourIndex, int srcColourIndex, uint32 elapsedTime, uint32 targetTime); + void loadSpecialColors(uint8 *destPalette); + void copyColor(int dstColorIndex, int srcColorIndex); + bool fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime); + bool fadePalSpecial(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime); - void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColours); + void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors); uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight); uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; } diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp index 50333cd44a..ece324fd19 100644 --- a/engines/kyra/screen_v2.cpp +++ b/engines/kyra/screen_v2.cpp @@ -90,12 +90,12 @@ void Screen_v2::applyOverlay(int x, int y, int w, int h, int pageNum, const uint } } -int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColours) { +int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColors) { int m = 0x7fff; int r = 0x101; for (int i = 0; i < numColors; i++) { - if (skipSpecialColours && i >= 0xc0 && i <= 0xc3) + if (skipSpecialColors && i >= 0xc0 && i <= 0xc3) continue; int v = paletteEntry[0] - *palette++; diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h index dd001da731..22bab346db 100644 --- a/engines/kyra/screen_v2.h +++ b/engines/kyra/screen_v2.h @@ -45,7 +45,7 @@ public: // palette handling uint8 *generateOverlay(const uint8 *palette, uint8 *buffer, int color, uint16 factor); void applyOverlay(int x, int y, int w, int h, int pageNum, const uint8 *overlay); - int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColours = false); + int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColors = false); virtual void getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff); diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp index 9f6a52a18e..2a55dfa484 100644 --- a/engines/kyra/script_hof.cpp +++ b/engines/kyra/script_hof.cpp @@ -187,10 +187,7 @@ int KyraEngine_HoF::o2_displayWsaFrame(EMCState *script) { _screen->hideMouse(); uint32 endTime = _system->getMillis() + waitTime * _tickLength; - _wsaSlots[slot]->setX(x); - _wsaSlots[slot]->setY(y); - _wsaSlots[slot]->setDrawPage(dstPage); - _wsaSlots[slot]->displayFrame(frame, copyParam | 0xC000, 0, 0); + _wsaSlots[slot]->displayFrame(frame, dstPage, x, y, copyParam | 0xC000, 0, 0); _screen->updateScreen(); if (backUp) @@ -222,17 +219,13 @@ int KyraEngine_HoF::o2_displayWsaSequentialFramesLooping(EMCState *script) { if (maxTimes > 1) maxTimes = 1; - _wsaSlots[slot]->setX(x); - _wsaSlots[slot]->setY(y); - _wsaSlots[slot]->setDrawPage(0); - _screen->hideMouse(); int curTime = 0; while (curTime < maxTimes) { if (startFrame < endFrame) { for (int i = startFrame; i <= endFrame; ++i) { uint32 endTime = _system->getMillis() + waitTime * _tickLength; - _wsaSlots[slot]->displayFrame(i, 0xC000 | copyFlags, 0, 0); + _wsaSlots[slot]->displayFrame(i, 0, x, y, 0xC000 | copyFlags, 0, 0); if (!skipFlag()) { _screen->updateScreen(); @@ -248,7 +241,7 @@ int KyraEngine_HoF::o2_displayWsaSequentialFramesLooping(EMCState *script) { } else { for (int i = startFrame; i >= endFrame; --i) { uint32 endTime = _system->getMillis() + waitTime * _tickLength; - _wsaSlots[slot]->displayFrame(i, 0xC000 | copyFlags, 0, 0); + _wsaSlots[slot]->displayFrame(i, 0, x, y, 0xC000 | copyFlags, 0, 0); if (!skipFlag()) { _screen->updateScreen(); @@ -286,15 +279,11 @@ int KyraEngine_HoF::o2_displayWsaSequentialFrames(EMCState *script) { uint16 index = stackPos(5); uint16 copyParam = stackPos(6) | 0xc000; - _wsaSlots[index]->setX(stackPos(0)); - _wsaSlots[index]->setY(stackPos(1)); - _wsaSlots[index]->setDrawPage(0); - _screen->hideMouse(); while (currentFrame <= lastFrame) { uint32 endTime = _system->getMillis() + frameDelay; - _wsaSlots[index]->displayFrame(currentFrame++, copyParam, 0, 0); + _wsaSlots[index]->displayFrame(currentFrame++, 0, stackPos(0), stackPos(1), copyParam, 0, 0); if (!skipFlag()) { _screen->updateScreen(); delayUntil(endTime); @@ -315,10 +304,6 @@ int KyraEngine_HoF::o2_displayWsaSequence(EMCState *script) { const bool doUpdate = (stackPos(4) != 0); const uint16 copyParam = stackPos(5) | 0xc000; - _wsaSlots[index]->setX(stackPos(0)); - _wsaSlots[index]->setY(stackPos(1)); - _wsaSlots[index]->setDrawPage(0); - _screen->hideMouse(); int currentFrame = 0; @@ -326,7 +311,7 @@ int KyraEngine_HoF::o2_displayWsaSequence(EMCState *script) { while (currentFrame <= lastFrame) { uint32 endTime = _system->getMillis() + frameDelay; - _wsaSlots[index]->displayFrame(currentFrame++, copyParam, 0, 0); + _wsaSlots[index]->displayFrame(currentFrame++, 0, stackPos(0), stackPos(1), copyParam, 0, 0); if (!skipFlag()) { if (doUpdate) update(); diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp index 4901b5e1c4..5eb86519a8 100644 --- a/engines/kyra/script_lok.cpp +++ b/engines/kyra/script_lok.cpp @@ -426,11 +426,8 @@ int KyraEngine_LoK::o1_runWSAFromBeginningToEnd(EMCState *script) { int worldUpdate = stackPos(4); int wsaFrame = 0; - _movieObjects[wsaIndex]->setX(xpos); - _movieObjects[wsaIndex]->setY(ypos); - _movieObjects[wsaIndex]->setDrawPage(0); while (running) { - _movieObjects[wsaIndex]->displayFrame(wsaFrame++); + _movieObjects[wsaIndex]->displayFrame(wsaFrame++, 0, xpos, ypos); _animator->_updateScreen = true; if (wsaFrame >= _movieObjects[wsaIndex]->frames()) running = false; @@ -461,10 +458,7 @@ int KyraEngine_LoK::o1_displayWSAFrame(EMCState *script) { int waitTime = stackPos(3); int wsaIndex = stackPos(4); _screen->hideMouse(); - _movieObjects[wsaIndex]->setX(xpos); - _movieObjects[wsaIndex]->setY(ypos); - _movieObjects[wsaIndex]->setDrawPage(0); - _movieObjects[wsaIndex]->displayFrame(frame); + _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos); _animator->_updateScreen = true; uint32 continueTime = waitTime * _tickLength + _system->getMillis(); while (_system->getMillis() < continueTime) { @@ -504,12 +498,9 @@ int KyraEngine_LoK::o1_runWSAFrames(EMCState *script) { int endFrame = stackPos(4); int wsaIndex = stackPos(5); _screen->hideMouse(); - _movieObjects[wsaIndex]->setX(xpos); - _movieObjects[wsaIndex]->setY(ypos); - _movieObjects[wsaIndex]->setDrawPage(0); for (; startFrame <= endFrame; ++startFrame) { uint32 nextRun = _system->getMillis() + delayTime * _tickLength; - _movieObjects[wsaIndex]->displayFrame(startFrame); + _movieObjects[wsaIndex]->displayFrame(startFrame, 0, xpos, ypos); _animator->_updateScreen = true; while (_system->getMillis() < nextRun) { _sprites->updateSceneAnims(); @@ -691,10 +682,7 @@ int KyraEngine_LoK::o1_displayWSAFrameOnHidPage(EMCState *script) { _screen->hideMouse(); uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->setX(xpos); - _movieObjects[wsaIndex]->setY(ypos); - _movieObjects[wsaIndex]->setDrawPage(2); - _movieObjects[wsaIndex]->displayFrame(frame); + _movieObjects[wsaIndex]->displayFrame(frame, 2, xpos, ypos); _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { _sprites->updateSceneAnims(); @@ -759,17 +747,13 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { if (maxTime - 1 <= 0) maxTime = 1; - _movieObjects[wsaIndex]->setX(xpos); - _movieObjects[wsaIndex]->setY(ypos); - _movieObjects[wsaIndex]->setDrawPage(0); - // Workaround for bug #1498221 "KYRA1: Glitches when meeting Zanthia" // the original didn't do a forced screen update after displaying a wsa frame // while we have to do it, which make brandon disappear for a short moment, // what shouldn't happen. So we're not updating the screen for this special // case too. if (startFrame == 18 && endFrame == 18 && _currentRoom == 45) { - _movieObjects[wsaIndex]->displayFrame(18); + _movieObjects[wsaIndex]->displayFrame(18, 0, xpos, ypos); delay(waitTime * _tickLength); return 0; } @@ -781,7 +765,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { int frame = startFrame; while (endFrame >= frame) { uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->displayFrame(frame); + _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos); if (waitTime) _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { @@ -799,7 +783,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { int frame = startFrame; while (endFrame <= frame) { uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->displayFrame(frame); + _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos); if (waitTime) _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { @@ -1276,9 +1260,6 @@ int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_makeAmuletAppear(%p) ()", (const void *)script); WSAMovie_v1 amulet(this); amulet.open("AMULET.WSA", 1, 0); - amulet.setX(224); - amulet.setY(152); - amulet.setDrawPage(0); if (amulet.opened()) { assert(_amuleteAnim); _screen->hideMouse(); @@ -1297,7 +1278,7 @@ int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) { if (code == 14) snd_playSoundEffect(0x73); - amulet.displayFrame(code); + amulet.displayFrame(code, 0, 224, 152); _animator->_updateScreen = true; while (_system->getMillis() < nextTime) { diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index d056352b36..13479799c7 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -131,9 +131,70 @@ int LoLEngine::olol_drawScene(EMCState *script) { return 1; } +int LoLEngine::olol_moveParty(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_moveParty(%p) (%d)", (const void *)script, stackPos(0)); + int mode = stackPos(0); + if (mode > 5 && mode < 10) + mode = (mode - 6 - _currentDirection) & 3; + + Button b; + memset(&b, 0, sizeof(Button)); + + switch (mode) { + case 0: + clickedUpArrow(&b); + break; + + case 1: + clickedRightArrow(&b); + break; + + case 2: + clickedDownArrow(&b); + break; + + case 3: + clickedLeftArrow(&b); + break; + + case 4: + clickedTurnLeftArrow(&b); + break; + + case 5: + clickedTurnRightArrow(&b); + break; + + case 10: + case 11: + case 12: + case 13: + mode = ABS(mode - 10 - _currentDirection); + if (mode > 2) + mode = (mode ^ 2) * -1; + + while (mode) { + if (mode > 0) { + clickedTurnRightArrow(&b); + mode--; + } else { + clickedTurnLeftArrow(&b); + mode++; + } + } + break; + + default: + break; + } + + return 1; +} + + int LoLEngine::olol_delay(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_delay(%p) (%d)", (const void *)script, stackPos(0)); - delay(stackPos(0) * _tickLength); + delay(stackPos(0) * _tickLength, false, true); return 1; } @@ -461,6 +522,20 @@ int LoLEngine::olol_getDirection(EMCState *script) { return _currentDirection; } +int LoLEngine::olol_characterSurpriseFeedback(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_characterSurpriseFeedback(%p)", (const void *)script); + for (int i = 0; i < 4; i++) { + if (!(_characters[i].flags & 1) || _characters[i].id >= 0) + continue; + int s = -_characters[i].id; + int sfx = (s == 1) ? 136 : ((s == 5) ? 50 : ((s == 8) ? 49 : ((s == 9) ? 48 : 0))); + if (sfx) + snd_playSoundEffect(sfx, -1); + return 1; + } + return 1; +} + int LoLEngine::olol_setMusicTrack(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setMusicTrack(%p) (%d)", (const void *)script, stackPos(0)); _curMusicTheme = stackPos(0); @@ -539,7 +614,7 @@ int LoLEngine::olol_stopBackgroundAnimation(EMCState *script) { int LoLEngine::olol_getGlobalScriptVar(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getGlobalScriptVar(%p) (%d)", (const void *)script, stackPos(0)); - assert(stackPos(0) < 16); + assert(stackPos(0) < 24); return _globalScriptVars[stackPos(0)]; } @@ -701,6 +776,8 @@ int LoLEngine::olol_copyRegion(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_copyRegion(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7)); _screen->copyRegion(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), Screen::CR_NO_P_CHECK); + if (!stackPos(7)) + _screen->updateScreen(); return 1; } @@ -765,7 +842,7 @@ int LoLEngine::olol_fadeClearSceneWindow(EMCState *script) { int LoLEngine::olol_fadeSequencePalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_fadeSequencePalette(%p)", (const void *)script); memcpy(_screen->getPalette(3) + 0x180, _screen->_currentPalette + 0x180, 0x180); - _screen->loadSpecialColours(_screen->getPalette(3)); + _screen->loadSpecialColors(_screen->getPalette(3)); _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; return 1; @@ -1171,6 +1248,13 @@ int LoLEngine::olol_playCharacterScriptChat(EMCState *script) { return playCharacterScriptChat(stackPos(0), stackPos(1), 1, getLangString(stackPos(2)), script, 0, 3); } +int LoLEngine::olol_playEnvironmentalSfx(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playEnvironmentalSfx(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + uint16 block = (stackPos(1) == -1) ? _currentBlock : stackPos(1); + snd_processEnvironmentalSoundEffect(stackPos(0), block); + return 1; +} + int LoLEngine::olol_update(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_update(%p)", (const void *)script); update(); @@ -1239,6 +1323,36 @@ int LoLEngine::olol_countBlockItems(EMCState *script) { return res; } +int LoLEngine::olol_characterSkillTest(EMCState *script){ + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_characterSkillTest(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + int skill = stackPos(0); + int n = countActiveCharacters(); + uint m = 0; + int c = 0; + + for (int i = 0; i < n ; i++) { + uint v = _characters[i].skillModifiers[skill] + _characters[i].skillLevels[skill] + 25; + if (v > m) { + m = v; + c = i; + } + } + + return (_rnd.getRandomNumberRng(1, 100) > m) ? -1 : c; +} + +int LoLEngine::olol_countActiveMonsters(EMCState *script){ + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_countActiveMonsters(%p)", (const void *)script); + int res = 0; + + for (int i = 0; i < 30; i++) { + if (_monsters[i].hitPoints > 0 && _monsters[i].mode != 13) + res++; + } + + return res; +} + int LoLEngine::olol_stopCharacterSpeech(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_stopCharacterSpeech(%p)", (const void *)script); snd_stopSpeech(1); @@ -1301,6 +1415,32 @@ int LoLEngine::olol_calcInflictableDamagePerItem(EMCState *script) { return calcInflictableDamagePerItem(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); } +int LoLEngine::olol_distanceAttack(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_distanceAttack(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8)); + + uint16 fX = stackPos(3); + uint16 fY = stackPos(4); + + if (!(stackPos(8) & 0x8000)) + fX = fY = 0x80; + + uint16 x = 0; + uint16 y = 0; + calcCoordinates(x, y, stackPos(2), fX, fY); + + if (launchObject(stackPos(0), stackPos(1), x, y, stackPos(5), stackPos(6) << 1, stackPos(7), stackPos(8), 0x3f)) + return 1; + + deleteItem(stackPos(1)); + return 0; +} + +int LoLEngine::olol_removeCharacterEffects(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_removeCharacterEffects(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + removeCharacterEffects(&_characters[stackPos(0)], stackPos(1), stackPos(2)); + return 1; +} + int LoLEngine::olol_objectLeavesLevel(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_objectLeavesLevel(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); int o = _levelBlockProperties[stackPos(0)].assignedObjects; @@ -1347,6 +1487,12 @@ int LoLEngine::olol_objectLeavesLevel(EMCState *script) { return res; } +int LoLEngine::olol_addSpellToScroll(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_addSpellToScroll(%p) (%d)", (const void *)script, stackPos(0)); + addSpellToScroll(stackPos(0), stackPos(1)); + return 1; +} + int LoLEngine::olol_playDialogueTalkText(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playDialogueTalkText(%p) (%d)", (const void *)script, stackPos(0)); int track = stackPos(0); @@ -1388,6 +1534,40 @@ int LoLEngine::olol_suspendMonster(EMCState *script) { return 1; } +int LoLEngine::olol_triggerEventOnMouseButtonRelease(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_triggerEventOnMouseButtonRelease(%p) (%d)", (const void *)script, stackPos(0)); + gui_notifyButtonListChanged(); + snd_characterSpeaking(); + + int f = checkInput(0); + removeInputTop(); + if (f == 0 || (f & 0x800)) + return 0; + + int evt = stackPos(0); + if (evt) { + gui_triggerEvent(evt); + _seqTrigger = 1; + } else { + removeInputTop(); + } + + return 1; +} + +int LoLEngine::olol_printWindowText(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_printWindowText(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + int dim = stackPos(0); + int flg = stackPos(1); + _screen->setScreenDim(dim); + if (flg & 1) + _txt->clearCurDim(); + if (flg & 3) + _txt->resetDimTextPositions(dim); + _txt->printDialogueText(dim, getLangString(stackPos(2)), script, 0, 3); + return 1; +} + int LoLEngine::olol_setUnkDoorVar(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setUnkDoorVar(%p) (%d)", (const void *)script, stackPos(0)); _emcDoorState = stackPos(0); @@ -1476,6 +1656,11 @@ int LoLEngine::olol_checkNeedSceneRestore(EMCState *script) { return _needSceneRestore; } +int LoLEngine::olol_castSpell(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_castSpell(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + return castSpell(stackPos(0), stackPos(1), stackPos(2)); +} + int LoLEngine::olol_disableControls(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_disableControls(%p) (%d)", (const void *)script, stackPos(0)); return gui_disableControls(stackPos(0)); @@ -1575,10 +1760,7 @@ int LoLEngine::tlol_processWsaFrame(const TIM *tim, const uint16 *param) { int w2 = (w1 * factor) / 100; int h2 = (h1 * factor) / 100; - anim->wsa->setDrawPage(2); - anim->wsa->setX(x1); - anim->wsa->setY(y1); - anim->wsa->displayFrame(frame, anim->wsaCopyParams & 0xF0FF, 0, 0); + anim->wsa->displayFrame(frame, 2, x1, y1, anim->wsaCopyParams & 0xF0FF, 0, 0); _screen->wsaFrameAnimationStep(x1, y1, x2, y2, w1, h1, w2, h2, 2, 8, 0); _screen->checkedPageUpdate(8, 4); _screen->updateScreen(); @@ -1638,7 +1820,7 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { case 1: tmp = _screen->getPalette(3); memcpy(tmp + 0x180, _screen->_currentPalette + 0x180, 0x180); - _screen->loadSpecialColours(tmp); + _screen->loadSpecialColors(tmp); _screen->fadePalette(tmp, 10); _screen->_fadeFlag = 0; break; @@ -1649,7 +1831,7 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { case 3: tmp = _screen->getPalette(3); - _screen->loadSpecialColours(tmp); + _screen->loadSpecialColors(tmp); _screen->fadePalette(tmp, 10); _screen->_fadeFlag = 0; break; @@ -1664,7 +1846,7 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { case 5: tmp = _screen->getPalette(3); - _screen->loadSpecialColours(tmp); + _screen->loadSpecialColors(tmp); _screen->fadePalette(_screen->getPalette(1), 10); _screen->_fadeFlag = 0; break; @@ -1679,6 +1861,8 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_copyRegion(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_copyRegion(%p, %p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void*)tim, (const void*)param, param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7]); _screen->copyRegion(param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7], Screen::CR_NO_P_CHECK); + if (!param[7]) + _screen->updateScreen(); return 1; } @@ -1691,8 +1875,8 @@ int LoLEngine::tlol_characterChat(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_drawScene(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_drawScene(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]); gui_drawScene(param[0]); - if (_sceneDrawPage2 != 2 && param[0] == 2) - _screen->copyRegion(112, 0, 112, 0, 176, 120, _sceneDrawPage2, 2, Screen::CR_NO_P_CHECK); + //if (_sceneDrawPage2 != 2 && param[0] == 2) + // _screen->copyRegion(112 << 3, 0, 112 << 3, 0, 176 << 3, 120, _sceneDrawPage2, 2, Screen::CR_NO_P_CHECK); return 1; } @@ -1774,7 +1958,7 @@ void LoLEngine::setupOpcodeTable() { Opcode(o1_getRand); // 0x04 - OpcodeUnImpl(); + Opcode(olol_moveParty); OpcodeUnImpl(); Opcode(olol_delay); Opcode(olol_setGameFlag); @@ -1811,7 +1995,7 @@ void LoLEngine::setupOpcodeTable() { // 0x1C Opcode(olol_getDirection); - OpcodeUnImpl(); + Opcode(olol_characterSurpriseFeedback); Opcode(olol_setMusicTrack); Opcode(olol_setSequenceButtons); @@ -1912,7 +2096,7 @@ void LoLEngine::setupOpcodeTable() { Opcode(olol_update); // 0x60 - OpcodeUnImpl(); + Opcode(olol_playEnvironmentalSfx); Opcode(olol_healCharacter); Opcode(olol_drawExitButton); Opcode(olol_loadSoundFile); @@ -1921,10 +2105,10 @@ void LoLEngine::setupOpcodeTable() { Opcode(olol_playMusicTrack); OpcodeUnImpl(); Opcode(olol_countBlockItems); - OpcodeUnImpl(); + Opcode(olol_characterSkillTest); // 0x68 - OpcodeUnImpl(); + Opcode(olol_countActiveMonsters); OpcodeUnImpl(); Opcode(olol_stopCharacterSpeech); Opcode(olol_setPaletteBrightness); @@ -1938,8 +2122,8 @@ void LoLEngine::setupOpcodeTable() { // 0x70 Opcode(olol_deleteLevelItem); Opcode(olol_calcInflictableDamagePerItem); - OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(olol_distanceAttack); + Opcode(olol_removeCharacterEffects); // 0x74 OpcodeUnImpl(); @@ -1948,7 +2132,7 @@ void LoLEngine::setupOpcodeTable() { OpcodeUnImpl(); // 0x78 - OpcodeUnImpl(); + Opcode(olol_addSpellToScroll); OpcodeUnImpl(); Opcode(olol_playDialogueTalkText); Opcode(olol_checkMonsterTypeHostility); @@ -1961,8 +2145,8 @@ void LoLEngine::setupOpcodeTable() { // 0x80 OpcodeUnImpl(); - OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(olol_triggerEventOnMouseButtonRelease); + Opcode(olol_printWindowText); OpcodeUnImpl(); // 0x84 @@ -2027,7 +2211,7 @@ void LoLEngine::setupOpcodeTable() { // 0xAC OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(olol_castSpell); OpcodeUnImpl(); OpcodeUnImpl(); diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 4165053c15..cae74ef82b 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -420,10 +420,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char screen()->updateScreen(); } - anim->wsa->setX(x); - anim->wsa->setY(y); - anim->wsa->setDrawPage(0); - anim->wsa->displayFrame(0, 0, 0, 0); + anim->wsa->displayFrame(0, 0, 0, 0, 0); } if (wsaFlags & 2) @@ -581,12 +578,9 @@ int TIMInterpreter::cmd_stopFunc(const uint16 *param) { int TIMInterpreter::cmd_wsaDisplayFrame(const uint16 *param) { Animation &anim = _animations[param[0]]; const int frame = param[1]; - - anim.wsa->setX(anim.x); - anim.wsa->setY(anim.y); - anim.wsa->setDrawPage((anim.wsaCopyParams & 0x4000) != 0 ? 2 : _drawPage2); - anim.wsa->displayFrame(frame, anim.wsaCopyParams & 0xF0FF, 0, 0); - if (!_drawPage2) + int page = (anim.wsaCopyParams & 0x4000) != 0 ? 2 : _drawPage2; + anim.wsa->displayFrame(frame, page, anim.x, anim.y, anim.wsaCopyParams & 0xF0FF, 0, 0); + if (!page) screen()->updateScreen(); return 1; } @@ -829,17 +823,11 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c _screen->fadeToBlack(10); } - if (wsaFlags & 7) { - _screen->hideMouse(); - anim->wsa->setDrawPage(0); - anim->wsa->setX(x); - anim->wsa->setY(y); - anim->wsa->displayFrame(0, 0); - _screen->showMouse(); - } + if (wsaFlags & 7) + anim->wsa->displayFrame(0, 0, x, y, 0); if (wsaFlags & 3) { - _screen->loadSpecialColours(_screen->getPalette(3)); + _screen->loadSpecialColors(_screen->getPalette(3)); _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; } @@ -938,12 +926,8 @@ void TIMInterpreter_LoL::startBackgroundAnimation(int animIndex, int part) { anim->curFrame = p->firstFrame; anim->cyclesCompleted = 0; - if (anim->wsa) { - anim->wsa->setX(anim->x); - anim->wsa->setY(anim->y); - anim->wsa->setDrawPage(0); - anim->wsa->displayFrame(anim->curFrame - 1, 0, 0); - } + if (anim->wsa) + anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0); } void TIMInterpreter_LoL::stopBackgroundAnimation(int animIndex) { @@ -1002,36 +986,26 @@ void TIMInterpreter_LoL::updateBackgroundAnimation(int animIndex) { anim->nextFrame += (anim->frameDelay * _vm->_tickLength); - anim->wsa->setX(anim->x); - anim->wsa->setY(anim->y); - anim->wsa->setDrawPage(0); - anim->wsa->displayFrame(anim->curFrame - 1, 0); + anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0); anim->nextFrame += _system->getMillis(); } void TIMInterpreter_LoL::playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) { Animation *anim = &_animations[animIndex]; - anim->wsa->setX(anim->x); - anim->wsa->setY(anim->y); int step = (lastFrame >= firstFrame) ? 1 : -1; for (int i = firstFrame; i != (lastFrame + step) ; i += step) { uint32 next = _system->getMillis() + delay * _vm->_tickLength; if (anim->wsaCopyParams & 0x4000) { _screen->copyRegion(112, 0, 112, 0, 176, 120, 6, 2); - anim->wsa->setDrawPage(2); - anim->wsa->displayFrame(i - 1, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_trueLightTable1, _vm->_trueLightTable2); + anim->wsa->displayFrame(i - 1, 2, anim->x, anim->y, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_trueLightTable1, _vm->_trueLightTable2); _screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0); _screen->updateScreen(); } else { - anim->wsa->setDrawPage(0); - anim->wsa->displayFrame(i - 1, 0); + anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0); _screen->updateScreen(); } - while ((int)(next - _system->getMillis()) > 0) { - _vm->updateInput(); - _vm->delay(_vm->_tickLength); - } + _vm->delayUntil(next); } } diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp index 3391c51ab7..cf8476eceb 100644 --- a/engines/kyra/seqplayer.cpp +++ b/engines/kyra/seqplayer.cpp @@ -132,7 +132,6 @@ void SeqPlayer::s1_wsaOpen() { _seqWsaCurDecodePage = _seqMovies[wsaObj].page = (offscreenDecode == 0) ? 0 : 3; if (!_seqMovies[wsaObj].movie) _seqMovies[wsaObj].movie = _vm->createWSAMovie(); - _seqMovies[wsaObj].movie->setDrawPage(_seqMovies[wsaObj].page); _seqMovies[wsaObj].movie->open(_vm->seqWSATable()[wsaObj], offscreenDecode, 0); _seqMovies[wsaObj].frame = 0; _seqMovies[wsaObj].numFrames = _seqMovies[wsaObj].movie->frames() - 1; @@ -152,9 +151,7 @@ void SeqPlayer::s1_wsaPlayFrame() { _seqMovies[wsaObj].pos.x = READ_LE_UINT16(_seqData); _seqData += 2; _seqMovies[wsaObj].pos.y = *_seqData++; assert(_seqMovies[wsaObj].movie); - _seqMovies[wsaObj].movie->setX(_seqMovies[wsaObj].pos.x); - _seqMovies[wsaObj].movie->setY(_seqMovies[wsaObj].pos.y); - _seqMovies[wsaObj].movie->displayFrame(frame); + _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y); _seqMovies[wsaObj].frame = frame; } @@ -166,7 +163,7 @@ void SeqPlayer::s1_wsaPlayNextFrame() { frame = 0; _seqMovies[wsaObj].frame = 0; } - _seqMovies[wsaObj].movie->displayFrame(frame); + _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y); } void SeqPlayer::s1_wsaPlayPrevFrame() { @@ -177,7 +174,7 @@ void SeqPlayer::s1_wsaPlayPrevFrame() { frame = _seqMovies[wsaObj].numFrames; _seqMovies[wsaObj].frame = frame; } else { - _seqMovies[wsaObj].movie->displayFrame(frame); + _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y); } } diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 63239ccf63..3ed022a47a 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -103,10 +103,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _seqWsa->close(); _seqWsa->open(cseq.wsaFile, 0, _screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0)); - _seqWsa->setX(cseq.xPos); - _seqWsa->setY(cseq.yPos); - _seqWsa->setDrawPage(2); - _seqWsa->displayFrame(0, 0); + _seqWsa->displayFrame(0, 2, cseq.xPos, cseq.yPos, 0); } if (cseq.flags & 4) { @@ -178,10 +175,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { if (_seqWsa) { int f = _seqWsaCurrentFrame % _seqWsa->frames(); - _seqWsa->setX(cseq.xPos); - _seqWsa->setY(cseq.yPos); - _seqWsa->setDrawPage(2); - _seqWsa->displayFrame(f, 0); + _seqWsa->displayFrame(f, 2, cseq.xPos, cseq.yPos, 0); } _screen->copyPage(2, 12); @@ -2245,9 +2239,6 @@ void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) { _activeWSA[wsaNum].endFrame = s.endFrame; _activeWSA[wsaNum].startFrame = _activeWSA[wsaNum].currentFrame = s.startframe; _activeWSA[wsaNum].frameDelay = s.frameDelay; - _activeWSA[wsaNum].movie->setX(0); - _activeWSA[wsaNum].movie->setY(0); - _activeWSA[wsaNum].movie->setDrawPage(_screen->_curPage); _activeWSA[wsaNum].callback = _callbackN[seqNum]; _activeWSA[wsaNum].control = s.wsaControl; @@ -2274,61 +2265,40 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { switch (command) { case 0: - _activeWSA[wsaNum].movie->setDrawPage(8); xa = -_activeWSA[wsaNum].movie->xAdd(); ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->setX(xa); - _activeWSA[wsaNum].movie->setY(ya); - _activeWSA[wsaNum].movie->displayFrame(0, 0); - _activeWSA[wsaNum].movie->setX(0); - _activeWSA[wsaNum].movie->setY(0); + _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0); seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 2); break; case 1: - _activeWSA[wsaNum].movie->setDrawPage(8); xa = -_activeWSA[wsaNum].movie->xAdd(); ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->setX(xa); - _activeWSA[wsaNum].movie->setY(ya); - _activeWSA[wsaNum].movie->displayFrame(0, 0); - _activeWSA[wsaNum].movie->setX(0); - _activeWSA[wsaNum].movie->setY(0); + _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0); seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 1); break; case 2: seq_waitForTextsTimeout(); - _activeWSA[wsaNum].movie->setDrawPage(8); xa = -_activeWSA[wsaNum].movie->xAdd(); ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->setX(xa); - _activeWSA[wsaNum].movie->setY(ya); - _activeWSA[wsaNum].movie->displayFrame(0x15, 0); - _activeWSA[wsaNum].movie->setX(0); - _activeWSA[wsaNum].movie->setY(0); + _activeWSA[wsaNum].movie->displayFrame(0x15, 8, xa, ya, 0); seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 0, 2); break; case 3: _screen->copyPage(2, 10); - _activeWSA[wsaNum].movie->setDrawPage(2); - _activeWSA[wsaNum].movie->setX(0); - _activeWSA[wsaNum].movie->setY(0); - _activeWSA[wsaNum].movie->displayFrame(0, 0); + _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0); _screen->copyPage(2, 12); seq_cmpFadeFrame("scene2.cmp"); break; case 4: _screen->copyPage(2, 10); - _activeWSA[wsaNum].movie->setDrawPage(2); - _activeWSA[wsaNum].movie->setX(0); - _activeWSA[wsaNum].movie->setY(0); - _activeWSA[wsaNum].movie->displayFrame(0, 0); + _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0); _screen->copyPage(2, 12); seq_cmpFadeFrame("scene3.cmp"); break; @@ -2414,15 +2384,11 @@ bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) { } if (_activeWSA[wsaNum].movie) { - _activeWSA[wsaNum].movie->setDrawPage(2); - _activeWSA[wsaNum].movie->setX(_activeWSA[wsaNum].x); - _activeWSA[wsaNum].movie->setY(_activeWSA[wsaNum].y); - if (_activeWSA[wsaNum].flags & 0x20) { - _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 0x4000); + _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000); _activeWSA[wsaNum].frameDelay = _activeWSA[wsaNum].control[currentFrame].delay; } else { - _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 0x4000); + _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000); } } @@ -2532,12 +2498,8 @@ void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, i curframe = firstframe; _seqWsaChatFrameTimeout = _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; - if (wsa) { - wsa->setDrawPage(2); - wsa->setX(wsaXpos); - wsa->setY(wsaYpos); - wsa->displayFrame(curframe % wsa->frames(), 0); - } + if (wsa) + wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0); _screen->copyPage(2, 12); @@ -2794,24 +2756,21 @@ void KyraEngine_HoF::seq_showStarcraftLogo() { return; } _screen->hideMouse(); - ci->setX(0); - ci->setY(0); - ci->setDrawPage(2); - ci->displayFrame(0, 0); + ci->displayFrame(0, 2, 0, 0, 0); _screen->copyPage(2, 0); _screen->fadeFromBlack(); for (int i = 1; i < endframe; i++) { _seqEndTime = _system->getMillis() + 50; if (skipFlag()) break; - ci->displayFrame(i, 0); + ci->displayFrame(i, 2, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); delay(_seqEndTime - _system->getMillis()); } if (!skipFlag()) { _seqEndTime = _system->getMillis() + 50; - ci->displayFrame(0, 0); + ci->displayFrame(0, 2, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); delay(_seqEndTime - _system->getMillis()); @@ -2943,16 +2902,12 @@ void KyraEngine_HoF::seq_makeBookAppear() { _invWsa.running = false; snd_playSoundEffect(0xAF); - _invWsa.wsa->setX(0); - _invWsa.wsa->setY(0); - _invWsa.wsa->setDrawPage(_invWsa.page); - while (true) { _invWsa.timer = _system->getMillis() + _invWsa.delay * _tickLength; _screen->copyBlockToPage(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect); - _invWsa.wsa->displayFrame(_invWsa.curFrame, 0x4000, 0, 0); + _invWsa.wsa->displayFrame(_invWsa.curFrame, _invWsa.page, 0, 0, 0x4000, 0, 0); if (_invWsa.page) _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, _invWsa.page, 0, Screen::CR_NO_P_CHECK); diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index 6f08fd71f2..643d8a1d05 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -984,8 +984,6 @@ int KyraEngine_LoK::seq_playEnd() { _finalA = new WSAMovie_v1(this); assert(_finalA); _finalA->open("finald.wsa", 1, 0); - _finalA->setX(8); _finalA->setY(8); - _finalA->setDrawPage(0); delayUntil(nextTime); snd_playSoundEffect(0x40); for (int i = 0; i < 22; ++i) { @@ -995,7 +993,7 @@ int KyraEngine_LoK::seq_playEnd() { else if (i == 20) snd_playSoundEffect(0x0E); nextTime = _system->getMillis() + 8 * _tickLength; - _finalA->displayFrame(i); + _finalA->displayFrame(i, 0, 8, 8); _screen->updateScreen(); } delete _finalA; @@ -1232,10 +1230,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 2: if (_system->getMillis() >= timer2) { - _finalA->setX(8); - _finalA->setY(46); - _finalA->setDrawPage(0); - _finalA->displayFrame(frame); + _finalA->displayFrame(frame, 0, 8, 46); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1250,10 +1245,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { if (_system->getMillis() < timer1) { if (_system->getMillis() >= timer2) { frame = _rnd.getRandomNumberRng(14, 17); - _finalA->setX(8); - _finalA->setY(46); - _finalA->setDrawPage(0); - _finalA->displayFrame(frame); + _finalA->displayFrame(frame, 0, 8, 46); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; } @@ -1265,10 +1257,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 4: if (_system->getMillis() >= timer2) { - _finalA->setX(8); - _finalA->setY(46); - _finalA->setDrawPage(0); - _finalA->displayFrame(frame); + _finalA->displayFrame(frame, 0, 8, 46); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1282,10 +1271,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 5: if (_system->getMillis() >= timer2) { - _finalA->setX(8); - _finalA->setY(46); - _finalA->setDrawPage(0); - _finalA->displayFrame(frame); + _finalA->displayFrame(frame, 0, 8, 46); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1299,10 +1285,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 6: if (_unkEndSeqVar4) { if (frame <= 33 && _system->getMillis() >= timer2) { - _finalA->setX(8); - _finalA->setY(46); - _finalA->setDrawPage(0); - _finalA->displayFrame(frame); + _finalA->displayFrame(frame, 0, 8, 46); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1327,10 +1310,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 8: if (_system->getMillis() >= timer2) { - _finalA->setX(8); - _finalA->setY(46); - _finalA->setDrawPage(0); - _finalA->displayFrame(frame); + _finalA->displayFrame(frame, 0, 8, 46); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1345,12 +1325,9 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 9: snd_playSoundEffect(12); snd_playSoundEffect(12); - _finalC->setX(16); - _finalC->setY(50); - _finalC->setDrawPage(0); for (int i = 0; i < 18; ++i) { timer2 = _system->getMillis() + 4 * _tickLength; - _finalC->displayFrame(i); + _finalC->displayFrame(i, 0, 16, 50); _screen->updateScreen(); delayUntil(timer2); } @@ -1554,19 +1531,16 @@ int KyraEngine_LoK::handleBeadState() { if (beadState2.dstX == 290) { _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); uint32 nextRun = 0; - _finalB->setX(224); - _finalB->setY(8); - _finalB->setDrawPage(0); for (int i = 0; i < 8; ++i) { nextRun = _system->getMillis() + _tickLength; - _finalB->displayFrame(i); + _finalB->displayFrame(i, 0, 224, 8); _screen->updateScreen(); delayUntil(nextRun); } snd_playSoundEffect(0x0D); for (int i = 7; i >= 0; --i) { nextRun = _system->getMillis() + _tickLength; - _finalB->displayFrame(i); + _finalB->displayFrame(i, 0, 224, 8); _screen->updateScreen(); delayUntil(nextRun); } diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index 720e8fdf47..6375b614fe 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -213,10 +213,8 @@ int LoLEngine::chooseCharacter() { if (!_chargenWSA->open("CHARGEN.WSA", 1, 0)) error("Couldn't load CHARGEN.WSA"); - _chargenWSA->setX(113); - _chargenWSA->setY(0); - _chargenWSA->setDrawPage(2); - _chargenWSA->displayFrame(0, 0, 0, 0); + + _chargenWSA->displayFrame(0, 2, 113, 0, 0, 0, 0); _screen->setFont(Screen::FID_9_FNT); _screen->_curPage = 2; @@ -305,15 +303,11 @@ void LoLEngine::kingSelectionIntro() { _sound->voicePlay("KING01"); - _chargenWSA->setX(113); - _chargenWSA->setY(0); - _chargenWSA->setDrawPage(0); - int index = 4; - while (_sound->voiceIsPlaying("KING01") && _charSelection == -1 && !shouldQuit() && !skipFlag()) { + while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying("KING01"))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) { index = MAX(index, 4); - _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 0, 0); + _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0); _screen->copyRegion(_selectionPosTable[_selectionChar1IdxTable[index]*2+0], _selectionPosTable[_selectionChar1IdxTable[index]*2+1], _charPreviews[0].x, _charPreviews[0].y, 32, 32, 4, 0); _screen->copyRegion(_selectionPosTable[_selectionChar2IdxTable[index]*2+0], _selectionPosTable[_selectionChar2IdxTable[index]*2+1], _charPreviews[1].x, _charPreviews[1].y, 32, 32, 4, 0); _screen->copyRegion(_selectionPosTable[_selectionChar3IdxTable[index]*2+0], _selectionPosTable[_selectionChar3IdxTable[index]*2+1], _charPreviews[2].x, _charPreviews[2].y, 32, 32, 4, 0); @@ -326,12 +320,15 @@ void LoLEngine::kingSelectionIntro() { _system->delayMillis(10); } - index = (index + 1) % 22; + if (_speechFlag) + index = (index + 1) % 22; + else if (++index >= 27) + break; } resetSkipFlag(); - _chargenWSA->displayFrame(0x10, 0, 0, 0); + _chargenWSA->displayFrame(0x10, 0,113, 0, 0, 0, 0); _screen->updateScreen(); _sound->voiceStop("KING01"); } @@ -347,13 +344,9 @@ void LoLEngine::kingSelectionReminder() { _sound->voicePlay("KING02"); - _chargenWSA->setX(113); - _chargenWSA->setY(0); - _chargenWSA->setDrawPage(0); - int index = 0; - while (_sound->voiceIsPlaying("KING02") && _charSelection == -1 && !shouldQuit() && index < 15) { - _chargenWSA->displayFrame(_chargenFrameTable[index+9], 0, 0, 0); + while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying("KING02"))) && _charSelection == -1 && !shouldQuit() && index < 15) { + _chargenWSA->displayFrame(_chargenFrameTable[index+9], 0, 113, 0, 0, 0, 0); _screen->copyRegion(_selectionPosTable[_reminderChar1IdxTable[index]*2+0], _selectionPosTable[_reminderChar1IdxTable[index]*2+1], _charPreviews[0].x, _charPreviews[0].y, 32, 32, 4, 0); _screen->copyRegion(_selectionPosTable[_reminderChar2IdxTable[index]*2+0], _selectionPosTable[_reminderChar2IdxTable[index]*2+1], _charPreviews[1].x, _charPreviews[1].y, 32, 32, 4, 0); _screen->copyRegion(_selectionPosTable[_reminderChar3IdxTable[index]*2+0], _selectionPosTable[_reminderChar3IdxTable[index]*2+1], _charPreviews[2].x, _charPreviews[2].y, 32, 32, 4, 0); @@ -366,7 +359,10 @@ void LoLEngine::kingSelectionReminder() { _system->delayMillis(10); } - index = (index + 1) % 22; + if (_speechFlag) + index = (index + 1) % 22; + else if (++index >= 27) + break; } _sound->voiceStop("KING02"); @@ -377,15 +373,11 @@ void LoLEngine::kingSelectionOutro() { _sound->voicePlay("KING03"); - _chargenWSA->setX(113); - _chargenWSA->setY(0); - _chargenWSA->setDrawPage(0); - int index = 0; - while (_sound->voiceIsPlaying("KING03") && !shouldQuit() && !skipFlag()) { + while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying("KING03"))) && !shouldQuit() && !skipFlag()) { index = MAX(index, 4); - _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 0, 0); + _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0); _screen->updateScreen(); uint32 waitEnd = _system->getMillis() + 8 * _tickLength; @@ -394,12 +386,15 @@ void LoLEngine::kingSelectionOutro() { _system->delayMillis(10); } - index = (index + 1) % 22; + if (_speechFlag) + index = (index + 1) % 22; + else if (++index >= 27) + break; } resetSkipFlag(); - _chargenWSA->displayFrame(0x10, 0, 0, 0); + _chargenWSA->displayFrame(0x10, 0, 113, 0, 0, 0, 0); _screen->updateScreen(); _sound->voiceStop("KING03"); } @@ -598,10 +593,7 @@ void LoLEngine::showStarcraftLogo() { return; } _screen->hideMouse(); - ci->setX(32); - ci->setY(80); - ci->setDrawPage(2); - ci->displayFrame(0, 0); + ci->displayFrame(0, 2, 32, 80, 0); _screen->copyPage(2, 0); _screen->fadeFromBlack(); int inputFlag = 0; @@ -609,7 +601,7 @@ void LoLEngine::showStarcraftLogo() { inputFlag = checkInput(0) & 0xff; if (shouldQuit() || inputFlag) break; - ci->displayFrame(i, 0); + ci->displayFrame(i, 2, 32, 80, 0); _screen->copyPage(2, 0); _screen->updateScreen(); delay(4 * _tickLength); diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 4aacd40658..14e63c81a6 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -188,6 +188,13 @@ bool Sound::voiceIsPlaying(const char *file) { return res; } +bool Sound::allVoiceChannelsPlaying() { + for (int i = 0; i < kNumChannelHandles; ++i) + if (!_mixer->isSoundHandleActive(_soundChannels[i].channelHandle)) + return false; + return true; +} + uint32 Sound::voicePlayedTime(const char *file) { if (!file) return 0; diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 565e02e917..52334806ad 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -213,6 +213,13 @@ public: bool voiceIsPlaying(const char *file = 0); /** + * Checks if all voice handles are used. + * + * @return false when a handle is free, else true + */ + bool allVoiceChannelsPlaying(); + + /** * Checks how long a voice has been playing * * @return time in milliseconds diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 7f43f8e5b1..de81b667f4 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -2714,7 +2714,7 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { finOut += _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0]; } - finOut /= 4; + finOut >>= 1; buffer[i << 1] += finOut; buffer[(i << 1) + 1] += finOut; } @@ -2887,7 +2887,7 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) { finOut += _rhChan[ii].out; } - finOut *= 3; + finOut <<= 2; buffer[i << 1] += finOut; buffer[(i << 1) + 1] += finOut; @@ -3381,7 +3381,7 @@ void TownsPC98_OpnCore::nextTick(int32 *buffer, uint32 bufferSize) { break; }; - int32 finOut = ((output * 3) / ((_numChan + _numSSG - 3) / 3)); + int32 finOut = ((output << 2) / ((_numChan + _numSSG - 3) / 3)); if (_chanInternal[i].enableLeft) *leftSample += finOut; diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index daff86545c..acef7cd426 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -372,7 +372,7 @@ void LoLEngine::assignMonsterToBlock(uint16 *assignedBlockObjects, int id) { } int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, int testFlag, int wallFlag) { - _monsterLastWalkDirection = 0; + _objectLastDirection = 0; int x2 = 0; int y2 = 0; int xOffs = 0; @@ -390,7 +390,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, in if (x & 0x80) { if (((x & 0xff) + objectWidth) & 0xff00) { xOffs = 1; - _monsterLastWalkDirection = 2; + _objectLastDirection = 2; x2 = x + objectWidth; r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y), x, y, objectWidth, testFlag, wallFlag); @@ -406,7 +406,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, in } else { if (((x & 0xff) - objectWidth) & 0xff00) { xOffs = -1; - _monsterLastWalkDirection = 6; + _objectLastDirection = 6; x2 = x - objectWidth; r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y), x, y, objectWidth, testFlag, wallFlag); @@ -424,7 +424,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, in if (y & 0x80) { if (((y & 0xff) + objectWidth) & 0xff00) { yOffs = 1; - _monsterLastWalkDirection = 4; + _objectLastDirection = 4; y2 = y + objectWidth; r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y2), x, y, objectWidth, testFlag, wallFlag); @@ -434,13 +434,14 @@ int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, in r = checkBlockOccupiedByParty(x, y + yOffs, testFlag); if (r) return 4; + flag &= 1; } else { flag = 0; } } else { if (((y & 0xff) - objectWidth) & 0xff00) { yOffs = -1; - _monsterLastWalkDirection = 0; + _objectLastDirection = 0; y2 = y - objectWidth; r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y2), x, y, objectWidth, testFlag, wallFlag); @@ -450,6 +451,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int objectWidth, in r = checkBlockOccupiedByParty(x, y + yOffs, testFlag); if (r) return 4; + flag &= 1; } else { flag = 0; } @@ -517,11 +519,11 @@ int LoLEngine::calcMonsterSkillLevel(int id, int a) { return (r- (r >> 1)); } -bool LoLEngine::checkBlockOccupiedByParty(int x, int y, int testFlag) { +int LoLEngine::checkBlockOccupiedByParty(int x, int y, int testFlag) { if ((testFlag & 4) && (_currentBlock == calcBlockIndex(x, y))) - return true; + return 1; - return false; + return 0; } void LoLEngine::drawBlockObjects(int blockArrayIndex) { @@ -1191,8 +1193,8 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) { if (walkMonsterCheckDest(monster->x, monster->y, monster, 4) != 1) return; - _monsterLastWalkDirection ^= 4; - setMonsterDirection(monster, _monsterLastWalkDirection); + _objectLastDirection ^= 4; + setMonsterDirection(monster, _objectLastDirection); } else { setMonsterDirection(monster, s); if (monster->numDistAttacks) { @@ -1208,7 +1210,7 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) { int fx = 0; int fy = 0; - getNextStepCoords(monster->x, monster->y, fx, fy, (s == -1) ? _monsterLastWalkDirection : s); + getNextStepCoords(monster->x, monster->y, fx, fy, (s == -1) ? _objectLastDirection : s); placeMonster(monster, fx, fy); } diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 02c3c4316e..921402b582 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -44,7 +44,7 @@ namespace Kyra { -#define RESFILE_VERSION 45 +#define RESFILE_VERSION 46 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -449,7 +449,9 @@ bool StaticResource::init() { { lolMapStringId, kLolRawDataBe16, "MAPSTRID.LST" }, //{ lolMapPal, kRawData, "MAP.PAL" }, - { lolHealShapeFrames, kRawData, "MHEAL.SHP" }, + { lolSpellbookAnim, kRawData, "MBOOKA.DEF" }, + { lolSpellbookCoords, kRawData, "MBOOKC.DEF" }, + { lolHealShapeFrames, kRawData, "MHEAL.SHP" }, { 0, 0, 0 } }; @@ -1047,8 +1049,12 @@ bool StaticResource::loadSpellData(const char *filename, void *&ptr, int &size) t->spellNameCode = file->readUint16LE(); for (int ii = 0; ii < 4; ii++) t->mpRequired[ii] = file->readUint16LE(); - for (int ii = 0; ii < 8; ii++) - t->unkArr[ii] = file->readUint16LE(); + t->field_a = file->readUint16LE(); + t->field_c = file->readUint16LE(); + for (int ii = 0; ii < 4; ii++) + t->hpRequired[ii] = file->readUint16LE(); + t->field_16 = file->readUint16LE(); + t->field_18 = file->readUint16LE(); t->flags = file->readUint16LE(); }; @@ -1849,6 +1855,8 @@ void LoLEngine::initStaticResource() { memcpy (_mapCursorOverlay, tmp, tmpSize); _staticres->unloadId(lolMapCursorOvl); + _updateSpellBookCoords = _staticres->loadRawData(lolSpellbookCoords, _updateSpellBookCoordsSize); + _updateSpellBookAnimData = _staticres->loadRawData(lolSpellbookAnim, _updateSpellBookAnimDataSize); _healShapeFrames = _staticres->loadRawData(lolHealShapeFrames, _healShapeFramesSize); // assign music data @@ -1962,11 +1970,11 @@ void LoLEngine::assignButtonCallback(Button *button, int index) { cb(clickedScroll), cb(clickedScroll), cb(clickedScroll), - cb(clickedUnk23), - cb(clickedUnk23), - cb(clickedUnk23), - cb(clickedUnk23), - cb(clickedUnk24), + cb(clickedSpellTargetCharacter), + cb(clickedSpellTargetCharacter), + cb(clickedSpellTargetCharacter), + cb(clickedSpellTargetCharacter), + cb(clickedSpellTargetScene), cb(clickedSceneThrowItem), cb(clickedSceneThrowItem), cb(clickedOptions), @@ -2950,6 +2958,11 @@ const ScreenDim Screen_LoL::_screenDimTable256C[] = { { 0x07, 0x19, 0x1A, 0x97, 0x00, 0x00, 0x00, 0x00 }, { 0x03, 0x1E, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 }, { 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0E, 0x00, 0x16, 0x78, 0xFE, 0x01, 0x00, 0x00 }, + { 0x0D, 0xA2, 0x18, 0x0C, 0xFE, 0x01, 0x00, 0x00 }, + { 0x0F, 0x06, 0x14, 0x6E, 0x01, 0x00, 0x00, 0x00 }, + { 0x1A, 0xBE, 0x0A, 0x07, 0xFE, 0x01, 0x00, 0x00 }, { 0x0B, 0x8C, 0x10, 0x33, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (5 entries, CD version only) { 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 } // Main menu box (3 entries, floppy version only) }; @@ -2967,6 +2980,11 @@ const ScreenDim Screen_LoL::_screenDimTable16C[] = { { 0x07, 0x19, 0x1A, 0x97, 0x00, 0x00, 0x00, 0x00 }, { 0x03, 0x1E, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 }, { 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0E, 0x00, 0x16, 0x78, 0x33, 0x44, 0x00, 0x00 }, + { 0x0D, 0xA2, 0x18, 0x0C, 0x33, 0x44, 0x00, 0x00 }, + { 0x0F, 0x06, 0x14, 0x6E, 0x44, 0x00, 0x00, 0x00 }, + { 0x1A, 0xBE, 0x0A, 0x07, 0x33, 0x44, 0x00, 0x00 }, { 0x0B, 0x8C, 0x10, 0x33, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (5 entries, not used here) { 0x0B, 0x8C, 0x10, 0x23, 0x33, 0x44, 0x00, 0x00 } // Main menu box (3 entries) }; @@ -2986,7 +3004,7 @@ const LoLEngine::CharacterPrev LoLEngine::_charPreviews[] = { { "Conrad", 0x10F, 0x7F, { 0x0A, 0x0C, 0x0A } } }; -const uint8 LoLEngine::_chargenFrameTable[] = { +const uint8 LoLEngine::_chargenFrameTableTalkie[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x01, 0x02, 0x03, @@ -2995,6 +3013,12 @@ const uint8 LoLEngine::_chargenFrameTable[] = { 0x0E, 0x0F, 0x10, 0x11, 0x12 }; +const uint8 LoLEngine::_chargenFrameTableFloppy[] = { + 0, 1, 2, 3, 4, 5, 4, 3, 2, + 1, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + const uint16 LoLEngine::_selectionPosTable[] = { 0x6F, 0x00, 0x8F, 0x00, 0xAF, 0x00, 0xCF, 0x00, 0xEF, 0x00, 0x6F, 0x20, 0x8F, 0x20, 0xAF, 0x20, diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp index 9616596710..1091fd3a4c 100644 --- a/engines/kyra/text_lol.cpp +++ b/engines/kyra/text_lol.cpp @@ -33,7 +33,7 @@ namespace Kyra { TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm), _screen(screen), - _scriptParameter(0), _animWidth(0), _animColour1(0), _animColour2(0), _animFlag(true), _lineCount(0), + _scriptParameter(0), _animWidth(0), _animColor1(0), _animColor2(0), _animFlag(true), _lineCount(0), _printFlag(false), _lineWidth(0), _numCharsTotal(0), _numCharsLeft(0), _numCharsPrinted(0) { memset(_stringParameters, 0, 15 * sizeof(char*)); @@ -102,7 +102,7 @@ void TextDisplayer_LoL::expandField() { if (_vm->textEnabled()) { _vm->_fadeText = false; - _vm->_textColourFlag = 0; + _vm->_textColorFlag = 0; _vm->_timer->disable(11); _screen->setScreenDim(clearDim(3)); _screen->copyRegionToBuffer(3, 0, 0, 320, 10, tmp); @@ -146,13 +146,13 @@ void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, ui if (str) { _animString = str; _animWidth = x; - _animColour1 = col1; - _animColour2 = col2; + _animColor1 = col1; + _animColor2 = col2; } else { _animString = defaultStr; _animWidth = 7; - _animColour1 = 0; - _animColour2 = 0; + _animColor1 = 0; + _animColor2 = 0; } } @@ -163,17 +163,21 @@ void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script, if (_vm->_updateFlags & 2) { oldDim = clearDim(4); _textDimData[4].color1 = 254; + _textDimData[4].color2 = _screen->_curDim->unkA; } else { oldDim = clearDim(3); _textDimData[3].color1 = 192; - _screen->copyColour(192, 254); + _textDimData[3].color2 = _screen->_curDim->unkA; + _screen->copyColor(192, 254); _vm->enableTimer(11); - _vm->_textColourFlag = 0; + _vm->_textColorFlag = 0; _vm->_fadeText = false; } } else { - oldDim = clearDim(dim); + oldDim = _screen->curDimIndex(); + _screen->setScreenDim(dim); _textDimData[dim].color1 = 254; + _textDimData[dim].color2 = _screen->_curDim->unkA; } int cp = _screen->setCurPage(0); @@ -190,15 +194,15 @@ void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script, _vm->_fadeText = false; } -void TextDisplayer_LoL::printMessage(uint16 type, char *str, ...) { - static uint8 textColours[] = { 0xfe, 0xa2, 0x84, 0x97, 0x9F }; +void TextDisplayer_LoL::printMessage(uint16 type, const char *str, ...) { + static uint8 textColors[] = { 0xfe, 0xa2, 0x84, 0x97, 0x9F }; static uint8 soundEffect[] = { 0x0B, 0x00, 0x2B, 0x1B, 0x00 }; if (type & 4) type ^= 4; else _vm->updatePortraits(); - uint16 col = textColours[type & 0x7fff]; + uint16 col = textColors[type & 0x7fff]; int od = _screen->curDimIndex(); @@ -207,7 +211,7 @@ void TextDisplayer_LoL::printMessage(uint16 type, char *str, ...) { _textDimData[4].color1 = col; } else { clearDim(3); - _screen->copyColour(192, col); + _screen->copyColor(192, col); _textDimData[3].color1 = 192; _vm->enableTimer(11); } @@ -228,7 +232,7 @@ void TextDisplayer_LoL::printMessage(uint16 type, char *str, ...) { _vm->sound()->playSoundEffect(soundEffect[type]); } - _vm->_textColourFlag = type & 0x7fff; + _vm->_textColorFlag = type & 0x7fff; _vm->_fadeText = false; } diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h index 776965117e..157e5a5852 100644 --- a/engines/kyra/text_lol.h +++ b/engines/kyra/text_lol.h @@ -50,7 +50,7 @@ public: void resetDimTextPositions(int dim); void printDialogueText(int dim, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex); - void printMessage(uint16 type, char *str, ...); + void printMessage(uint16 type, const char *str, ...); int16 _scriptParameter; @@ -82,8 +82,8 @@ private: const char *_animString; int16 _animWidth; - uint8 _animColour1; - uint8 _animColour2; + uint8 _animColor1; + uint8 _animColor2; bool _animFlag; bool _printFlag; diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp index 57bf717906..220208e313 100644 --- a/engines/kyra/text_mr.cpp +++ b/engines/kyra/text_mr.cpp @@ -603,12 +603,8 @@ void KyraEngine_MR::albumChatWaitToFinish() { if (frame > 22) frame = 13; - _album.wsa->setX(-100); - _album.wsa->setY(90); - _album.wsa->setDrawPage(2); - albumRestoreRect(); - _album.wsa->displayFrame(frame, 0x4000); + _album.wsa->displayFrame(frame, 2, -100, 90, 0x4000); albumUpdateRect(); nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength; diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp index 79bb8d1c2d..05e8e75144 100644 --- a/engines/kyra/timer_lol.cpp +++ b/engines/kyra/timer_lol.cpp @@ -53,7 +53,7 @@ void LoLEngine::setupTimers() { void LoLEngine::enableTimer(int id) { _timer->enable(id); - _timer->setNextRun(id, _system->getMillis() + _timer->getDelay(id) * _tickLength); + _timer->setCountdown(id, _timer->getDelay(id)); } void LoLEngine::enableSysTimer(int sysTimer) { @@ -249,7 +249,7 @@ void LoLEngine::timerUpdatePortraitAnimations(int skipUpdate) { } void LoLEngine::timerUpdateLampState(int timerNum) { - if ((_gameFlags[15] & 0x800) && (_gameFlags[15] & 0x400) && _lampOilStatus) + if ((_gameFlags[15] & 0x800) && (_gameFlags[15] & 0x400) && _lampOilStatus > 0) _lampOilStatus--; } diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp index 50d17659a4..97f31e80ae 100644 --- a/engines/kyra/wsamovie.cpp +++ b/engines/kyra/wsamovie.cpp @@ -134,11 +134,15 @@ void WSAMovie_v1::close() { } } -void WSAMovie_v1::displayFrame(int frameNum, ...) { - debugC(9, kDebugLevelMovie, "WSAMovie_v1::displayFrame(%d, ...)", frameNum); +void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, ...) { + debugC(9, kDebugLevelMovie, "WSAMovie_v1::displayFrame(%d, %d, %d, %d, ...)", frameNum, pageNum, x, y); if (frameNum >= _numFrames || !_opened) return; + _x = x; + _y = y; + _drawPage = pageNum; + uint8 *dst; if (_flags & WF_OFFSCREEN_DECODE) dst = _offscreenBuffer; @@ -236,11 +240,15 @@ void WSAMovieAmiga::close() { WSAMovie_v1::close(); } -void WSAMovieAmiga::displayFrame(int frameNum, ...) { - debugC(9, kDebugLevelMovie, "WSAMovieAmiga::displayFrame(%d)", frameNum); +void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) { + debugC(9, kDebugLevelMovie, "WSAMovieAmiga::displayFrame(%d, %d, %d, %d,...)", frameNum, pageNum, x, y); if (frameNum >= _numFrames || frameNum < 0 || !_opened) return; + _x = x; + _y = y; + _drawPage = pageNum; + uint8 *dst; dst = _buffer; memset(_buffer, 0, _width*_height); @@ -415,16 +423,26 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { _flags |= WF_NO_FIRST_FRAME; } - for (int i = 1; i < _numFrames + 2; ++i) { + for (int i = 1; i < _numFrames; ++i) { _frameOffsTable[i] = READ_LE_UINT32(wsaData) - frameDataOffs; wsaData += 4; } + _frameOffsTable[_numFrames] = READ_LE_UINT32(wsaData); + wsaData += 4; + _frameOffsTable[_numFrames + 1] = READ_LE_UINT32(wsaData); + wsaData += 4; + if (_frameOffsTable[_numFrames + 1]) + _frameOffsTable[_numFrames] -= frameDataOffs; + else + _frameOffsTable[_numFrames] = 0; + // skip palette wsaData += offsPal; // read frame data const int frameDataSize = p + fileSize - wsaData; + _frameData = new uint8[frameDataSize]; memcpy(_frameData, wsaData, frameDataSize); @@ -438,11 +456,15 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { return _numFrames; } -void WSAMovie_v2::displayFrame(int frameNum, ...) { - debugC(9, kDebugLevelMovie, "WSAMovie_v2::displayFrame(%d, ...)", frameNum); +void WSAMovie_v2::displayFrame(int frameNum, int pageNum, int x, int y, ...) { + debugC(9, kDebugLevelMovie, "WSAMovie_v2::displayFrame(%d, %d, %d, %d,...)", frameNum, pageNum, x, y); if (frameNum >= _numFrames || frameNum < 0 || !_opened) return; + _x = x + _xAdd; + _y = y + _yAdd; + _drawPage = pageNum; + uint8 *dst = 0; if (_flags & WF_OFFSCREEN_DECODE) dst = _offscreenBuffer; @@ -503,7 +525,7 @@ void WSAMovie_v2::displayFrame(int frameNum, ...) { _screen->_curPage = _drawPage; va_list args; - va_start(args, frameNum); + va_start(args, y); int copyParam = va_arg(args, int); int plotFunc = (copyParam & 0xFF00) >> 12; diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h index 1db8ee8474..a1e0562f60 100644 --- a/engines/kyra/wsamovie.h +++ b/engines/kyra/wsamovie.h @@ -47,11 +47,8 @@ public: virtual int frames() = 0; - virtual void displayFrame(int frameNum, ...) = 0; + virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...) = 0; - virtual void setX(int x) { _x = x; } - virtual void setY(int y) { _y = y; } - virtual void setDrawPage(int page) { _drawPage = page; } protected: KyraEngine_v1 *_vm; bool _opened; @@ -70,7 +67,7 @@ public: virtual int frames() { return _opened ? _numFrames : -1; } - virtual void displayFrame(int frameNum, ...); + virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...); enum WSAFlags { WF_OFFSCREEN_DECODE = 0x10, @@ -100,7 +97,7 @@ public: int open(const char *filename, int offscreen, uint8 *palette); void close(); - void displayFrame(int frameNum, ...); + void displayFrame(int frameNum, int pageNum, int x, int y, ...); private: void processFrame(int frameNum, uint8 *dst); @@ -113,10 +110,7 @@ public: int open(const char *filename, int unk1, uint8 *palette); - virtual void displayFrame(int frameNum, ...); - - void setX(int x) { _x = x + _xAdd; } - void setY(int y) { _y = y + _yAdd; } + virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...); int xAdd() const { return _xAdd; } int yAdd() const { return _yAdd; } diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp index d8876cde3c..50b294c6b8 100644 --- a/tools/create_kyradat/create_kyradat.cpp +++ b/tools/create_kyradat/create_kyradat.cpp @@ -31,7 +31,7 @@ #include "md5.h" enum { - kKyraDatVersion = 45, + kKyraDatVersion = 46, kIndexSize = 12 }; @@ -341,6 +341,8 @@ const ExtractFilename extractFilenames[] = { { lolMapStringId, lolTypeRaw16, "MAPSTRID.LST" }, //{ lolMapPal, kTypeRawData, "MAP.PAL" }, + { lolSpellbookAnim, k3TypeRaw16to8, "MBOOKA.DEF" }, + { lolSpellbookCoords, k3TypeRaw16to8, "MBOOKC.DEF" }, { lolHealShapeFrames, kTypeRawData, "MHEAL.SHP" }, { -1, 0, 0 } diff --git a/tools/create_kyradat/create_kyradat.h b/tools/create_kyradat/create_kyradat.h index 9589340ebc..4c93cbd9e9 100644 --- a/tools/create_kyradat/create_kyradat.h +++ b/tools/create_kyradat/create_kyradat.h @@ -251,6 +251,8 @@ enum kExtractID { lolMapStringId, //lolMapPal, + lolSpellbookAnim, + lolSpellbookCoords, lolHealShapeFrames, kMaxResIDs diff --git a/tools/create_kyradat/lol_cd.h b/tools/create_kyradat/lol_cd.h index d05f74f05d..3c07777627 100644 --- a/tools/create_kyradat/lol_cd.h +++ b/tools/create_kyradat/lol_cd.h @@ -74,6 +74,8 @@ const ExtractEntry lolCDFile2[] = { { lolMapStringId, 0x000287D0, 0x0002880C }, //{ lolMapPal, 0x0001D9C0, 0x0001DBC0 }, + { lolSpellbookAnim, 0x00032D94, 0x00032DCC }, + { lolSpellbookCoords, 0x00032DCC, 0x00032DE4 }, { lolHealShapeFrames, 0x000297D0, 0x00029820 }, { -1, 0, 0 } diff --git a/tools/create_kyradat/misc.h b/tools/create_kyradat/misc.h index c154d423e5..f868e7ce2e 100644 --- a/tools/create_kyradat/misc.h +++ b/tools/create_kyradat/misc.h @@ -557,6 +557,8 @@ const int lolCDFile2Need[] = { lolMapStringId, //lolMapPal, + lolSpellbookAnim, + lolSpellbookCoords, lolHealShapeFrames, -1 |