From cbce9e11790decbce0f2a3b9c9d802db984e9b55 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sat, 23 May 2009 18:43:04 +0000 Subject: LOL: implemented fireball spell svn-id: r40813 --- engines/kyra/lol.cpp | 153 ++++++++++++++++++++++++++++++++++++++++++++- engines/kyra/lol.h | 24 +++++++ engines/kyra/resource.h | 1 + engines/kyra/staticres.cpp | 49 +++++++++------ 4 files changed, 205 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 55ca7a4e1e..da0703f5e0 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -232,6 +232,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _mapOverlay = 0; _automapShapes = 0; _defaultLegendData = 0; + _mapCursorOverlay = 0; _lightningProps = 0; _lightningCurSfx = -1; @@ -2538,6 +2539,154 @@ void LoLEngine::processMagicIce(int charNum, int spellLevel) { } void LoLEngine::processMagicFireball(int charNum, int spellLevel) { + int fbCnt = 0; + int d = 1; + + if (spellLevel == 0) { + fbCnt = 4; + } else if (spellLevel == 1) { + fbCnt = 5; + } else if (spellLevel == 2) { + fbCnt = 6; + } else if (spellLevel == 3) { + d = 0; + fbCnt = 5; + } + + int drawPage1 = 2; + int drawPage2 = 4; + + int bl = _currentBlock; + int fireballItem = makeItem(9, 0, 0); + + int i = 0; + for (; i < 3; i++) { + runLevelScriptCustom(bl, 0x200, -1, fireballItem, 0, 0); + uint16 o = _levelBlockProperties[bl].assignedObjects; + + if ((o & 0x8000) || (_wllWallFlags[_levelBlockProperties[bl].walls[_currentDirection ^ 2]] & 7)) { + while (o & 0x8000) { + static const uint8 fireballDamage[] = { 20, 40, 80, 100 }; + int dmg = calcInflictableDamagePerItem(charNum, o, fireballDamage[spellLevel], 4, 1); + MonsterInPlay *m = &_monsters[o & 0x7fff]; + o = m->nextAssignedObject; + _envSfxUseQueue = true; + inflictDamage(m->id | 0x8000, dmg, charNum, 2, 4); + _envSfxUseQueue = false; + } + break; + } + + bl = calcNewBlockPosition(bl, _currentDirection); + } + + d += i; + if (d > 3) + d = 3; + + deleteItem(fireballItem); + + snd_playSoundEffect(69, -1); + + int cp = _screen->setCurPage(2); + _screen->copyPage(0, 12); + + int fireBallWH = (d << 4) * -1; + int numFireBalls = 1; + if (fbCnt > 3) + numFireBalls = fbCnt - 3; + + FireballState *fireballState[3]; + memset(fireballState, 0, sizeof(fireballState)); + for (i = 0; i < numFireBalls; i++) + fireballState[i] = new FireballState(i); + + _screen->copyPage(12, drawPage1); + + for (i = 0; i < numFireBalls;) { + _screen->setCurPage(drawPage1); + uint32 ctime = _system->getMillis(); + + for (int ii = 0; ii < MIN(fbCnt, 3); ii++) { + FireballState *fb = fireballState[ii]; + if (!fb) + continue; + if (!fb->active) + continue; + + static const int8 finShpIndex1[] = { 5, 6, 7, 7, 6, 5 }; + static const int8 finShpIndex2[] = { -1, 1, 2, 3, 4, -1 }; + uint8 *shp = fb->finalize ? _fireballShapes[finShpIndex1[fb->finProgress]] : _fireballShapes[0]; + + int fX = (((fb->progress * _fireBallCoords[fb->tblIndex & 0xff]) >> 16) + fb->destX) - ((fb->progress / 8 + shp[3] + fireBallWH) >> 1); + int fY = (((fb->progress * _fireBallCoords[(fb->tblIndex + 64) & 0xff]) >> 16) + fb->destY) - ((fb->progress / 8 + shp[2] + fireBallWH) >> 1); + int sW = ((fb->progress / 8 + shp[3] + fireBallWH) << 8) / shp[3]; + int sH = ((fb->progress / 8 + shp[2] + fireBallWH) << 8) / shp[2]; + + if (fb->finalize) { + _screen->drawShape(_screen->_curPage, shp, fX, fY, 0, 0x1004, _trueLightTable1, _trueLightTable2, sW, sH); + + if (finShpIndex2[fb->finProgress] != -1) { + shp = _fireballShapes[finShpIndex2[fb->finProgress]]; + fX = (((fb->progress * _fireBallCoords[fb->tblIndex & 0xff]) >> 16) + fb->destX) - ((fb->progress / 8 + shp[3] + fireBallWH) >> 1); + fY = (((fb->progress * _fireBallCoords[(fb->tblIndex + 64) & 0xff]) >> 16) + fb->destY) - ((fb->progress / 8 + shp[2] + fireBallWH) >> 1); + sW = ((fb->progress / 8 + shp[3] + fireBallWH) << 8) / shp[3]; + sH = ((fb->progress / 8 + shp[2] + fireBallWH) << 8) / shp[2]; + _screen->drawShape(_screen->_curPage, shp, fX, fY, 0, 4, sW, sH); + } + + } else { + _screen->drawShape(_screen->_curPage, shp, fX, fY, 0, 0x1004, _trueLightTable1, _trueLightTable2, sW, sH); + } + + if (fb->finalize) { + if (++fb->finProgress >= 6) { + fb->active = false; + i++; + } + } else { + if (fb->step < 40) + fb->step += 2; + else + fb->step = 40; + + if (fb->progress < fb->step) { + if (ii < 1) { + fb->progress = fb->step = fb->finProgress = 0; + fb->finalize = true; + } else { + fb->active = false; + i++; + } + + static const uint8 fireBallSfx[] = { 98, 167, 167, 168 }; + snd_playSoundEffect(fireBallSfx[d], -1); + + } else { + fb->progress -= fb->step; + } + } + } + + int del = _tickLength - (_system->getMillis() - ctime); + if (del > 0) + delay(del, false, true); + + _screen->checkedPageUpdate(drawPage1, drawPage2); + _screen->updateScreen(); + SWAP(drawPage1, drawPage2); + _screen->copyPage(12, drawPage1); + } + + for (i = 0; i < numFireBalls; i++) + delete[] fireballState[i]; + + _screen->setCurPage(cp); + _screen->copyPage(12, 0); + _screen->updateScreen(); + updateDrawPage2(); + snd_playQueuedEffects(); + runLevelScriptCustom(bl, 0x20, charNum, 3, 0, 0); } void LoLEngine::processMagicHandOfFate(int charNum, int spellLevel) { @@ -2574,8 +2723,8 @@ void LoLEngine::processMagicLightning(int charNum, int spellLevel) { _screen->copyPage(12, 0); updateDrawPage2(); - static const uint8 lighntingDamage[] = { 18, 35, 50, 72 }; - inflictMagicalDamageForBlock(calcNewBlockPosition(_currentBlock, _currentDirection), charNum, lighntingDamage[spellLevel], 5); + static const uint8 lightningDamage[] = { 18, 35, 50, 72 }; + inflictMagicalDamageForBlock(calcNewBlockPosition(_currentBlock, _currentDirection), charNum, lightningDamage[spellLevel], 5); _sceneUpdateRequired = true; gui_drawScene(0); diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index cd779b53f9..5a82a47cdb 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -266,6 +266,28 @@ struct LightningProperty { int16 sfxId; }; +struct FireballState { + FireballState(int i) { + active = true; + destX = 200; + destY = 60; + tblIndex = ((i * 50) % 255) + 200; + progress = 1000; + step = 10; + finalize = false; + finProgress = 0; + }; + + bool active; + int16 destX; + int16 destY; + uint16 tblIndex; + int32 progress; + uint8 step; + bool finalize; + uint8 finProgress; +}; + class LoLEngine : public KyraEngine_v1 { friend class GUI_LoL; friend class TextDisplayer_LoL; @@ -1308,6 +1330,8 @@ private: int _updateSpellBookAnimDataSize; const uint8 *_healShapeFrames; int _healShapeFramesSize; + const int16 *_fireBallCoords; + int _fireBallCoordsSize; // fight int battleHitSkillTest(int16 attacker, int16 target, int skill); diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index eb5ba3e23c..07fb2e05b7 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -291,6 +291,7 @@ enum kKyraResources { lolSpellbookCoords, lolHealShapeFrames, lolLightningDefs, + lolFireballCoords, #endif // ENABLE_LOL kMaxResIDs diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 4dfc4e12c1..ced2dff0a4 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -44,7 +44,7 @@ namespace Kyra { -#define RESFILE_VERSION 47 +#define RESFILE_VERSION 48 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -453,6 +453,7 @@ bool StaticResource::init() { { lolSpellbookCoords, kRawData, "MBOOKC.DEF" }, { lolHealShapeFrames, kRawData, "MHEAL.SHP" }, { lolLightningDefs, kRawData, "MLGHTNG.DEF" }, + { lolFireballCoords, kLolRawDataBe16, "MFIREBLL.DEF" }, { 0, 0, 0 } }; @@ -1848,12 +1849,14 @@ void LoLEngine::initStaticResource() { _scrollYBottom = _staticres->loadRawData(kLolScrollYBottom, _scrollYBottomSize); const char *const *tmpSndList = _staticres->loadStrings(kLolIngameSfxFiles, _ingameSoundListSize); - _ingameSoundList = new char*[_ingameSoundListSize]; - for (int i = 0; i < _ingameSoundListSize; i++) { - _ingameSoundList[i] = new char[strlen(tmpSndList[i]) + 1]; - strcpy(_ingameSoundList[i], tmpSndList[i]); + if (tmpSndList) { + _ingameSoundList = new char*[_ingameSoundListSize]; + for (int i = 0; i < _ingameSoundListSize; i++) { + _ingameSoundList[i] = new char[strlen(tmpSndList[i]) + 1]; + strcpy(_ingameSoundList[i], tmpSndList[i]); + } + _staticres->unloadId(kLolIngameSfxFiles); } - _staticres->unloadId(kLolIngameSfxFiles); _buttonData = _staticres->loadButtonDefs(kLolButtonDefs, _buttonDataSize); _buttonList1 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList1, _buttonList1Size); @@ -1870,15 +1873,17 @@ void LoLEngine::initStaticResource() { int tmpSize = 0; const uint8 *tmp = _staticres->loadRawData(lolLegendData, tmpSize); tmpSize /= 5; - _defaultLegendData = new MapLegendData[tmpSize]; - for (int i = 0; i < tmpSize; i++) { - _defaultLegendData[i].shapeIndex = *tmp++; - _defaultLegendData[i].enable = *tmp++ ? true : false; - _defaultLegendData[i].x = (int8)*tmp++; - _defaultLegendData[i].stringId = READ_LE_UINT16(tmp); - tmp += 2; + if (tmp) { + _defaultLegendData = new MapLegendData[tmpSize]; + for (int i = 0; i < tmpSize; i++) { + _defaultLegendData[i].shapeIndex = *tmp++; + _defaultLegendData[i].enable = *tmp++ ? true : false; + _defaultLegendData[i].x = (int8)*tmp++; + _defaultLegendData[i].stringId = READ_LE_UINT16(tmp); + tmp += 2; + } + _staticres->unloadId(lolLegendData); } - _staticres->unloadId(lolLegendData); tmp = _staticres->loadRawData(lolMapCursorOvl, tmpSize); _mapCursorOverlay = new uint8[tmpSize]; @@ -1890,13 +1895,17 @@ void LoLEngine::initStaticResource() { _healShapeFrames = _staticres->loadRawData(lolHealShapeFrames, _healShapeFramesSize); tmp = _staticres->loadRawData(lolLightningDefs, tmpSize); - _lightningProps = new LightningProperty[5]; - for (int i = 0; i < 5; i++) { - _lightningProps[i].lastFrame = tmp[i << 2]; - _lightningProps[i].frameDiv = tmp[(i << 2) + 1]; - _lightningProps[i].sfxId = READ_LE_UINT16(&tmp[(i << 2) + 2]); + if (tmp) { + _lightningProps = new LightningProperty[5]; + for (int i = 0; i < 5; i++) { + _lightningProps[i].lastFrame = tmp[i << 2]; + _lightningProps[i].frameDiv = tmp[(i << 2) + 1]; + _lightningProps[i].sfxId = READ_LE_UINT16(&tmp[(i << 2) + 2]); + } + _staticres->unloadId(lolLightningDefs); } - _staticres->unloadId(lolLightningDefs); + + _fireBallCoords = (const int16*) _staticres->loadRawDataBe16(lolFireballCoords, _fireBallCoordsSize); _buttonCallbacks.clear(); _buttonCallbacks.reserve(95); -- cgit v1.2.3