aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/lol.cpp153
-rw-r--r--engines/kyra/lol.h24
-rw-r--r--engines/kyra/resource.h1
-rw-r--r--engines/kyra/staticres.cpp49
4 files changed, 205 insertions, 22 deletions
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);