aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dists/engine-data/kyra.datbin256787 -> 256888 bytes
-rw-r--r--engines/kyra/detection.cpp80
-rw-r--r--engines/kyra/gui_lok.cpp2
-rw-r--r--engines/kyra/gui_lol.cpp67
-rw-r--r--engines/kyra/items_lol.cpp70
-rw-r--r--engines/kyra/kyra_v1.h10
-rw-r--r--engines/kyra/lol.cpp891
-rw-r--r--engines/kyra/lol.h185
-rw-r--r--engines/kyra/resource.h2
-rw-r--r--engines/kyra/saveload_lok.cpp2
-rw-r--r--engines/kyra/scene_lol.cpp20
-rw-r--r--engines/kyra/screen.cpp58
-rw-r--r--engines/kyra/screen.h2
-rw-r--r--engines/kyra/screen_lol.cpp127
-rw-r--r--engines/kyra/screen_lol.h39
-rw-r--r--engines/kyra/screen_v2.cpp3
-rw-r--r--engines/kyra/script_lol.cpp187
-rw-r--r--engines/kyra/script_tim.cpp4
-rw-r--r--engines/kyra/script_tim.h4
-rw-r--r--engines/kyra/sequences_lol.cpp61
-rw-r--r--engines/kyra/sound.h8
-rw-r--r--engines/kyra/sound_towns.cpp59
-rw-r--r--engines/kyra/sprites_lol.cpp226
-rw-r--r--engines/kyra/staticres.cpp193
-rw-r--r--engines/kyra/timer.cpp2
-rw-r--r--engines/kyra/timer_lol.cpp111
-rw-r--r--engines/kyra/wsamovie.cpp13
-rw-r--r--tools/create_kyradat/create_kyradat.cpp4
-rw-r--r--tools/create_kyradat/create_kyradat.h2
-rw-r--r--tools/create_kyradat/lol_cd.h2
-rw-r--r--tools/create_kyradat/misc.h2
31 files changed, 1860 insertions, 576 deletions
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat
index cedbdacc1d..eb6314e7d3 100644
--- a/dists/engine-data/kyra.dat
+++ b/dists/engine-data/kyra.dat
Binary files differ
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index c84dbb9434..dd5162e56e 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -43,36 +43,35 @@ struct KYRAGameDescription {
namespace {
-#define FLAGS(x, y, z, a, b, c, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, id }
-#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, id }
-
-#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_KYRA1)
-#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, Kyra::GI_KYRA1)
-#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA1)
-
-#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_KYRA2)
-#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, Kyra::GI_KYRA2)
-
-#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, true, true, Kyra::GI_KYRA3)
-#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, true, false, Kyra::GI_KYRA3)
-#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, true, false, Kyra::GI_KYRA3)
-
-#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_LOL)
-#define LOL_PC98_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, false, false, Kyra::GI_LOL)
-#define LOL_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA2)
+#define FLAGS(x, y, z, a, b, c, d, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
+#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
+
+#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA1)
+#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA1)
+
+#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA2)
+#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, false, Kyra::GI_KYRA2)
+
+#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, true, true, Kyra::GI_KYRA3)
+#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, true, false, Kyra::GI_KYRA3)
+#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3)
+
+#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL)
+#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL)
+#define LOL_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
const KYRAGameDescription adGameDescs[] = {
/* disable these targets until they get supported
@@ -1020,23 +1019,6 @@ const KYRAGameDescription adGameDescs[] = {
LOL_FLOPPY_FLAGS
},
- /* disable these targets until they get supported
- {
- {
- "lol",
- 0,
- {
- { "GENERAL.PAK", 0, "3fe6539b9b09084c0984eaf7170464e9", -1 },
- { "MUS.PAK", 0, "008dc69d8cbcdb6bae30e270fab26e76", -1 },
- { 0, 0, 0, 0 }
- },
- Common::EN_ANY,
- Common::kPlatformPC98,
- ADGF_NO_FLAGS
- },
- LOL_PC98_FLAGS
- },
-
{
{
"lol",
@@ -1051,7 +1033,7 @@ const KYRAGameDescription adGameDescs[] = {
ADGF_NO_FLAGS
},
LOL_PC98_SJIS_FLAGS
- },*/
+ },
{
{
@@ -1069,7 +1051,7 @@ const KYRAGameDescription adGameDescs[] = {
},
#endif // ENABLE_LOL
- { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0) }
+ { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) }
};
const PlainGameDescriptor gameList[] = {
diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp
index 665c38115b..baf39c0954 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 || _vm->gameFlags().platform == Common::kPlatformPC98) ? 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 30e0ec7c15..2769692a65 100644
--- a/engines/kyra/gui_lol.cpp
+++ b/engines/kyra/gui_lol.cpp
@@ -473,7 +473,7 @@ void LoLEngine::gui_drawLiveMagicBar(int x, int y, int curPoints, int unk, int m
int barHeight = (curPoints * h) / maxPoints;
- if (barHeight < 1 && curPoints < 1)
+ if (barHeight < 1 && curPoints > 0)
barHeight = 1;
_screen->drawClippedLine(x - 1, y - h, x - 1, y, 1);
@@ -1037,6 +1037,46 @@ int LoLEngine::clickedTurnRightArrow(Button *button) {
}
int LoLEngine::clickedAttackButton(Button *button) {
+ int c = button->data2Val2;
+
+ if (_characters[c].flags & 0x314C)
+ return 1;
+
+ int bl = calcNewBlockPosition(_currentBlock, _currentDirection);
+
+ if (_levelBlockProperties[bl].flags & 0x10) {
+ attackWall(0, 0);
+ return 1;
+ }
+
+ uint16 target = getNearestMonsterFromCharacter(c);
+ int s = 0;
+
+ for (int i = 0; i < 4; i++) {
+ if (!_characters[c].items[i])
+ continue;
+
+ runItemScript(c, _characters[c].items[i], 0x400, target, s);
+ runLevelScriptCustom(_currentBlock, 0x400, c, _characters[c].items[i], target, s);
+ s -= 10;
+ }
+
+ if (!s) {
+ runItemScript(c, 0, 0x400, target, s);
+ runLevelScriptCustom(_currentBlock, 0x400, c, 0, target, s);
+ }
+
+ s = _characters[c].weaponHit ? 4 : calcMonsterSkillLevel(c, 8) + 4;
+
+ // check for Zephyr ring
+ if (itemEquipped(c, 230))
+ s >>= 1;
+
+ _characters[c].flags |= 4;
+ gui_highlightPortraitFrame(c);
+
+ setCharacterUpdateEvent(c, 1, s, 1);
+
return 1;
}
@@ -1074,7 +1114,7 @@ int LoLEngine::clickedMagicSubmenu(Button *button) {
// TODO
///
/*if (processSpellcast(c, _availableSpells[_selectedSpell], spellLevel)) {
- setFaceFramesUnkArrays(c, 1, 8, 1);
+ setCharacterUpdateEvent(c, 1, 8, 1);
sub_718F(c, 2, spellLevel * spellLevel);
} else {*/
_characters[c].flags &= 0xfffb;
@@ -1130,6 +1170,23 @@ int LoLEngine::clickedLiveMagicBarsLeft(Button *button) {
}
int LoLEngine::clickedPortraitEtcRight(Button *button) {
+ if (!_itemInHand)
+ return 1;
+
+ int flg = _itemProperties[_itemsInPlay[_itemInHand].itemPropertyIndex].flags;
+ int c = button->data2Val2;
+
+ if (flg & 1) {
+ if (!(_characters[c].flags & 8) || (flg & 0x20)) {
+ runItemScript(c, _itemInHand, 0x400, 0, 0);
+ runLevelScriptCustom(_currentBlock, 0x400, c, _itemInHand, 0, 0);
+ } else {
+ _txt->printMessage(2, getLangString(0x402c), _characters[c].name);
+ }
+ return 1;
+ }
+
+ _txt->printMessage(2, getLangString((flg & 8) ? 0x4029 : ((flg & 0x10) ? 0x402a : 0x402b)));
return 1;
}
@@ -1389,8 +1446,10 @@ int LoLEngine::clickedWall(Button *button) {
int LoLEngine::clickedSequenceWindow(Button *button) {
runLevelScript(calcNewBlockPosition(_currentBlock, _currentDirection), 0x40);
- if (!_seqTrigger || !posWithinRect(_mouseX, _mouseY, _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2))
+ if (!_seqTrigger || !posWithinRect(_mouseX, _mouseY, _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2)) {
_seqTrigger = 0;
+ removeInputTop();
+ }
return 1;
}
@@ -1418,7 +1477,7 @@ int LoLEngine::clickedSceneThrowItem(Button *button) {
uint16 y = 0;
calcCoordinates(x, y, _currentBlock, 0x80, 0x80);
- if (throwItem(0, _itemInHand, x, y, 12, _currentDirection << 1, 6, _selectedCharacter, 0x3f)) {
+ if (launchObject(0, _itemInHand, x, y, 12, _currentDirection << 1, 6, _selectedCharacter, 0x3f)) {
snd_playSoundEffect(18, -1);
setHandItem(0);
}
diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp
index 64a6850fcb..02c8e50410 100644
--- a/engines/kyra/items_lol.cpp
+++ b/engines/kyra/items_lol.cpp
@@ -181,14 +181,14 @@ int LoLEngine::makeItem(int itemType, int curFrame, int flags) {
void LoLEngine::placeMoveLevelItem(int itemIndex, int level, int block, int xOffs, int yOffs, int flyingHeight) {
calcCoordinates(_itemsInPlay[itemIndex].x, _itemsInPlay[itemIndex].y, block, xOffs, yOffs);
- if (_itemsInPlay[itemIndex].blockPropertyIndex)
- removeLevelItem(itemIndex, _itemsInPlay[itemIndex].blockPropertyIndex);
+ if (_itemsInPlay[itemIndex].block)
+ removeLevelItem(itemIndex, _itemsInPlay[itemIndex].block);
if (_currentLevel == level) {
setItemPosition(itemIndex, _itemsInPlay[itemIndex].x, _itemsInPlay[itemIndex].y, flyingHeight, 1);
} else {
_itemsInPlay[itemIndex].level = level;
- _itemsInPlay[itemIndex].blockPropertyIndex = block;
+ _itemsInPlay[itemIndex].block = block;
_itemsInPlay[itemIndex].flyingHeight = flyingHeight;
_itemsInPlay[itemIndex].shpCurFrame_flg |= 0x4000;
}
@@ -289,6 +289,24 @@ void LoLEngine::setHandItem(uint16 itemIndex) {
_screen->setMouseCursor(mouseOffs, mouseOffs, getItemIconShapePtr(itemIndex));
}
+bool LoLEngine::itemEquipped(int charNum, uint16 itemType) {
+ if (charNum < 0 || charNum > 3)
+ return false;
+
+ if (!(_characters[charNum].flags & 1))
+ return false;
+
+ for (int i = 0; i < 11; i++) {
+ if (!_characters[charNum].items[i])
+ continue;
+
+ if (_itemsInPlay[_characters[charNum].items[i]].itemPropertyIndex == itemType)
+ return true;
+ }
+
+ return false;
+}
+
void LoLEngine::setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, int b) {
if (!flyingHeight) {
x = (x & 0xffc0) | 0x40;
@@ -298,7 +316,7 @@ void LoLEngine::setItemPosition(int item, uint16 x, uint16 y, int flyingHeight,
uint16 block = calcBlockIndex(x, y);
_itemsInPlay[item].x = x;
_itemsInPlay[item].y = y;
- _itemsInPlay[item].blockPropertyIndex = block;
+ _itemsInPlay[item].block = block;
_itemsInPlay[item].flyingHeight = flyingHeight;
if (b)
@@ -320,12 +338,12 @@ void LoLEngine::removeLevelItem(int item, int block) {
removeAssignedObjectFromBlock(&_levelBlockProperties[block], item);
removeDrawObjectFromBlock(&_levelBlockProperties[block], item);
runLevelScriptCustom(block, 0x100, -1, item, 0, 0);
- _itemsInPlay[item].blockPropertyIndex = 0;
+ _itemsInPlay[item].block = 0;
_itemsInPlay[item].level = 0;
}
-bool LoLEngine::throwItem(int a, int item, int x, int y, int flyingHeight, int direction, int, int charNum, int c) {
- int sp = checkDrawObjectSpace(_partyPosX, _partyPosX, x, y);
+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);
FlyingObject *t = _flyingObjects;
int slot = -1;
int i = 0;
@@ -348,31 +366,31 @@ bool LoLEngine::throwItem(int a, int item, int x, int y, int flyingHeight, int d
i = slot;
t = &_flyingObjects[i];
- endObjectFlight(t, x, y, 8);
+ endObjectFlight(t, startX, startY, 8);
}
if (i == 8)
return false;
t->enable = 1;
- t->a = a;
+ t->objectType = objectType;
t->item = item;
- t->x = x;
- t->y = y;
+ t->x = startX;
+ t->y = startY;
t->flyingHeight = flyingHeight;
t->direction = direction;
t->distance = 255;
- t->charNum = charNum;
+ t->attackerId = attackerId;
t->flags = 7;
t->wallFlags = 2;
t->c = c;
- if (charNum != -1) {
- if (charNum & 0x8000) {
+ if (attackerId != -1) {
+ if (attackerId & 0x8000) {
t->flags &= 0xfd;
} else {
t->flags &= 0xfb;
- increaseExperience(charNum, 1, 2);
+ increaseExperience(attackerId, 1, 2);
}
}
@@ -393,7 +411,7 @@ void LoLEngine::endObjectFlight(FlyingObject *t, int x, int y, int objectOnNextB
cy = t->y;
}
- if (t->a == 0 || t->a == 1) {
+ if (t->objectType == 0 || t->objectType == 1) {
objectFlightProcessHits(t, cx, cy, objectOnNextBlock);
t->x = (cx & 0xffc0) | 0x40;
t->y = (cy & 0xffc0) | 0x40;
@@ -416,9 +434,9 @@ void LoLEngine::processObjectFlight(FlyingObject *t, int x, int y) {
}
void LoLEngine::updateObjectFlightPosition(FlyingObject *t) {
- if (t->a == 0) {
+ if (t->objectType == 0) {
setItemPosition(t->item, t->x, t->y, t->flyingHeight, (t->flyingHeight == 0) ? 1 : 0);
- } else if (t->a == 1) {
+ } else if (t->objectType == 1) {
if (t->flyingHeight == 0) {
deleteItem(t->item);
checkSceneUpdateNeed(calcBlockIndex(t->x, t->y));
@@ -432,23 +450,23 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec
uint16 r = 0;
if (objectOnNextBlock == 1) {
- runLevelScriptCustom(calcNewBlockPosition(_itemsInPlay[t->item].blockPropertyIndex, t->direction >> 1), 0x8000, -1, t->item, 0, 0);
+ runLevelScriptCustom(calcNewBlockPosition(_itemsInPlay[t->item].block, t->direction >> 1), 0x8000, -1, t->item, 0, 0);
return;
} else if (objectOnNextBlock == 2) {
if (_itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000) {
- int o = _levelBlockProperties[_itemsInPlay[t->item].blockPropertyIndex].assignedObjects;
+ int o = _levelBlockProperties[_itemsInPlay[t->item].block].assignedObjects;
while (o & 0x8000) {
ItemInPlay *i = findObject(o);
o = i->nextAssignedObject;
- runItemScript(t->charNum, t->item, 0x8000, o, 0);
+ runItemScript(t->attackerId, t->item, 0x8000, o, 0);
}
return;
} else {
- r = getClosestMonster(x, y);
+ r = getNearestMonsterFromPos(x, y);
}
} else if (objectOnNextBlock == 4) {
@@ -456,19 +474,19 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec
if (_itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000) {
for (int i = 0; i < 4; i++) {
if (_characters[i].flags & 1)
- runItemScript(t->charNum, t->item, 0x8000, i, 0);
+ runItemScript(t->attackerId, t->item, 0x8000, i, 0);
}
return;
} else {
- r = getClosestPartyMember(x, y);
+ r = getNearestPartyMemberFromPos(x, y);
}
}
- runItemScript(t->charNum, t->item, 0x8000, r, 0);
+ runItemScript(t->attackerId, t->item, 0x8000, r, 0);
}
-void LoLEngine::updateFlyingObjects(FlyingObject *t) {
+void LoLEngine::updateFlyingObject(FlyingObject *t) {
int x = 0;
int y = 0;
getNextStepCoords(t->x, t->y, x, y, t->direction);
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index 527739f19f..148da506c4 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -56,6 +56,7 @@ struct GameFlags {
bool useAltShapeHeader : 1; // alternative shape header (uses 2 bytes more, those are unused though)
bool isTalkie : 1;
bool useHiResOverlay : 1;
+ bool use16ColorMode : 1;
bool useDigSound : 1;
bool useInstallerPackage : 1;
@@ -70,10 +71,11 @@ enum {
};
struct AudioDataStruct {
- const char * const *_fileList;
- int _fileListLen;
- const void * _cdaTracks;
- int _cdaNumTracks;
+ const char *const *fileList;
+ int fileListLen;
+ const void *cdaTracks;
+ int cdaNumTracks;
+ int extraOffset;
};
// TODO: this is just the start of makeing the debug output of the kyra engine a bit more useable
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 9093c63dc9..a05003ffbd 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -63,6 +63,9 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_lang = 2;
break;
+ case Common::JA_JPN:
+ _lang = 0;
+
default:
warning("unsupported language, switching back to English");
_lang = 0;
@@ -91,13 +94,14 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_specialSceneFlag = 0;
_lastCharInventory = -1;
- _itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _effectShapes = _fireballShapes = 0;
+ _itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _effectShapes = _fireballShapes = _healShapes = _healiShapes = 0;
_levelShpList = _levelDatList = 0;
_monsterShapes = _monsterPalettes = 0;
_monsterShapesEx = 0;
_gameShapeMap = 0;
memset(_monsterUnk, 0, 3);
_pageSavedFlag = false;
+ _healOverlay = 0;
_ingameMT32SoundIndex = _ingameGMSoundIndex = /*_ingameADLSoundIndex =*/ 0;
@@ -181,7 +185,11 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_curMusicTheme = -1;
_curMusicFileExt = 0;
_curMusicFileIndex = -1;
- _environmentSfx = _environmentSfxVol = _environmentSfxDistThreshold = 0;
+ _environmentSfx = _environmentSfxVol = _envSfxDistThreshold = 0;
+ _envSfxUseQueue = false;
+ _envSfxNumTracksInQueue = 0;
+ memset (_envSfxQueuedTracks, 0, sizeof(_envSfxQueuedTracks));
+ memset (_envSfxQueuedBlocks, 0, sizeof(_envSfxQueuedBlocks));
_sceneDrawVarDown = _sceneDrawVarRight = _sceneDrawVarLeft = _wllProcessFlag = 0;
_partyPosX = _partyPosY = 0;
@@ -198,7 +206,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
memset(_charStatsTemp, 0, sizeof(_charStatsTemp));
- _compassBroken = _unkBt2 = 0;
+ _compassBroken = _drainMagic = 0;
_dialogueField = false;
_rndSpecial = 0x12349876;
@@ -220,6 +228,8 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_defaultLegendData = 0;
_compassTimer = 0;
+ _timer3Para = 0;
+ _partyDeathFlag = -1;
}
LoLEngine::~LoLEngine() {
@@ -250,32 +260,49 @@ LoLEngine::~LoLEngine() {
delete[] _itemIconShapes[i];
delete[] _itemIconShapes;
}
+
if (_itemShapes) {
for (int i = 0; i < _numItemShapes; i++)
delete[] _itemShapes[i];
delete[] _itemShapes;
}
+
if (_gameShapes) {
for (int i = 0; i < _numGameShapes; i++)
delete[] _gameShapes[i];
delete[] _gameShapes;
}
+
if (_thrownShapes) {
for (int i = 0; i < _numThrownShapes; i++)
delete[] _thrownShapes[i];
delete[] _thrownShapes;
}
+
if (_effectShapes) {
for (int i = 0; i < _numEffectShapes; i++)
delete[] _effectShapes[i];
delete[] _effectShapes;
}
+
if (_fireballShapes) {
for (int i = 0; i < _numFireballShapes; i++)
delete[] _fireballShapes[i];
delete[] _fireballShapes;
}
+ if (_healShapes) {
+ for (int i = 0; i < _numHealShapes; i++)
+ delete[] _healShapes[i];
+ delete[] _healShapes;
+ }
+
+ if (_healiShapes) {
+ for (int i = 0; i < _numHealiShapes; i++)
+ delete[] _healiShapes[i];
+ delete[] _healiShapes;
+ }
+
if (_monsterShapes) {
for (int i = 0; i < 48; i++)
delete[] _monsterShapes[i];
@@ -357,6 +384,8 @@ LoLEngine::~LoLEngine() {
}
}
+ delete[] _healOverlay;
+
delete[] _defaultLegendData;
delete[] _mapCursorOverlay;
delete[] _mapOverlay;
@@ -378,7 +407,7 @@ Common::Error LoLEngine::init() {
KyraEngine_v1::init();
initStaticResource();
- _environmentSfxDistThreshold = (MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB) == MD_ADLIB || ConfMan.getBool("multi_midi")) ? 15 : 3;
+ _envSfxDistThreshold = (MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB) == MD_ADLIB || ConfMan.getBool("multi_midi")) ? 15 : 3;
_gui = new GUI_LoL(this);
assert(_gui);
@@ -475,6 +504,7 @@ Common::Error LoLEngine::init() {
Common::Error LoLEngine::go() {
setupPrologueData(true);
+ _sound->setSoundList(&_soundData[kMusicIntro]);
if (!saveFileLoadable(0))
showIntro();
@@ -532,7 +562,7 @@ Common::Error LoLEngine::go() {
return Common::kNoError;
if (processSelection == 0) {
- _sound->loadSoundFile("LOREINTR");
+ _sound->loadSoundFile(0);
_sound->playTrack(6);
chooseCharacter();
_sound->playTrack(1);
@@ -541,6 +571,9 @@ Common::Error LoLEngine::go() {
setupPrologueData(false);
+ _sound->setSoundList(&_soundData[kMusicIngame]);
+ _sound->loadSoundFile(0);
+
_tim = new TIMInterpreter_LoL(this, _screen, _system);
assert(_tim);
@@ -637,15 +670,27 @@ int LoLEngine::mainMenu() {
bool hasSave = saveFileLoadable(0);
- MainMenu::StaticData data = {
- { 0, 0, 0, 0, 0 },
- { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x3D, 0x9F },
- { 0x2C, 0x19, 0x48, 0x2C },
- Screen::FID_9_FNT, 1
+ MainMenu::StaticData data[] = {
+ // 256 color mode
+ {
+ { 0, 0, 0, 0, 0 },
+ { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x3D, 0x9F },
+ { 0x2C, 0x19, 0x48, 0x2C },
+ Screen::FID_9_FNT, 1
+ },
+ // 16 color mode
+ {
+ { 0, 0, 0, 0, 0 },
+ { 0x01, 0x04, 0x0C, 0x03, 0x00, 0xC1, 0xE1 },
+ { 0xCC, 0xDD, 0xDD, 0xDD },
+ Screen::FID_9_FNT, 1
+ }
};
+ int dataIndex = _flags.use16ColorMode ? 1 : 0;
+
if (hasSave)
- ++data.menuTable[3];
+ ++data[dataIndex].menuTable[3];
static const uint16 mainMenuStrings[4][5] = {
{ 0x4248, 0x4249, 0x42DD, 0x424A, 0x0000 },
@@ -658,14 +703,14 @@ int LoLEngine::mainMenu() {
for (int i = 0; i < 5; ++i) {
if (hasSave)
- data.strings[i] = getLangString(mainMenuStrings[1 + tableOffs][i]);
+ data[dataIndex].strings[i] = getLangString(mainMenuStrings[1 + tableOffs][i]);
else
- data.strings[i] = getLangString(mainMenuStrings[tableOffs][i]);
+ data[dataIndex].strings[i] = getLangString(mainMenuStrings[tableOffs][i]);
}
MainMenu *menu = new MainMenu(this);
assert(menu);
- menu->init(data, MainMenu::Animation());
+ menu->init(data[dataIndex], MainMenu::Animation());
int selection = menu->handle(_flags.isTalkie ? (hasSave ? 12 : 6) : (hasSave ? 6 : 13));
delete menu;
@@ -735,6 +780,20 @@ void LoLEngine::startup() {
for (int i = 0; i < _numFireballShapes; i++)
_fireballShapes[i] = _screen->makeShapeCopy(shp, i);
+ _screen->loadBitmap("HEAL.SHP", 3, 3, 0);
+ shp = _screen->getCPagePtr(3);
+ _numHealShapes = READ_LE_UINT16(shp);
+ _healShapes = new uint8*[_numHealShapes];
+ for (int i = 0; i < _numHealShapes; i++)
+ _healShapes[i] = _screen->makeShapeCopy(shp, i);
+
+ _screen->loadBitmap("HEALI.SHP", 3, 3, 0);
+ shp = _screen->getCPagePtr(3);
+ _numHealiShapes = READ_LE_UINT16(shp);
+ _healiShapes = new uint8*[_numHealiShapes];
+ for (int i = 0; i < _numHealiShapes; i++)
+ _healiShapes[i] = _screen->makeShapeCopy(shp, i);
+
memset(_itemsInPlay, 0, 400 * sizeof(ItemInPlay));
for (int i = 0; i < 400; i++)
_itemsInPlay[i].shpCurFrame_flg |= 0x8000;
@@ -814,10 +873,10 @@ void LoLEngine::runLoop() {
else
updateEnvironmentalSfx(0);
- /*if (_partyDeathFlag != -1) {
- checkForPartyDeath(_partyDeathFlag);
+ if (_partyDeathFlag != -1) {
+ checkForPartyDeath();
_partyDeathFlag = -1;
- }*/
+ }
delay(_tickLength);
}
@@ -864,8 +923,12 @@ char *LoLEngine::getLangString(uint16 id) {
char *string = (char *)getTableEntry(buffer, realId);
char *srcBuffer = _stringBuffer[_lastUsedStringBuffer];
- Util::decodeString1(string, srcBuffer);
- Util::decodeString2(srcBuffer, srcBuffer);
+ if (_flags.lang != Common::JA_JPN) {
+ Util::decodeString1(string, srcBuffer);
+ Util::decodeString2(srcBuffer, srcBuffer);
+ } else {
+ decodeSjis(string, srcBuffer);
+ }
++_lastUsedStringBuffer;
_lastUsedStringBuffer %= ARRAYSIZE(_stringBuffer);
@@ -881,6 +944,36 @@ uint8 *LoLEngine::getTableEntry(uint8 *buffer, uint16 id) {
return buffer + READ_LE_UINT16(buffer + (id<<1));
}
+void LoLEngine::decodeSjis(const char *src, char *dst) {
+ char s[2];
+ char d[3];
+ s[1] = 0;
+
+ uint8 cmd = *src++;
+
+ while (cmd) {
+ if (cmd == 27) {
+ cmd = *src & 0x7f;
+ src++;
+
+ for (int i = 0; i < cmd; i ++) {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ }
+ cmd = *src++;
+
+ } else {
+ s[0] = *src++;
+ Util::decodeString1(s, d);
+ *dst++ = d[0];
+ cmd = *src++;
+ }
+ }
+
+ if (!cmd)
+ *dst = 0;
+}
+
bool LoLEngine::addCharacter(int id) {
const uint16 *cdf[] = { _charDefsMan, _charDefsMan, _charDefsMan, _charDefsWoman,
_charDefsMan, _charDefsMan, _charDefsWoman, _charDefsKieran, _charDefsAkshel };
@@ -913,29 +1006,30 @@ bool LoLEngine::addCharacter(int id) {
calcCharPortraitXpos();
if (numChars > 0)
- setFaceFrames(numChars, 2, 6, 0);
+ setTemporaryFaceFrame(numChars, 2, 6, 0);
return true;
}
-void LoLEngine::setFaceFrames(int charNum, int defaultFrame, int unk2, int redraw) {
- _characters[charNum].defaultFaceFrame = defaultFrame;
- if (defaultFrame || unk2)
- setFaceFramesUnkArrays(charNum, 6, unk2, 1);
+void LoLEngine::setTemporaryFaceFrame(int charNum, int frame, int updateDelay, int redraw) {
+ _characters[charNum].defaultFaceFrame = frame;
+ if (frame || updateDelay)
+ setCharacterUpdateEvent(charNum, 6, updateDelay, 1);
if (redraw)
gui_drawCharPortraitWithStats(charNum);
}
-void LoLEngine::setFaceFramesUnkArrays(int charNum, int unk1, int unk2, int unk3) {
+void LoLEngine::setCharacterUpdateEvent(int charNum, int updateType, int updateDelay, int overwrite) {
LoLCharacter *l = &_characters[charNum];
for (int i = 0; i < 5; i++) {
- if (l->arrayUnk2[i] && (!unk3 || l->arrayUnk2[i] != unk1))
+ if (l->characterUpdateEvents[i] && (!overwrite || l->characterUpdateEvents[i] != updateType))
continue;
- l->arrayUnk2[i] = unk1;
- l->arrayUnk1[i] = unk2;
+ l->characterUpdateEvents[i] = updateType;
+ l->characterUpdateDelay[i] = updateDelay;
_timer->setNextRun(3, _system->getMillis());
_timer->enable(3);
+ break;
}
}
@@ -1057,10 +1151,10 @@ void LoLEngine::setCharFaceFrame(int charNum, int frameNum) {
void LoLEngine::faceFrameRefresh(int charNum) {
if (_characters[charNum].curFaceFrame == 1)
- setFaceFrames(charNum, 0, 0, 0);
+ setTemporaryFaceFrame(charNum, 0, 0, 0);
else if (_characters[charNum].curFaceFrame == 6)
if (_characters[charNum].defaultFaceFrame != 5)
- setFaceFrames(charNum, 0, 0, 0);
+ setTemporaryFaceFrame(charNum, 0, 0, 0);
else
_characters[charNum].curFaceFrame = 5;
else
@@ -1114,7 +1208,7 @@ int LoLEngine::calculateProtection(int index) {
c = (_monsters[index].properties->itemProtection * _monsters[index].properties->fightingStats[2]) >> 8;
} else {
// Character
- c = _characters[index].itemsProtection + _characters[index].protection;
+ c = _characters[index].itemProtection + _characters[index].protection;
c = (c * _characters[index].defaultModifiers[2]) >> 8;
c = (c * _characters[index].totalProtectionModifier) >> 8;
}
@@ -1122,6 +1216,74 @@ int LoLEngine::calculateProtection(int index) {
return c;
}
+void LoLEngine::setCharacterMagicOrHitPoints(int charNum, int type, int points, int mode) {
+ static const uint16 barData[2][5] = {
+ // xPos, bar color, text color, flag, string id
+ { 0x27, 0x9A, 0x98, 0x01, 0x4254 },
+ { 0x21, 0xA2, 0xA0, 0x00, 0x4253 }
+ };
+
+ LoLCharacter *c = &_characters[charNum];
+ if (!(c->flags & 1))
+ return;
+
+ int pointsMax = type ? c->magicPointsMax : c->hitPointsMax;
+ int pointsCur = type ? c->magicPointsCur : c->hitPointsCur;
+
+ int newVal = (mode == 2) ? (pointsMax + points) : (mode ? (pointsCur + points) : points);
+ newVal = CLIP(newVal, 0, pointsMax);
+
+ if (type) {
+ c->magicPointsCur = newVal;
+ } else {
+ c->hitPointsCur = newVal;
+ if (c->hitPointsCur < 1)
+ c->flags |= 8;
+ }
+
+ if (_updateFlags & 2)
+ return;
+
+ Screen::FontId cf = _screen->setFont(Screen::FID_6_FNT);
+ int cp = _screen->setCurPage(0);
+
+ int s = 8192 / pointsMax;
+ pointsMax = (s * pointsMax) >> 8;
+ pointsCur = (s * pointsCur) >> 8;
+ newVal = (s * newVal) >> 8;
+ int newValScl = CLIP(newVal, 0, pointsMax);
+
+ int step = (newVal > pointsCur) ? 2 : -2;
+ newVal = CLIP(newVal + step, 0, pointsMax);
+
+ if (newVal != pointsCur) {
+ step = (newVal >= pointsCur) ? 2 : -2;
+
+ for (int i = pointsCur; i != newVal || newVal != newValScl;) {
+ if (ABS(i - newVal) < ABS(step))
+ step >>= 1;
+
+ i += step;
+
+ _smoothScrollTimer = _system->getMillis() + _tickLength;
+
+ gui_drawLiveMagicBar(barData[type][0] + _activeCharsXpos[charNum], 175, i, 0, pointsMax, 5, 32, barData[type][1], 1, barData[type][3]);
+ _screen->printText(getLangString(barData[type][4]), barData[type][0] + _activeCharsXpos[charNum], 144, barData[type][2], 0);
+ _screen->updateScreen();
+
+ if (i == newVal) {
+ newVal = newValScl;
+ step = -step;
+ }
+
+ delayUntil(_smoothScrollTimer);
+ }
+ }
+
+ _screen->setFont(cf);
+ _screen->setCurPage(cp);
+}
+
void LoLEngine::increaseExperience(int charNum, int skill, uint32 points) {
if (charNum & 0x8000)
return;
@@ -1174,6 +1336,17 @@ void LoLEngine::increaseExperience(int charNum, int skill, uint32 points) {
}
}
+void LoLEngine::increaseCharacterHitpoints(int charNum, int points, bool ignoreDeath) {
+ if (_characters[charNum].hitPointsCur <= 0 && !ignoreDeath)
+ return;
+
+ if (points <= 1)
+ points = 1;
+
+ _characters[charNum].hitPointsCur = CLIP<int16>(_characters[charNum].hitPointsCur + points, 1, _characters[charNum].hitPointsMax);
+ _characters[charNum].flags &= 0xfff7;
+}
+
void LoLEngine::setupScreenDims() {
if (textEnabled()) {
_screen->modifyScreenDim(4, 11, 124, 28, 45);
@@ -1590,7 +1763,7 @@ void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
int dist = 0;
if (block) {
dist = getMonsterDistance(_currentBlock, block);
- if (dist > _environmentSfxDistThreshold) {
+ if (dist > _envSfxDistThreshold) {
_environmentSfx = 0;
return;
}
@@ -1619,6 +1792,16 @@ void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
snd_processEnvironmentalSoundEffect(0, 0);
}
+void LoLEngine::snd_queueEnvironmentalSoundEffect(int soundId, int block) {
+ if (_envSfxUseQueue && _envSfxNumTracksInQueue < 10) {
+ _envSfxQueuedTracks[_envSfxNumTracksInQueue] = soundId;
+ _envSfxQueuedBlocks[_envSfxNumTracksInQueue] = block;
+ _envSfxNumTracksInQueue++;
+ } else {
+ snd_processEnvironmentalSoundEffect(soundId, block);
+ }
+}
+
void LoLEngine::snd_loadSoundFile(int track) {
if (_sound->musicEnabled()) {
char filename[13];
@@ -1781,6 +1964,14 @@ const uint16 *LoLEngine::getCharacterOrMonsterStats(int id) {
return (id & 0x8000) ? (const uint16*)_monsters[id & 0x7fff].properties->fightingStats : _characters[id].defaultModifiers;
}
+uint16 *LoLEngine::getCharacterOrMonsterItemsMight(int id) {
+ return (id & 0x8000) ? _monsters[id & 0x7fff].properties->itemsMight : _characters[id].itemsMight;
+}
+
+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()) {
@@ -1820,6 +2011,120 @@ void LoLEngine::updateEnvironmentalSfx(int soundId) {
snd_processEnvironmentalSoundEffect(soundId, _currentBlock);
}
+void LoLEngine::processMagicHeal(int charNum, int points) {
+ if (!_healOverlay) {
+ _healOverlay = new uint8[256];
+ _screen->generateGrayOverlay(_screen->getPalette(1), _healOverlay, 52, 22, 20, 0, 256, true);
+ }
+
+ const uint8 *healShpFrames = 0;
+ const uint8 *healiShpFrames = 0;
+ bool resetFlag = false;
+ int maxDiff = 0;
+
+ if (points == 0) {
+ maxDiff = 25;
+ healShpFrames = _healShapeFrames;
+ healiShpFrames = _healShapeFrames + 32;
+
+ } else if (points == 1) {
+ maxDiff = 45;
+ healShpFrames = _healShapeFrames + 16;
+ healiShpFrames = _healShapeFrames + 48;
+
+ } else if (points > 3) {
+ resetFlag = true;
+ maxDiff = points;
+ healShpFrames = _healShapeFrames + 16;
+ healiShpFrames = _healShapeFrames + 64;
+
+ } else {
+ resetFlag = true;
+ maxDiff = 10000;
+ healShpFrames = _healShapeFrames + 16;
+ healiShpFrames = _healShapeFrames + 64;
+
+ }
+
+ int ch = 0;
+ int n = 4;
+
+ if (charNum != -1){
+ ch = charNum;
+ n = charNum + 1;
+ }
+
+ charNum = ch;
+
+ uint16 pX[4];
+ uint16 pY = 138;
+ uint16 diff[4];
+ uint16 pts[4];
+ memset(pts, 0, sizeof(pts));
+
+ while (charNum < n) {
+ if (!(_characters[charNum].flags & 1))
+ continue;
+
+ pX[charNum] = _activeCharsXpos[charNum] - 6;
+ _characters[charNum].damageSuffered = 0;
+ int dmg = _characters[charNum].hitPointsMax - _characters[charNum].hitPointsCur;
+ diff[charNum] = (dmg < maxDiff) ? dmg : maxDiff;
+ _screen->copyRegion(pX[charNum], pY, charNum * 77, 32, 77, 44, 0, 2, Screen::CR_NO_P_CHECK);
+ charNum++;
+ }
+
+ int cp = _screen->setCurPage(2);
+ snd_playSoundEffect(68, -1);
+
+ for (int i = 0; i < 16; i++) {
+ _smoothScrollTimer = _system->getMillis() + 4 * _tickLength;
+
+ for (charNum = ch; charNum < n; charNum++) {
+ if (!(_characters[charNum].flags & 1))
+ continue;
+
+ _screen->copyRegion(charNum * 77, 32, pX[charNum], pY, 77, 44, 2, 2, Screen::CR_NO_P_CHECK);
+
+ pts[charNum] &= 0xff;
+ pts[charNum] += ((diff[charNum] << 8) / 16);
+ increaseCharacterHitpoints(ch, pts[charNum] / 256, true);
+ gui_drawCharPortraitWithStats(charNum);
+
+ _screen->drawShape(2, _healShapes[healShpFrames[i]], pX[charNum], pY, 0, 0x1000, _trueLightTable1, _trueLightTable2);
+ _screen->fillRect(0, 0, 31, 31, 0);
+
+ _screen->drawShape(_screen->_curPage, _healiShapes[healiShpFrames[i]], 0, 0, 0, 0);
+ _screen->applyOverlaySpecial(_screen->_curPage, 0, 0, 2, pX[charNum] + 7, pY + 6, 32, 32, 0, 0, _healOverlay);
+
+ _screen->copyRegion(pX[charNum], pY, pX[charNum], pY, 77, 44, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ }
+
+ while ((int)(_smoothScrollTimer - _system->getMillis()) > 0) {
+ updateInput();
+ delay(_tickLength);
+ }
+ }
+
+ for (charNum = ch; charNum < n; charNum++) {
+ if (!(_characters[charNum].flags & 1))
+ 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);
+
+ gui_drawCharPortraitWithStats(charNum);
+ _screen->copyRegion(pX[charNum], pY, pX[charNum], pY, 77, 44, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ }
+
+ _screen->setCurPage(cp);
+ updateDrawPage2();
+}
+
bool LoLEngine::notEnoughMagic(int charNum, int spellNum, int spellLevel) {
if (_spellProperties[spellNum].mpRequired[spellLevel] > _characters[charNum].magicPointsCur) {
if (characterSays(0x4043, _characters[charNum].id, true))
@@ -1833,6 +2138,8 @@ bool LoLEngine::notEnoughMagic(int charNum, int spellNum, int spellLevel) {
return false;
}
+// fight
+
int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) {
if (target == -1)
return 0;
@@ -1879,28 +2186,440 @@ int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) {
}
int LoLEngine::calcInflictableDamage(int16 attacker, int16 target, int hitType) {
- const uint16 *s = getCharacterOrMonsterStats(attacker);
+ const uint16 *s = getCharacterOrMonsterItemsMight(attacker);
- int res = 0;
+ // The original code looks somewhat like the commented out part of the next line.
+ // In the end the value is always set to zero. I do not know whether this is done on purpose or not.
+ // It might be a bug in the original code.
+ int res = 0/*attacker & 0x8000 ? 0 : _characters[attacker].might*/;
for (int i = 0; i < 8; i++)
- res += calcInflictableDamagePerStat(attacker, target, s[2 + i], i, hitType);
+ res += calcInflictableDamagePerItem(attacker, target, s[i], i, hitType);
return res;
}
-void LoLEngine::battleHit_sub2(int16 target, int damageInflicted, int16 attacker, uint32 b) {
+int LoLEngine::inflictDamage(int16 target, int damage, int16 attacker, int skill, int deathFlag) {
+ MonsterInPlay *m = 0;
+ LoLCharacter *c = 0;
+
+ if (target & 0x8000) {
+ m = &_monsters[target & 0x7fff];
+ if (m->mode >= 13)
+ return 0;
+
+ if (damage > 0) {
+ m->hitPoints -= damage;
+ m->damageReceived = 0x8000 | damage;
+ m->flags |= 0x10;
+ m->hitOffsX = _rnd.getRandomNumberRng(1, 24);
+ m->hitOffsX -= 12;
+ m->hitOffsY = _rnd.getRandomNumberRng(1, 24);
+ m->hitOffsY -= 12;
+ m->hitPoints = CLIP<int16>(m->hitPoints, 0, m->properties->hitPoints);
+
+ if (!(attacker & 0x8000))
+ applyMonsterDefenseSkill(m, attacker, deathFlag, skill, damage);
+
+ snd_queueEnvironmentalSoundEffect(m->properties->sounds[2], m->block);
+ checkSceneUpdateNeed(m->block);
+
+ if (m->hitPoints <= 0) {
+ m->hitPoints = 0;
+ if (!(attacker & 0x8000))
+ increaseExperience(attacker, skill, m->properties->hitPoints);
+ setMonsterMode(m, 13);
+ }
+ } else {
+ m->hitPoints -= damage;
+ m->hitPoints = CLIP<int16>(m->hitPoints, 1, m->properties->hitPoints);
+ }
+
+ } else {
+ c = &_characters[target];
+ if (!(c->flags & 1) || (c->flags & 8))
+ return 0;
+
+ if (!(c->flags & 0x1000))
+ snd_playSoundEffect(c->screamSfx, -1);
+
+ setTemporaryFaceFrame(target, 6, 4, 0);
+
+ // check for equipped cloud ring
+ if (deathFlag == 4 && itemEquipped(target, 229))
+ damage >>= 2;
+
+ setCharacterMagicOrHitPoints(target, 0, -damage, 1);
+
+ if (c->hitPointsCur <= 0) {
+ characterHitpointsZero(target, deathFlag);
+ } else {
+ _characters[target].damageSuffered = damage;
+ setCharacterUpdateEvent(target, 2, 4, 1);
+ }
+ gui_drawCharPortraitWithStats(target);
+ }
+
+ if (!(attacker & 0x8000)) {
+ if (!skill)
+ _characters[attacker].weaponHit = damage;
+ increaseExperience(attacker, skill, damage);
+ }
+
+ return damage;
+}
+
+void LoLEngine::characterHitpointsZero(int16 charNum, int deathFlag) {
+ LoLCharacter *c = &_characters[charNum];
+ c->hitPointsCur = 0;
+ c->flags |= 8;
+ resetCharacterState(c, 1, 5);
+ _partyDeathFlag = deathFlag;
+}
+
+void LoLEngine::resetCharacterState(LoLCharacter *c, int first, int last) {
+ for (int i = first; i <= last; i++) {
+ switch (i - 1) {
+ case 0:
+ c->weaponHit = 0;
+ break;
+
+ case 1:
+ c->damageSuffered = 0;
+ break;
+
+ case 2:
+ c->flags &= 0xffbf;
+ break;
+
+ case 3:
+ c->flags &= 0xff7f;
+ break;
+
+ case 4:
+ c->flags &= 0xfeff;
+ break;
+
+ case 6:
+ c->flags &= 0xefff;
+ break;
+
+ default:
+ break;
+ }
+
+ for (int ii = 0; ii < 5; ii++) {
+ if (i != c->characterUpdateEvents[ii])
+ continue;
+
+ c->characterUpdateEvents[ii] = 0;
+ c->characterUpdateDelay[ii] = 0;
+ }
+ }
+ _timer3Para = 1;
+ _timer->enable(3);
}
-void LoLEngine::battleHit_sub3(MonsterInPlay *monster, int16 target, int16 damageInflicted) {
+int LoLEngine::calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 itemMight, int index, int hitType) {
+ int dmg = (attacker == -1) ? 0x100 : getCharacterOrMonsterStats(attacker)[1];
+ const uint16 *st_t = getCharacterOrMonsterProtectionAgainstItems(target);
+
+ dmg = (dmg * itemMight) >> 8;
+ if (!dmg)
+ return 0;
+
+ if (!(attacker & 0x8000)) {
+ dmg = (dmg * _characters[attacker].totalMightModifier) >> 8;
+ if (!dmg)
+ return 0;
+ }
+
+ int d = (index & 0x80) ? st_t[7] : st_t[index];
+ int r = (dmg * ABS(d)) >> 8;
+ dmg = d < 0 ? -r : r;
+
+ if (hitType == 2 || !dmg)
+ return (dmg == 1) ? 2 : dmg;
+
+ int p = (calculateProtection(target) << 7) / dmg;
+ if (p > 217)
+ p = 217;
+
+ d = 256 - p;
+ r = (dmg * ABS(d)) >> 8;
+ dmg = d < 0 ? -r : r;
+
+ return (dmg < 2) ? 2 : dmg;
}
-int LoLEngine::calcInflictableDamagePerStat(int16 attacker, int16 target, uint16 stat2m, int index, int hitType) {
- return 1;
+void LoLEngine::checkForPartyDeath() {
+
}
-uint16 LoLEngine::getClosestMonster(int x, int y) {
+void LoLEngine::applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage) {
+ if (_rnd.getRandomNumberRng(1, 100) > monster->properties->attackSkillChance)
+ return;
+
+ int t = 0;
+
+ switch (monster->properties->attackSkillType - 1) {
+ case 0:
+ t = removeCharacterItem(target, 0x7ff);
+ if (t) {
+ giveItemToMonster(monster, t);
+ if (characterSays(0x4019, _characters[target].id, true))
+ _txt->printMessage(6, getLangString(0x4019));
+ }
+ break;
+
+ case 1:
+ // poison character
+ paralyzePoisonCharacter(target, 0x80, 0x88, 100, 1);
+ break;
+
+ case 2:
+ t = removeCharacterItem(target, 0x20);
+ if (t) {
+ deleteItem(t);
+ if (characterSays(0x401b, _characters[target].id, true))
+ _txt->printMessage(6, getLangString(0x401b));
+ }
+ break;
+
+ case 3:
+ t = removeCharacterItem(target, 0x0f);
+ if (t) {
+ if (characterSays(0x401e, _characters[target].id, true))
+ _txt->printMessage(6, getLangString(0x401e), _characters[target].name);
+ setItemPosition(t, monster->x, monster->y, 0, 1);
+ }
+ break;
+
+ case 5:
+ if (_characters[target].magicPointsCur <= 0)
+ return;
+
+ monster->hitPoints += _characters[target].magicPointsCur;
+ _characters[target].magicPointsCur = 0;
+ gui_drawCharPortraitWithStats(target);
+ if (characterSays(0x4020, _characters[target].id, true))
+ _txt->printMessage(6, getLangString(0x4020), _characters[target].name);
+ break;
+
+ case 7:
+ stunCharacter(target);
+ break;
+
+ case 8:
+ monster->hitPoints += damage;
+ if (monster->hitPoints > monster->properties->hitPoints)
+ monster->hitPoints = monster->properties->hitPoints;
+
+ break;
+
+ case 9:
+ // paralyze party (spider web)
+ paralyzePoisonAllCharacters(0x40, 0x48, 100);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void LoLEngine::applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int deathFlag, int skill, int damage) {
+ if (_rnd.getRandomNumberRng(1, 100) > monster->properties->defenseSkillChance)
+ return;
+
+ int itm = 0;
+
+ switch (monster->properties->defenseSkillType - 1) {
+ case 0:
+ case 1:
+ if ((deathFlag & 0x3f) == 2 || skill)
+ return;
+
+ for (int i = 0; i < 3 ; i++) {
+ itm = _characters[attacker].items[i];
+ if (!itm)
+ continue;
+ if ((_itemProperties[_itemsInPlay[itm].itemPropertyIndex].protection & 0x3f) != deathFlag)
+ continue;
+
+ removeCharacterItem(attacker, 0x7fff);
+
+ if (monster->properties->defenseSkillType == 1) {
+ deleteItem(itm);
+ if (characterSays(0x401d, _characters[attacker].id, true))
+ _txt->printMessage(6, getLangString(0x401d));
+ } else {
+ giveItemToMonster(monster, itm);
+ if (characterSays(0x401c, _characters[attacker].id, true))
+ _txt->printMessage(6, getLangString(0x401c));
+ }
+ }
+ break;
+
+ case 2:
+ if (!(deathFlag & 0x80))
+ return;
+ monster->flags |= 8;
+ monster->direction = calcMonsterDirection(monster->x, monster->y, _partyPosX, _partyPosY) ^ 4;
+ setMonsterMode(monster, 9);
+ monster->fightCurTick = 30;
+ break;
+
+ case 3:
+ if (deathFlag != 3)
+ return;
+ monster->hitPoints += damage;
+ if (monster->hitPoints > monster->properties->hitPoints)
+ monster->hitPoints = monster->properties->hitPoints;
+
+
+ break;
+
+ case 4:
+ if (!(deathFlag & 0x80))
+ return;
+ monster->hitPoints += damage;
+ if (monster->hitPoints > monster->properties->hitPoints)
+ monster->hitPoints = monster->properties->hitPoints;
+ break;
+
+ case 5:
+ if ((deathFlag & 0x84) == 0x84)
+ monster->numDistAttacks++;
+ break;
+
+ default:
+ break;
+ }
+}
+
+int LoLEngine::removeCharacterItem(int charNum, int itemFlags) {
+ for (int i = 0; i < 11; i++) {
+ int s = _characters[charNum].items[i];
+ if (!((1 << i) & itemFlags) || !s)
+ continue;
+
+ _characters[charNum].items[i] = 0;
+ runItemScript(charNum, s, 0x100, 0, 0);
+
+ return s;
+ }
+
+ return 0;
+}
+
+bool LoLEngine::paralyzePoisonCharacter(int charNum, int typeFlag, int immunityFlags, int hitChance, int redraw) {
+ if (!(_characters[charNum].flags & 1) || (_characters[charNum].flags & immunityFlags))
+ return 0;
+
+ if ((int)_rnd.getRandomNumberRng(1, 100) > hitChance)
+ return 0;
+
+ int r = false;
+
+ if (typeFlag == 0x40) {
+ _characters[charNum].flags |= 0x40;
+ setCharacterUpdateEvent(charNum, 3, 3600, 1);
+ r = true;
+
+ // check for bezel ring
+ } else if (typeFlag == 0x80 && !itemEquipped(charNum, 225)) {
+ _characters[charNum].flags |= 0x80;
+ setCharacterUpdateEvent(charNum, 4, 10, 1);
+ if (characterSays(0x4021, _characters[charNum].id, true))
+ _txt->printMessage(6, getLangString(0x4021), _characters[charNum].name);
+ r = true;
+
+ } else if (typeFlag == 0x1000) {
+ _characters[charNum].flags |= 0x1000;
+ setCharacterUpdateEvent(charNum, 7, 120, 1);
+ r = true;
+ }
+
+ if (r && redraw)
+ gui_drawCharPortraitWithStats(charNum);
+
+ return r;
+}
+
+void LoLEngine::paralyzePoisonAllCharacters(int typeFlag, int immunityFlags, int hitChance) {
+ bool r = false;
+ for (int i = 0; i < 4; i++) {
+ if (paralyzePoisonCharacter(i, typeFlag, immunityFlags, hitChance, 0))
+ r = true;
+ }
+ if (r)
+ gui_drawAllCharPortraitsWithStats();
+}
+
+void LoLEngine::stunCharacter(int charNum) {
+ if (!(_characters[charNum].flags & 1) || (_characters[charNum].flags & 0x108))
+ return;
+
+ _characters[charNum].flags |= 0x100;
+
+ setCharacterUpdateEvent(charNum, 5, 20, 1);
+ gui_drawCharPortraitWithStats(charNum);
+
+ _txt->printMessage(6, getLangString(0x4026), _characters[charNum].name);
+}
+
+void LoLEngine::level11specialUnk() {
+
+}
+
+void LoLEngine::distObj1Sub(int a, int b, int c, int d) {
+
+}
+
+void LoLEngine::launchMagicViper() {
+
+}
+
+void LoLEngine::attackWall(int a, int b) {
+
+}
+
+uint16 LoLEngine::getNearestMonsterFromCharacter(int charNum) {
+ return getNearestMonsterFromCharacterForBlock(calcNewBlockPosition(_currentBlock, _currentDirection), charNum);
+}
+
+uint16 LoLEngine::getNearestMonsterFromCharacterForBlock(int block, int charNum) {
+ uint16 cX = 0;
+ uint16 cY = 0;
+
+ uint16 id = 0xffff;
+ int minDist = 0x7fff;
+
+ calcCoordinatesForSingleCharacter(charNum, cX, cY);
+
+ int o = _levelBlockProperties[block].assignedObjects;
+
+ while (o & 0x8000) {
+ MonsterInPlay *m = &_monsters[o & 0x7fff];
+ if (m->mode >= 13) {
+ o = m->nextAssignedObject;
+ continue;
+ }
+
+ int d = ABS(cX - m->x) + ABS(cY - m->y);
+ if (d < minDist) {
+ minDist = d;
+ id = o;
+ }
+
+ o = m->nextAssignedObject;
+ }
+
+ return id;
+}
+
+uint16 LoLEngine::getNearestMonsterFromPos(int x, int y) {
uint16 id = 0xffff;
int minDist = 0x7fff;
@@ -1918,7 +2637,7 @@ uint16 LoLEngine::getClosestMonster(int x, int y) {
return id;
}
-uint16 LoLEngine::getClosestPartyMember(int x, int y) {
+uint16 LoLEngine::getNearestPartyMemberFromPos(int x, int y) {
uint16 id = 0xffff;
int minDist = 0x7fff;
@@ -1940,50 +2659,6 @@ uint16 LoLEngine::getClosestPartyMember(int x, int y) {
return id;
}
-void LoLEngine::generateTempData() {
- int l = _currentLevel - 1;
- if (_lvlTempData[l]) {
- delete[] _lvlTempData[l]->wallsXorData;
- delete[] _lvlTempData[l]->flags;
- delete[] _lvlTempData[l]->monsters;
- delete[] _lvlTempData[l]->flyingObjects;
- delete _lvlTempData[l];
- }
-
- _lvlTempData[l] = new LevelTempData;
-
- _lvlTempData[l]->wallsXorData = new uint8[4096];
- _lvlTempData[l]->flags = new uint8[1024];
- _lvlTempData[l]->monsters = new MonsterInPlay[30];
- _lvlTempData[l]->flyingObjects = new FlyingObject[8];
-
- char filename[13];
- snprintf(filename, sizeof(filename), "LEVEL%d.CMZ", _currentLevel);
-
- _screen->loadBitmap(filename, 3, 3, 0);
- const uint8 *p = _screen->getCPagePtr(2);
- uint16 len = READ_LE_UINT16(p + 4);
- p += 6;
-
- memset(_lvlTempData[l]->wallsXorData, 0, 4096);
- memset(_lvlTempData[l]->flags, 0, 1024);
- uint8 *d = _lvlTempData[l]->wallsXorData;
- uint8 *df = _lvlTempData[l]->flags;
-
- for (int i = 0; i < 1024; i++) {
- for (int ii = 0; ii < 4; ii++)
- *d++ = p[i * len + ii] ^ _levelBlockProperties[i].walls[ii];
- *df++ = _levelBlockProperties[i].flags;
- }
-
- memcpy(_lvlTempData[l]->monsters, _monsters, sizeof(MonsterInPlay) * 30);
- memcpy(_lvlTempData[l]->flyingObjects, _flyingObjects, sizeof(FlyingObject) * 8);
-
- _lvlTempData[l]->monsterDifficulty =_monsterDifficulty;
-
- _hasTempDataFlags |= (1 << l);
-}
-
// magic atlas
void LoLEngine::displayAutomap() {
@@ -2056,7 +2731,7 @@ void LoLEngine::displayAutomap() {
exitAutomap = true;
}
- delay (_tickLength);
+ delay(_tickLength);
}
_screen->loadFont(Screen::FID_9_FNT, "FONT9P.FNT");
@@ -2468,6 +3143,50 @@ void LoLEngine::printMapExitButtonText() {
_screen->setCurPage(cp);
}
+void LoLEngine::generateTempData() {
+ int l = _currentLevel - 1;
+ if (_lvlTempData[l]) {
+ delete[] _lvlTempData[l]->wallsXorData;
+ delete[] _lvlTempData[l]->flags;
+ delete[] _lvlTempData[l]->monsters;
+ delete[] _lvlTempData[l]->flyingObjects;
+ delete _lvlTempData[l];
+ }
+
+ _lvlTempData[l] = new LevelTempData;
+
+ _lvlTempData[l]->wallsXorData = new uint8[4096];
+ _lvlTempData[l]->flags = new uint8[1024];
+ _lvlTempData[l]->monsters = new MonsterInPlay[30];
+ _lvlTempData[l]->flyingObjects = new FlyingObject[8];
+
+ char filename[13];
+ snprintf(filename, sizeof(filename), "LEVEL%d.CMZ", _currentLevel);
+
+ _screen->loadBitmap(filename, 3, 3, 0);
+ const uint8 *p = _screen->getCPagePtr(2);
+ uint16 len = READ_LE_UINT16(p + 4);
+ p += 6;
+
+ memset(_lvlTempData[l]->wallsXorData, 0, 4096);
+ memset(_lvlTempData[l]->flags, 0, 1024);
+ uint8 *d = _lvlTempData[l]->wallsXorData;
+ uint8 *df = _lvlTempData[l]->flags;
+
+ for (int i = 0; i < 1024; i++) {
+ for (int ii = 0; ii < 4; ii++)
+ *d++ = p[i * len + ii] ^ _levelBlockProperties[i].walls[ii];
+ *df++ = _levelBlockProperties[i].flags;
+ }
+
+ memcpy(_lvlTempData[l]->monsters, _monsters, sizeof(MonsterInPlay) * 30);
+ memcpy(_lvlTempData[l]->flyingObjects, _flyingObjects, sizeof(FlyingObject) * 8);
+
+ _lvlTempData[l]->monsterDifficulty =_monsterDifficulty;
+
+ _hasTempDataFlags |= (1 << l);
+}
+
} // end of namespace Kyra
#endif // ENABLE_LOL
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index f578c22f57..ba97167ede 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -50,18 +50,11 @@ struct LoLCharacter {
int16 id;
uint8 curFaceFrame;
uint8 defaultFaceFrame;
- uint8 field_12;
+ uint8 screamSfx;
const uint16 *defaultModifiers;
uint16 itemsMight[8];
- uint16 field_27[2];
- uint8 field_2B;
- uint16 field_2C;
- uint16 field_2E;
- uint16 field_30;
- uint16 field_32;
- uint16 field_34;
- uint8 field_36;
- uint16 itemsProtection;
+ uint16 protectionAgainstItems[8];
+ uint16 itemProtection;
int16 hitPointsCur;
uint16 hitPointsMax;
int16 magicPointsCur;
@@ -78,8 +71,8 @@ struct LoLCharacter {
uint8 skillLevels[3];
uint8 skillModifiers[3];
int32 experiencePts[3];
- uint8 arrayUnk2[5];
- uint8 arrayUnk1[5];
+ uint8 characterUpdateEvents[5];
+ uint8 characterUpdateDelay[5];
};
struct SpellProperty {
@@ -100,17 +93,22 @@ struct LevelBlockProperty {
struct MonsterProperty {
uint8 shapeIndex;
uint8 maxWidth;
- uint16 fightingStats[10];
- uint16 unk2[8];
- uint16 unk3[8];
+ uint16 fightingStats[9];
+ uint16 itemsMight[8];
+ uint16 protectionAgainstItems[8];
uint16 itemProtection;
- uint16 might;
+ uint16 hitPoints;
uint8 speedTotalWaitTicks;
uint8 skillLevel;
uint16 flags;
uint16 unk5;
- uint16 unk6[5];
- uint8 unk7[4];
+ uint16 numDistAttacks;
+ uint16 numDistWeapons;
+ uint16 distWeapons[3];
+ uint8 attackSkillChance;
+ uint8 attackSkillType;
+ uint8 defenseSkillChance;
+ uint8 defenseSkillType;
uint8 sounds[3];
};
@@ -118,15 +116,15 @@ struct MonsterInPlay {
uint16 nextAssignedObject;
uint16 nextDrawObject;
uint8 flyingHeight;
- uint16 blockPropertyIndex;
+ uint16 block;
uint16 x;
uint16 y;
int8 shiftStep;
uint16 destX;
uint16 destY;
uint8 destDirection;
- uint8 anon8;
- uint8 anonh;
+ int8 hitOffsX;
+ int8 hitOffsY;
uint8 currentSubFrame;
uint8 mode;
@@ -135,15 +133,15 @@ struct MonsterInPlay {
uint8 direction;
uint8 facing;
uint16 flags;
- uint8 field_1B;
- uint8 field_1C;
- int16 might;
+ uint16 damageReceived;
+ //uint8 field_1C;
+ int16 hitPoints;
uint8 speedTick;
uint8 type;
MonsterProperty *properties;
- uint8 field_25;
- uint8 field_26;
- uint8 field_27;
+ uint8 numDistAttacks;
+ uint8 curDistWeapon;
+ int8 distAttackTick;
uint16 assignedItems;
uint8 field_2A[4];
};
@@ -152,15 +150,15 @@ struct ItemInPlay {
uint16 nextAssignedObject;
uint16 nextDrawObject;
uint8 flyingHeight;
- uint16 blockPropertyIndex;
+ uint16 block;
uint16 x;
uint16 y;
int8 level;
uint16 itemPropertyIndex;
uint16 shpCurFrame_flg;
uint8 destDirection;
- uint8 anon8;
- uint8 anonh;
+ int8 hitOffsX;
+ int8 hitOffsY;
uint8 currentSubFrame;
};
@@ -213,8 +211,8 @@ struct OpenDoorState {
struct FlyingObject {
uint8 enable;
- uint8 a;
- uint16 charNum;
+ uint8 objectType;
+ uint16 attackerId;
uint16 item;
uint16 x;
uint16 y;
@@ -324,6 +322,8 @@ private:
int getCharSelection();
int selectionCharAccept();
+
+ void showStarcraftLogo();
int _charSelection;
int _charSelectionInfoResult;
@@ -354,16 +354,17 @@ private:
void timerProcessDoors(int timerNum);
void timerProcessMonsters(int timerNum);
- void timerSub3(int timerNum);
+ void timerSpecialCharacterUpdate(int timerNum);
void timerProcessFlyingObjects(int timerNum);
void timerRunSceneAnimScript(int timerNum);
- void timerSub6(int timerNum);
+ void timerRegeneratePoints(int timerNum);
void timerUpdatePortraitAnimations(int skipUpdate);
void timerUpdateLampState(int timerNum);
void timerFadeMessageText(int timerNum);
static const uint8 _clock2Timers[];
static const uint8 _numClock2Timers;
+ int _timer3Para;
// sound
void loadTalkFile(int index);
@@ -373,6 +374,7 @@ private:
void snd_stopSpeech(bool setFlag);
void snd_playSoundEffect(int track, int volume);
void snd_processEnvironmentalSoundEffect(int soundId, int block);
+ void snd_queueEnvironmentalSoundEffect(int soundId, int block);
void snd_loadSoundFile(int track);
int snd_playTrack(int track);
int snd_stopMusic();
@@ -387,7 +389,11 @@ private:
char _curMusicFileExt;
int _environmentSfx;
int _environmentSfxVol;
- int _environmentSfxDistThreshold;
+ int _envSfxDistThreshold;
+ bool _envSfxUseQueue;
+ int _envSfxNumTracksInQueue;
+ uint16 _envSfxQueuedTracks[10];
+ uint16 _envSfxQueuedBlocks[10];
int _nextSpeechId;
int _nextSpeaker;
@@ -405,8 +411,8 @@ private:
int _ingameGMSoundIndexSize;
const uint8 *_ingameMT32SoundIndex;
int _ingameMT32SoundIndexSize;
- /*const uint8 *_ingameADLSoundIndex;
- int _ingameADLSoundIndexSize;*/
+
+ AudioDataStruct _soundData[3];
// gui
void gui_drawPlayField();
@@ -597,15 +603,18 @@ private:
int olol_fadeSequencePalette(EMCState *script);
int olol_redrawPlayfield(EMCState *script);
int olol_loadNewLevel(EMCState *script);
+ int olol_getNearestMonsterFromCharacter(EMCState *script);
int olol_dummy0(EMCState *script);
int olol_loadMonsterProperties(EMCState *script);
int olol_battleHitSkillTest(EMCState *script);
+ int olol_inflictDamage(EMCState *script);
int olol_moveMonster(EMCState *script);
int olol_dialogueBox(EMCState *script);
int olol_giveTakeMoney(EMCState *script);
int olol_checkMoney(EMCState *script);
int olol_setScriptTimer(EMCState *script);
int olol_createHandItem(EMCState *script);
+ int olol_playAttackSound(EMCState *script);
int olol_characterJoinsParty(EMCState *script);
int olol_loadTimScript(EMCState *script);
int olol_runTimScript(EMCState *script);
@@ -619,18 +628,23 @@ private:
int olol_processDialogue(EMCState *script);
int olol_stopTimScript(EMCState *script);
int olol_getWallFlags(EMCState *script);
- int olol_changeMonsterSettings(EMCState *script);
+ int olol_changeMonsterStat(EMCState *script);
+ int olol_getMonsterStat(EMCState *script);
int olol_playCharacterScriptChat(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_stopCharacterSpeech(EMCState *script);
int olol_setPaletteBrightness(EMCState *script);
+ int olol_calcInflictableDamage(EMCState *script);
+ int olol_getInflictedDamage(EMCState *script);
int olol_checkForCertainPartyMember(EMCState *script);
int olol_printMessage(EMCState *script);
int olol_deleteLevelItem(EMCState *script);
+ int olol_calcInflictableDamagePerItem(EMCState *script);
int olol_objectLeavesLevel(EMCState *script);
int olol_playDialogueTalkText(EMCState *script);
int olol_checkMonsterTypeHostility(EMCState *script);
@@ -638,7 +652,7 @@ private:
int olol_dummy1(EMCState *script);
int olol_suspendMonster(EMCState *script);
int olol_setDoorState(EMCState *script);
- int olol_processButtonClick(EMCState *script);
+ int olol_resetTimDialogueState(EMCState *script);
int olol_savePage5(EMCState *script);
int olol_restorePage5(EMCState *script);
int olol_initDialogueSequence(EMCState *script);
@@ -699,6 +713,7 @@ private:
// Maybe we can someday reduce the size.
char *getLangString(uint16 id);
uint8 *getTableEntry(uint8 *buffer, uint16 id);
+ void decodeSjis(const char *src, char *dst);
static const char * const _languageExt[];
@@ -728,8 +743,6 @@ private:
int _numThrownShapes;
uint8 **_effectShapes;
int _numEffectShapes;
- uint8 **_fireballShapes;
- int _numFireballShapes;
const int8 *_gameShapeMap;
int _gameShapeMapSize;
@@ -740,8 +753,8 @@ private:
// characters
bool addCharacter(int id);
- void setFaceFrames(int charNum, int defaultFrame, int unk2, int redraw);
- void setFaceFramesUnkArrays(int charNum, int unk1, int unk2, int unk3);
+ void setTemporaryFaceFrame(int charNum, int frame, int updateDelay, int redraw);
+ void setCharacterUpdateEvent(int charNum, int updateType, int updateDelay, int overwrite);
int countActiveCharacters();
void loadCharFaceShapes(int charNum, int id);
void calcCharPortraitXpos();
@@ -756,7 +769,9 @@ private:
int calculateCharacterStats(int charNum, int index);
int calculateProtection(int index);
+ void setCharacterMagicOrHitPoints(int charNum, int type, int points, int mode);
void increaseExperience(int charNum, int skill, uint32 points);
+ void increaseCharacterHitpoints(int charNum, int points, bool unk);
LoLCharacter *_characters;
uint16 _activeCharsXpos[3];
@@ -1023,15 +1038,16 @@ private:
ItemInPlay *findObject(uint16 index);
void runItemScript(int charNum, int item, int sub, int next, int reg4);
void setHandItem(uint16 itemIndex);
+ bool itemEquipped(int charNum, uint16 itemType);
void setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, int b);
void removeLevelItem(int item, int block);
- bool throwItem(int a, int item, int x, int y, int flyingHeight, int direction, int, int charNum, int c);
+ bool launchObject(int objectType, int item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c);
void endObjectFlight(FlyingObject *t, int x, int y, int objectOnNextBlock);
void processObjectFlight(FlyingObject *t, int x, int y);
void updateObjectFlightPosition(FlyingObject *t);
void objectFlightProcessHits(FlyingObject *t, int x, int y, int objectOnNextBlock);
- void updateFlyingObjects(FlyingObject *t);
+ void updateFlyingObject(FlyingObject *t);
void assignItemToBlock(uint16 *assignedBlockObjects, int id);
int checkDrawObjectSpace(int itemX, int itemY, int partyX, int partyY);
@@ -1088,6 +1104,9 @@ private:
int calcMonsterSkillLevel(int id, int a);
bool checkBlockOccupiedByParty(int x, int y, int testFlag);
const uint16 *getCharacterOrMonsterStats(int id);
+ uint16 *getCharacterOrMonsterItemsMight(int id);
+ uint16 *getCharacterOrMonsterProtectionAgainstItems(int id);
+
void drawBlockObjects(int blockArrayIndex);
void drawMonster(uint16 id);
int getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags);
@@ -1107,7 +1126,7 @@ private:
void chasePartyWithCloseAttacks(MonsterInPlay *monster);
int walkMonsterCalcNextStep(MonsterInPlay *monster);
int getMonsterDistance(uint16 block1, uint16 block2);
- int walkMonster_s3(uint16 monsterBlock, int direction, int distance, uint16 curBlock);
+ int checkForPossibleDistanceAttack(uint16 monsterBlock, int direction, int distance, uint16 curBlock);
int walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk);
void getNextStepCoords(int16 monsterX, int16 monsterY, int &newX, int &newY, uint16 direction);
void rearrangeAttackingMonster(MonsterInPlay *monster);
@@ -1143,25 +1162,16 @@ private:
uint8 getRandomNumberSpecial();
uint8 _compassBroken;
- uint8 _unkBt2;
+ uint8 _drainMagic;
uint16 _unkWordArraySize8[8];
uint8 *_pageBuffer1;
uint8 *_pageBuffer2;
uint32 _rndSpecial;
- // fight
- int battleHitSkillTest(int16 attacker, int16 target, int skill);
- int calcInflictableDamage(int16 attacker, int16 target, int hitType);
- void battleHit_sub2(int16 target, int damageInflicted, int16 attacker, uint32 b);
- void battleHit_sub3(MonsterInPlay *monster, int16 target, int16 damageInflicted);
- int calcInflictableDamagePerStat(int16 attacker, int16 target, uint16 stat2m, int index, int hitType);
-
- uint16 getClosestMonster(int x, int y);
- uint16 getClosestPartyMember(int x, int y);
-
// spells
- bool notEnoughMagic(int charNum, int spellNum, int spellLevel);
+ void processMagicHeal(int charNum, int points);
+ bool notEnoughMagic(int charNum, int spellNum, int spellLevel);
int8 _availableSpells[7];
int _selectedSpell;
@@ -1170,17 +1180,46 @@ private:
int _subMenuIndex;
uint16 _unkIceSHpFlag;
- // unneeded
- void setWalkspeed(uint8) {}
- void removeHandItem() {}
- bool lineIsPassable(int, int) { return false; }
+ uint8 *_healOverlay;
- // save
- Common::Error loadGameState(int slot) { return Common::kNoError; }
- Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail) { return Common::kNoError; }
+ uint8 **_fireballShapes;
+ int _numFireballShapes;
+ uint8 **_healShapes;
+ int _numHealShapes;
+ uint8 **_healiShapes;
+ int _numHealiShapes;
- void generateTempData();
- LevelTempData *_lvlTempData[28];
+ const uint8 *_healShapeFrames;
+ int _healShapeFramesSize;
+
+ // fight
+ int battleHitSkillTest(int16 attacker, int16 target, int skill);
+ int calcInflictableDamage(int16 attacker, int16 target, int hitType);
+ int inflictDamage(int16 target, int damage, int16 attacker, int skill, int deathFlag);
+ void characterHitpointsZero(int16 charNum, int a);
+ void resetCharacterState(LoLCharacter *c, int first, int last);
+ int calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 itemMight, int index, int hitType);
+ void checkForPartyDeath();
+
+ void applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage);
+ void applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int deathFlag, int skill, int damage);
+ int removeCharacterItem(int charNum, int itemFlags);
+ bool paralyzePoisonCharacter(int charNum, int typeFlag, int immunityFlags, int hitChance, int redraw);
+ void paralyzePoisonAllCharacters(int typeFlag, int immunityFlags, int hitChance);
+ void stunCharacter(int charNum);
+ void level11specialUnk();
+
+ void distObj1Sub(int a, int b, int c, int d);
+ void launchMagicViper();
+
+ void attackWall(int a, int b);
+
+ uint16 getNearestMonsterFromCharacter(int charNum);
+ uint16 getNearestMonsterFromCharacterForBlock(int block, int charNum);
+ uint16 getNearestMonsterFromPos(int x, int y);
+ uint16 getNearestPartyMemberFromPos(int x, int y);
+
+ int _partyDeathFlag;
// magic atlas
void displayAutomap();
@@ -1211,6 +1250,18 @@ private:
uint8 _automapTopLeftY;
static const int8 _mapCoords[12][4];
bool _mapUpdateNeeded;
+
+ // unneeded
+ void setWalkspeed(uint8) {}
+ void removeHandItem() {}
+ bool lineIsPassable(int, int) { return false; }
+
+ // save
+ Common::Error loadGameState(int slot) { return Common::kNoError; }
+ Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail) { return Common::kNoError; }
+
+ void generateTempData();
+ LevelTempData *_lvlTempData[28];
};
} // end of namespace Kyra
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 4e97853490..9b858831a2 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -286,6 +286,8 @@ enum kKyraResources {
lolMapCursorOvl,
lolMapStringId,
//lolMapPal,
+
+ lolHealShapeFrames,
#endif // ENABLE_LOL
kMaxResIDs
diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp
index 3548723610..d5ff36480c 100644
--- a/engines/kyra/saveload_lok.cpp
+++ b/engines/kyra/saveload_lok.cpp
@@ -163,7 +163,7 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) {
// it wasn't made sure that _curSfxFile was initialized
// so if it's out of bounds we just set it to 0.
if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
- if (_curSfxFile >= _soundData->_fileListLen || _curSfxFile < 0)
+ if (_curSfxFile >= _soundData->fileListLen || _curSfxFile < 0)
_curSfxFile = 0;
_sound->loadSoundFile(_curSfxFile);
}
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index e467749700..2508a3062a 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -105,9 +105,9 @@ void LoLEngine::addLevelItems() {
if (_itemsInPlay[i].level != _currentLevel)
continue;
- assignBlockObject(&_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].assignedObjects, i);
+ assignBlockObject(&_levelBlockProperties[_itemsInPlay[i].block].assignedObjects, i);
- _levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].direction = 5;
+ _levelBlockProperties[_itemsInPlay[i].block].direction = 5;
_itemsInPlay[i].nextDrawObject = 0;
}
}
@@ -259,8 +259,8 @@ void LoLEngine::restoreBlockTempData(int index) {
}
for (int i = 0; i < 30; i++) {
- if (_monsters[i].blockPropertyIndex) {
- _monsters[i].blockPropertyIndex = 0;
+ if (_monsters[i].block) {
+ _monsters[i].block = 0;
_monsters[i].properties = &_monsterProperties[_monsters[i].type];
placeMonster(&_monsters[i], _monsters[i].x, _monsters[i].y);
}
@@ -276,14 +276,14 @@ void LoLEngine::restoreTempDataAdjustMonsterStrength(int index) {
uint16 d = (_monsterModifiers[_lvlTempData[index]->monsterDifficulty] << 8) / _monsterModifiers[_monsterDifficulty];
for (int i = 0; i < 30; i++) {
- if (_monsters[i].mode >= 14 || _monsters[i].blockPropertyIndex == 0 || _monsters[i].might <= 0)
+ if (_monsters[i].mode >= 14 || _monsters[i].block == 0 || _monsters[i].hitPoints <= 0)
continue;
- _monsters[i].might = (d * _monsters[i].might) >> 8;
+ _monsters[i].hitPoints = (d * _monsters[i].hitPoints) >> 8;
if (_monsterDifficulty < _lvlTempData[index]->monsterDifficulty)
- _monsters[i].might++;
- if (_monsters[i].might == 0)
- _monsters[i].might = 1;
+ _monsters[i].hitPoints++;
+ if (_monsters[i].hitPoints == 0)
+ _monsters[i].hitPoints = 1;
}
}
@@ -470,7 +470,7 @@ void LoLEngine::resetItems(int flag) {
ItemInPlay *it = &_itemsInPlay[id];
it->level = _currentLevel;
- it->blockPropertyIndex = i;
+ it->block = i;
if (r)
r->nextAssignedObject = 0;
}
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 26b8e3a922..c505152b11 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -73,6 +73,8 @@ bool Screen::init() {
memset(_sjisOverlayPtrs, 0, sizeof(_sjisOverlayPtrs));
_useOverlays = false;
_useSJIS = false;
+ _use16ColorMode = _vm->gameFlags().use16ColorMode;
+
_sjisTempPage = _sjisFontData = 0;
if (_vm->gameFlags().useHiResOverlay) {
@@ -432,11 +434,13 @@ void Screen::getFadeParams(const uint8 *palette, int delay, int &delayInc, int &
int Screen::fadePalStep(const uint8 *palette, int diff) {
debugC(9, kDebugLevelScreen, "Screen::fadePalStep(%p, %d)", (const void *)palette, diff);
+ const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : (_use16ColorMode ? 16 : 256)) * 3;
+
uint8 fadePal[768];
- memcpy(fadePal, _screenPalette, 768);
+ memcpy(fadePal, _screenPalette, colors);
bool needRefresh = false;
- const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256) * 3;
+
for (int i = 0; i < colors; ++i) {
int c1 = palette[i];
int c2 = fadePal[i];
@@ -495,17 +499,35 @@ void Screen::setScreenPalette(const uint8 *palData) {
debugC(9, kDebugLevelScreen, "Screen::setScreenPalette(%p)", (const void *)palData);
const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256);
+
+ uint8 screenPal[256 * 4];
if (palData != _screenPalette)
memcpy(_screenPalette, palData, colors*3);
- uint8 screenPal[256 * 4];
- for (int i = 0; i < colors; ++i) {
- screenPal[4 * i + 0] = (palData[0] << 2) | (palData[0] & 3);
- screenPal[4 * i + 1] = (palData[1] << 2) | (palData[1] & 3);
- screenPal[4 * i + 2] = (palData[2] << 2) | (palData[2] & 3);
- screenPal[4 * i + 3] = 0;
- palData += 3;
+ if (_use16ColorMode && _vm->gameFlags().platform == Common::kPlatformPC98) {
+ for (int l = 0; l < 1024; l += 64) {
+ const uint8 *tp = palData;
+ for (int i = 0; i < 16; ++i) {
+ screenPal[l + 4 * i + 0] = palData[1];
+ screenPal[l + 4 * i + 1] = palData[0];
+ screenPal[l + 4 * i + 2] = palData[2];
+ screenPal[l + 4 * i + 3] = 0;
+ palData += 3;
+ }
+ palData = tp;
+ }
+ } else {
+ if (palData != _screenPalette)
+ memcpy(_screenPalette, palData, colors*3);
+ for (int i = 0; i < colors; ++i) {
+ screenPal[4 * i + 0] = (palData[0] << 2) | (palData[0] & 3);
+ screenPal[4 * i + 1] = (palData[1] << 2) | (palData[1] & 3);
+ screenPal[4 * i + 2] = (palData[2] << 2) | (palData[2] & 3);
+ screenPal[4 * i + 3] = 0;
+ palData += 3;
+ }
}
+
_system->setPalette(screenPal, 0, colors);
}
@@ -1242,7 +1264,9 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int
&Screen::drawShapePlotType13, // used by Kyra 1
&Screen::drawShapePlotType14, // used by Kyra 1 (invisibility)
&Screen::drawShapePlotType11_15, // used by Kyra 1 (invisibility)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ &Screen::drawShapePlotType20, // used by LoL (heal spell effect)
+ 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
&Screen::drawShapePlotType33, // used by LoL (blood spots on the floor)
0, 0, 0,
@@ -1683,7 +1707,6 @@ void Screen::drawShapePlotType0(uint8 *dst, uint8 cmd) {
}
void Screen::drawShapePlotType1(uint8 *dst, uint8 cmd) {
- // uint32 relOffs = dst - _dsDstPage;
for (int i = 0; i < _dsTableLoopCount; ++i)
cmd = _dsTable[cmd];
@@ -1705,7 +1728,6 @@ void Screen::drawShapePlotType4(uint8 *dst, uint8 cmd) {
}
void Screen::drawShapePlotType5(uint8 *dst, uint8 cmd) {
- // uint32 relOffs = dst - _dsDstPage;
cmd = _dsTable2[cmd];
for (int i = 0; i < _dsTableLoopCount; ++i)
cmd = _dsTable[cmd];
@@ -1812,6 +1834,15 @@ void Screen::drawShapePlotType14(uint8 *dst, uint8 cmd) {
*dst = cmd;
}
+void Screen::drawShapePlotType20(uint8 *dst, uint8 cmd) {
+ cmd = _dsTable2[cmd];
+ uint8 tOffs = _dsTable3[cmd];
+ if (!(tOffs & 0x80))
+ cmd = _dsTable4[tOffs << 8 | *dst];
+
+ *dst = cmd;
+}
+
void Screen::drawShapePlotType33(uint8 *dst, uint8 cmd) {
if (cmd == 255) {
*dst = _dsTable5[*dst];
@@ -2822,6 +2853,9 @@ void Screen::loadPalette(const byte *data, uint8 *palData, int bytes) {
palData[0] = (col & 0xF) << 2; col >>= 4;
palData += 3;
}
+ } else if (_use16ColorMode) {
+ for (int i = 0; i < bytes; ++i)
+ palData[i] = ((data[i] & 0xF) << 4) | (data[i] & 0xF0);
} else {
memcpy(palData, data, bytes);
}
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index 15f0ab2079..3720979c62 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -271,6 +271,7 @@ protected:
bool _useOverlays;
bool _useSJIS;
+ bool _use16ColorMode;
uint8 *_sjisFontData;
uint8 *_sjisTempPage;
@@ -328,6 +329,7 @@ protected:
void drawShapePlotType12(uint8 *dst, uint8 cmd);
void drawShapePlotType13(uint8 *dst, uint8 cmd);
void drawShapePlotType14(uint8 *dst, uint8 cmd);
+ void drawShapePlotType20(uint8 *dst, uint8 cmd);
void drawShapePlotType33(uint8 *dst, uint8 cmd);
void drawShapePlotType37(uint8 *dst, uint8 cmd);
void drawShapePlotType48(uint8 *dst, uint8 cmd);
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index e370cc9a33..f24d3a4472 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -32,9 +32,6 @@
namespace Kyra {
Screen_LoL::Screen_LoL(LoLEngine *vm, OSystem *system) : Screen_v2(vm, system), _vm(vm) {
- _customDimTable = new ScreenDim*[_screenDimTableCount];
- memset(_customDimTable, 0, sizeof(ScreenDim*) * _screenDimTableCount);
-
_paletteOverlay1 = new uint8[0x100];
_paletteOverlay2 = new uint8[0x100];
_grayOverlay = new uint8[0x100];
@@ -48,7 +45,7 @@ Screen_LoL::Screen_LoL(LoLEngine *vm, OSystem *system) : Screen_v2(vm, system),
_fadeFlag = 2;
_curDimIndex = 0;
- _mapDimX = _mapDimY = _mapDimW = _mapDimH = _mapDimDstX = _mapBlockWidth = _mapDimDstY = _mapBlockHeight = _mapDimU5 = _mapDimU6 = _mapBlockWidth2 = _mapDimU8 = 0;
+ _internDimX = _internDimY = _internDimW = _internDimH = _internDimDstX = _internBlockWidth = _internDimDstY = _internBlockHeight = _internDimU5 = _internDimU6 = _internBlockWidth2 = _internDimU8 = 0;
}
Screen_LoL::~Screen_LoL() {
@@ -64,6 +61,17 @@ Screen_LoL::~Screen_LoL() {
delete[] _grayOverlay;
}
+bool Screen_LoL::init() {
+ if (Screen::init()) {
+ _screenDimTable = _use16ColorMode ? _screenDimTable16C : _screenDimTable256C;
+ _customDimTable = new ScreenDim*[_screenDimTableCount];
+ memset(_customDimTable, 0, sizeof(ScreenDim*) * _screenDimTableCount);
+ return true;
+ }
+ return false;
+}
+
+
void Screen_LoL::setScreenDim(int dim) {
debugC(9, kDebugLevelScreen, "Screen_LoL::setScreenDim(%d)", dim);
assert(dim < _screenDimTableCount);
@@ -525,23 +533,23 @@ void Screen_LoL::copyBlockSpecial(int page1, int x1, int y1, int page2, int x2,
return;
const ScreenDim *cdim = getScreenDim(dim);
- _mapDimX = cdim->sx << 3;
- _mapDimY = cdim->sy;
- _mapDimW = cdim->w << 3;
- _mapDimH = cdim->h;
+ _internDimX = cdim->sx << 3;
+ _internDimY = cdim->sy;
+ _internDimW = cdim->w << 3;
+ _internDimH = cdim->h;
calcMapBoundaries(x2, y2, w, h);
- if (_mapBlockWidth == -1)
+ if (_internBlockWidth == -1)
return;
uint8 *src = getPagePtr(page1) + y1 * 320 + x1;
- uint8 *dst = getPagePtr(page2) + (_mapDimDstY + _mapDimY) * 320;
+ uint8 *dst = getPagePtr(page2) + (_internDimDstY + _internDimY) * 320;
- for (int i = 0; i < _mapBlockHeight; i++) {
- uint8 *s = src + _mapDimU5;
- uint8 *d = dst + (_mapDimDstX + _mapDimX);
+ for (int i = 0; i < _internBlockHeight; i++) {
+ uint8 *s = src + _internDimU5;
+ uint8 *d = dst + (_internDimDstX + _internDimX);
- for (int ii = 0; ii < _mapBlockWidth; ii++) {
+ for (int ii = 0; ii < _internBlockWidth; ii++) {
uint8 p = ovl[*s++];
if (p)
*d = p;
@@ -552,60 +560,97 @@ void Screen_LoL::copyBlockSpecial(int page1, int x1, int y1, int page2, int x2,
src += 320;
}
- addDirtyRect(_mapDimDstX + _mapDimX, _mapDimDstY + _mapDimY, _mapBlockWidth, _mapBlockHeight);
+ addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight);
+}
+
+void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl) {
+ if (!w || !h || !ovl)
+ return;
+
+ const ScreenDim *cdim = getScreenDim(dim);
+ _internDimX = cdim->sx << 3;
+ _internDimY = cdim->sy;
+ _internDimW = cdim->w << 3;
+ _internDimH = cdim->h;
+
+ calcMapBoundaries(x2, y2, w, h);
+ if (_internBlockWidth == -1)
+ return;
+
+ uint8 *src = getPagePtr(page1) + y1 * 320 + x1;
+ uint8 *dst = getPagePtr(page2) + (_internDimDstY + _internDimY) * 320;
+
+ for (int i = 0; i < _internBlockHeight; i++) {
+ uint8 *s = src + _internDimU5;
+ uint8 *d = dst + (_internDimDstX + _internDimX);
+
+ if (flag)
+ d += (i >> 1);
+
+ for (int ii = 0; ii < _internBlockWidth; ii++) {
+ if (*s++)
+ *d = ovl[*d];
+ d++;
+ }
+
+ dst += 320;
+ src += 320;
+ }
+
+ addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight);
}
void Screen_LoL::calcMapBoundaries(int dstX, int dstY, int width, int height) {
- _mapBlockWidth = _mapBlockWidth2 = width;
- _mapBlockHeight = height;
- _mapDimDstX = dstX;
- _mapDimDstY = dstY;
+ _internBlockWidth = _internBlockWidth2 = width;
+ _internBlockHeight = height;
+ _internDimDstX = dstX;
+ _internDimDstY = dstY;
- _mapDimU5 = _mapDimU6 = _mapDimU8 = 0;
+ _internDimU5 = _internDimU6 = _internDimU8 = 0;
- int t = _mapDimDstX + _mapBlockWidth;
+ int t = _internDimDstX + _internBlockWidth;
if (t <= 0) {
- _mapBlockWidth = _mapBlockHeight = -1;
+ _internBlockWidth = _internBlockHeight = -1;
return;
}
- if (t <= _mapDimDstX) {
- _mapDimU5 = _mapBlockWidth - t;
- _mapBlockWidth = t;
- _mapDimDstX = 0;
+ if (t <= _internDimDstX) {
+ _internDimU5 = _internBlockWidth - t;
+ _internBlockWidth = t;
+ _internDimDstX = 0;
}
- t = _mapDimW - _mapDimDstX;
+ t = _internDimW - _internDimDstX;
if (t <= 0) {
- _mapBlockWidth = _mapBlockHeight = -1;
+ _internBlockWidth = _internBlockHeight = -1;
return;
}
- if (t <= _mapBlockWidth)
- _mapBlockWidth = t;
+ if (t <= _internBlockWidth)
+ _internBlockWidth = t;
- _mapBlockWidth2 -= _mapBlockWidth;
+ _internBlockWidth2 -= _internBlockWidth;
- t = _mapDimDstY + _mapBlockHeight;
+ t = _internDimDstY + _internBlockHeight;
if (t <= 0) {
- _mapBlockWidth = _mapBlockHeight = -1;
+ _internBlockWidth = _internBlockHeight = -1;
return;
}
- if (t <= _mapDimDstY) {
- _mapDimU6 = _mapBlockHeight - t;
- _mapBlockHeight = t;
- _mapDimDstY = 0;
+ if (t <= _internDimDstY) {
+ _internDimU6 = _internBlockHeight - t;
+ _internBlockHeight = t;
+ _internDimDstY = 0;
}
- t = _mapDimH - _mapDimDstY;
+ t = _internDimH - _internDimDstY;
if (t <= 0) {
- _mapBlockWidth = _mapBlockHeight = -1;
+ _internBlockWidth = _internBlockHeight = -1;
return;
}
- if (t <= _mapBlockHeight)
- _mapBlockHeight = t;
+ if (t <= _internBlockHeight)
+ _internBlockHeight = t;
}
void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) {
diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h
index 30567ee808..d7580e1ff8 100644
--- a/engines/kyra/screen_lol.h
+++ b/engines/kyra/screen_lol.h
@@ -39,6 +39,8 @@ public:
Screen_LoL(LoLEngine *vm, OSystem *system);
~Screen_LoL();
+ bool init();
+
void setScreenDim(int dim);
const ScreenDim *getScreenDim(int dim);
int curDimIndex() { return _curDimIndex; }
@@ -60,11 +62,6 @@ public:
void smoothScrollTurnStep2(int srcPage1Num, int srcPage2Num, int dstPageNum);
void smoothScrollTurnStep3(int srcPage1Num, int srcPage2Num, int dstPageNum);
- // magic atlas
- // This method basically works like copyRegion, but the pixels
- // copied also have a palette overlay applied to them.
- void copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl);
-
// palette stuff
void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0);
void loadSpecialColours(uint8 *destPalette);
@@ -75,6 +72,9 @@ public:
uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight);
uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; }
+ void copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl);
+ void applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl);
+
uint8 getShapePaletteSize(const uint8 *shp);
uint8 *_paletteOverlay1;
@@ -85,9 +85,12 @@ public:
private:
LoLEngine *_vm;
- static const ScreenDim _screenDimTable[];
+ const ScreenDim *_screenDimTable;
static const int _screenDimTableCount;
+ static const ScreenDim _screenDimTable256C[];
+ static const ScreenDim _screenDimTable16C[];
+
ScreenDim **_customDimTable;
int _curDimIndex;
@@ -96,18 +99,18 @@ private:
// magic atlas
void calcMapBoundaries(int dstX, int dstY, int c, int d);
- int _mapDimX;
- int _mapDimY;
- int _mapDimW;
- int _mapDimH;
- int _mapDimDstX;
- int _mapBlockWidth;
- int _mapDimDstY;
- int _mapBlockHeight;
- int _mapDimU5;
- int _mapDimU6;
- int _mapBlockWidth2;
- int _mapDimU8;
+ int _internDimX;
+ int _internDimY;
+ int _internDimW;
+ int _internDimH;
+ int _internDimDstX;
+ int _internBlockWidth;
+ int _internDimDstY;
+ int _internBlockHeight;
+ int _internDimU5;
+ int _internDimU6;
+ int _internBlockWidth2;
+ int _internDimU8;
};
} // end of namespace Kyra
diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp
index ff8d228c56..50333cd44a 100644
--- a/engines/kyra/screen_v2.cpp
+++ b/engines/kyra/screen_v2.cpp
@@ -119,7 +119,8 @@ void Screen_v2::getFadeParams(const uint8 *palette, int delay, int &delayInc, in
int maxDiff = 0;
diff = 0;
- for (int i = 0; i < 768; ++i) {
+ int len = _use16ColorMode ? 48 : 768;
+ for (int i = 0; i < len; ++i) {
diff = ABS(palette[i] - _screenPalette[i]);
maxDiff = MAX(maxDiff, diff);
}
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index ae27cd6c3d..0015c7c817 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -231,7 +231,7 @@ int LoLEngine::olol_getItemPara(EMCState *script) {
switch (stackPos(1)) {
case 0:
- return i->blockPropertyIndex;
+ return i->block;
case 1:
return i->x;
case 2:
@@ -298,7 +298,7 @@ int LoLEngine::olol_getCharacterStat(EMCState *script) {
return c->magicPointsMax;
case 9:
- return c->itemsProtection;
+ return c->itemProtection;
case 10:
return c->items[d];
@@ -307,7 +307,7 @@ int LoLEngine::olol_getCharacterStat(EMCState *script) {
return c->skillLevels[d] + c->skillModifiers[d];
case 12:
- return c->field_27[d];
+ return c->protectionAgainstItems[d];
case 13:
return (d & 0x80) ? c->itemsMight[7] : c->itemsMight[d];
@@ -341,7 +341,7 @@ int LoLEngine::olol_setCharacterStat(EMCState *script) {
break;
case 5:
- //// TODO
+ setCharacterMagicOrHitPoints(stackPos(0), 0, e, 0);
break;
case 6:
@@ -349,7 +349,7 @@ int LoLEngine::olol_setCharacterStat(EMCState *script) {
break;
case 7:
- //// TODO
+ setCharacterMagicOrHitPoints(stackPos(0), 1, e, 0);
break;
case 8:
@@ -357,7 +357,7 @@ int LoLEngine::olol_setCharacterStat(EMCState *script) {
break;
case 9:
- c->itemsProtection = e;
+ c->itemProtection = e;
break;
case 10:
@@ -369,7 +369,7 @@ int LoLEngine::olol_setCharacterStat(EMCState *script) {
break;
case 12:
- c->field_27[d] = e;
+ c->protectionAgainstItems[d] = e;
break;
case 13:
@@ -577,7 +577,7 @@ int LoLEngine::olol_getGlobalVar(EMCState *script) {
case 11:
return _compassBroken;
case 12:
- return _unkBt2;
+ return _drainMagic;
case 13:
return _speechFlag;
default:
@@ -651,7 +651,7 @@ int LoLEngine::olol_setGlobalVar(EMCState *script) {
break;
case 12:
- _unkBt2 = a & 0xff;
+ _drainMagic = a & 0xff;
break;
default:
@@ -708,7 +708,7 @@ int LoLEngine::olol_initMonster(EMCState *script) {
for (uint8 i = 0; i < 30; i++) {
MonsterInPlay *l = &_monsters[i];
- if (l->might || l->mode == 13)
+ if (l->hitPoints || l->mode == 13)
continue;
memset(l, 0, sizeof(MonsterInPlay));
@@ -719,13 +719,13 @@ int LoLEngine::olol_initMonster(EMCState *script) {
l->type = stackPos(4);
l->properties = &_monsterProperties[l->type];
l->direction = l->facing << 1;
- l->might = (l->properties->might * _monsterModifiers[_monsterDifficulty]) >> 8;
+ l->hitPoints = (l->properties->hitPoints * _monsterModifiers[_monsterDifficulty]) >> 8;
if (_currentLevel == 12 && l->type == 2)
- l->might = (l->might * (_rnd.getRandomNumberRng(1, 128) + 192)) >> 8;
+ l->hitPoints = (l->hitPoints * (_rnd.getRandomNumberRng(1, 128) + 192)) >> 8;
- l->field_25 = l->properties->unk6[0];
- l->field_27 = _rnd.getRandomNumberRng(1, calcMonsterSkillLevel(l->id | 0x8000, 8)) - 1;
+ l->numDistAttacks = l->properties->numDistAttacks;
+ l->distAttackTick = _rnd.getRandomNumberRng(1, calcMonsterSkillLevel(l->id | 0x8000, 8)) - 1;
l->flyingHeight = 2;
l->flags = stackPos(5);
l->assignedItems = 0;
@@ -740,7 +740,7 @@ int LoLEngine::olol_initMonster(EMCState *script) {
for (int ii = 0; ii < 4; ii++)
l->field_2A[ii] = stackPos(7 + ii);
- checkSceneUpdateNeed(l->blockPropertyIndex);
+ checkSceneUpdateNeed(l->block);
return i;
}
@@ -779,7 +779,7 @@ int LoLEngine::olol_loadNewLevel(EMCState *script) {
disableSysTimer(2);
for (int i = 0; i < 8; i++) {
- if (!_flyingObjects[i].enable || _flyingObjects[i].a)
+ if (!_flyingObjects[i].enable || _flyingObjects[i].objectType)
continue;
endObjectFlight(&_flyingObjects[i], _flyingObjects[i].x, _flyingObjects[i].y, 1);
}
@@ -800,6 +800,11 @@ int LoLEngine::olol_loadNewLevel(EMCState *script) {
return 1;
}
+int LoLEngine::olol_getNearestMonsterFromCharacter(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getNearestMonsterFromCharacter(%p) (%d)", (const void *)script, stackPos(0));
+ return getNearestMonsterFromCharacter(stackPos(0));
+}
+
int LoLEngine::olol_dummy0(EMCState *script) {
return 0;
}
@@ -835,15 +840,14 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
l->fightingStats[6] = (stackPos(7) << 8) / 100; //
l->fightingStats[7] = (stackPos(8) << 8) / 100; //
l->fightingStats[8] = 0;
- l->fightingStats[9] = 0;
for (int i = 0; i < 8; i++) {
- l->unk2[i] = stackPos(9 + i);
- l->unk3[i] = (stackPos(17 + i) << 8) / 100;
+ l->itemsMight[i] = stackPos(9 + i);
+ l->protectionAgainstItems[i] = (stackPos(17 + i) << 8) / 100;
}
l->itemProtection = stackPos(25);
- l->might = stackPos(26);
+ l->hitPoints = stackPos(26);
l->speedTotalWaitTicks = 1;
l->flags = stackPos(27);
l->unk5 = stackPos(28);
@@ -851,13 +855,15 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
l->unk5 = stackPos(29);
//
- for (int i = 0; i < 5; i++)
- l->unk6[i] = stackPos(30 + i);
+ l->numDistAttacks = stackPos(30);
+ l->numDistWeapons = stackPos(31);
+ for (int i = 0; i < 3; i++)
+ l->distWeapons[i] = stackPos(32 + i);
- for (int i = 0; i < 2; i++) {
- l->unk7[i] = stackPos(35 + i);
- l->unk7[i + 2] = stackPos(37 + i);
- }
+ l->attackSkillChance = stackPos(35);
+ l->attackSkillType = stackPos(36);
+ l->defenseSkillChance = stackPos(37);
+ l->defenseSkillType = stackPos(38);
for (int i = 0; i < 3; i++)
l->sounds[i] = stackPos(39 + i);
@@ -870,6 +876,18 @@ int LoLEngine::olol_battleHitSkillTest(EMCState *script) {
return battleHitSkillTest(stackPos(0), stackPos(1), stackPos(2));
}
+int LoLEngine::olol_inflictDamage(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_inflictDamage(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ if (stackPos(0) == -1) {
+ for (int i = 0; i < 4; i++)
+ inflictDamage(i, stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ } else {
+ inflictDamage(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ }
+
+ return 1;
+}
+
int LoLEngine::olol_moveMonster(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_moveMonster(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
MonsterInPlay *m = &_monsters[stackPos(0)];
@@ -930,6 +948,20 @@ int LoLEngine::olol_createHandItem(EMCState *script) {
return 1;
}
+int LoLEngine::olol_playAttackSound(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playAttackSound(%p) (%d)", (const void *)script, stackPos(0));
+
+ static const uint8 sounds[] = { 12, 62, 63 };
+ int d = stackPos(0);
+
+ if ((d < 70 || d > 74) && (d < 81 || d > 89) && (d < 93 || d > 97) && (d < 102 || d > 106))
+ snd_playSoundEffect(sounds[_itemProperties[d].skill & 3], -1);
+ else
+ snd_playSoundEffect(12, -1);
+
+ return 1;
+}
+
int LoLEngine::olol_characterJoinsParty(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_characterJoinsParty(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
@@ -1043,8 +1075,8 @@ int LoLEngine::olol_getWallFlags(EMCState *script) {
return _wllWallFlags[_levelBlockProperties[stackPos(0)].walls[stackPos(1) & 3]];
}
-int LoLEngine::olol_changeMonsterSettings(EMCState *script) {
- debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_changeMonsterSettings(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+int LoLEngine::olol_changeMonsterStat(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_changeMonsterStat(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
if (stackPos(0) == -1)
return 1;
@@ -1060,7 +1092,7 @@ int LoLEngine::olol_changeMonsterSettings(EMCState *script) {
break;
case 1:
- m->might = d;
+ m->hitPoints = d;
break;
case 2:
@@ -1084,6 +1116,39 @@ int LoLEngine::olol_changeMonsterSettings(EMCState *script) {
return 1;
}
+int LoLEngine::olol_getMonsterStat(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getMonsterStat(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ if (stackPos(0) == -1)
+ return 0;
+
+ MonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
+ int d = stackPos(1);
+
+ switch (d) {
+ case 0:
+ return m->mode;
+ case 1:
+ return m->hitPoints;
+ case 2:
+ return m->block;
+ case 3:
+ return m->facing;
+ case 4:
+ return m->type;
+ case 5:
+ return m->properties->hitPoints;
+ case 6:
+ return m->flags;
+ case 7:
+ return m->properties->flags;
+ case 8:
+ return _monsterUnk[m->properties->shapeIndex];
+ default:
+ break;
+ }
+
+ return 0;
+}
int LoLEngine::olol_playCharacterScriptChat(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playCharacterScriptChat(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
@@ -1098,6 +1163,18 @@ int LoLEngine::olol_update(EMCState *script) {
return 1;
}
+int LoLEngine::olol_healCharacter(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_healCharacter(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ if (stackPos(3)) {
+ processMagicHeal(stackPos(0), stackPos(1));
+ } else {
+ increaseCharacterHitpoints(stackPos(0), stackPos(1), true);
+ if (stackPos(2))
+ gui_drawCharPortraitWithStats(stackPos(0));
+ }
+ return 1;
+}
+
int LoLEngine::olol_drawExitButton(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_drawExitButton(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
@@ -1164,6 +1241,17 @@ int LoLEngine::olol_setPaletteBrightness(EMCState *script) {
return old;
}
+int LoLEngine::olol_calcInflictableDamage(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_calcInflictableDamage(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ return calcInflictableDamage(stackPos(0), stackPos(1), stackPos(2));
+}
+
+int LoLEngine::olol_getInflictedDamage(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getInflictedDamage(%p) (%d)", (const void *)script, stackPos(0));
+ int mx = stackPos(0);
+ return mx ? _rnd.getRandomNumberRng(2, mx) : 0;
+}
+
int LoLEngine::olol_checkForCertainPartyMember(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_checkForCertainPartyMember(%p) (%d)", (const void *)script, stackPos(0));
for (int i = 0; i < 4; i++) {
@@ -1186,14 +1274,19 @@ int LoLEngine::olol_printMessage(EMCState *script) {
int LoLEngine::olol_deleteLevelItem(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_deleteLevelItem(%p) (%d)", (const void *)script, stackPos(0));
- if (_itemsInPlay[stackPos(0)].blockPropertyIndex)
- removeLevelItem(stackPos(0), _itemsInPlay[stackPos(0)].blockPropertyIndex);
+ if (_itemsInPlay[stackPos(0)].block)
+ removeLevelItem(stackPos(0), _itemsInPlay[stackPos(0)].block);
deleteItem(stackPos(0));
return 1;
}
+int LoLEngine::olol_calcInflictableDamagePerItem(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_calcInflictableDamagePerItem(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ return calcInflictableDamagePerItem(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+}
+
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;
@@ -1216,7 +1309,7 @@ int LoLEngine::olol_objectLeavesLevel(EMCState *script) {
MonsterInPlay *m = &_monsters[l];
setMonsterMode(m, 14);
- checkSceneUpdateNeed(m->blockPropertyIndex);
+ checkSceneUpdateNeed(m->block);
placeMonster(m, 0, 0);
res = 1;
@@ -1276,7 +1369,7 @@ int LoLEngine::olol_suspendMonster(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_suspendMonster(%p) (%d)", (const void *)script, stackPos(0));
MonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
setMonsterMode(m, 14);
- checkSceneUpdateNeed(m->blockPropertyIndex);
+ checkSceneUpdateNeed(m->block);
placeMonster(m, 0, 0);
return 1;
}
@@ -1287,9 +1380,9 @@ int LoLEngine::olol_setDoorState(EMCState *script) {
return _emcDoorState;
}
-int LoLEngine::olol_processButtonClick(EMCState *script) {
- debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_processButtonClick(%p) (%d)", (const void *)script, stackPos(0));
- _tim->forceDialogue(_activeTim[stackPos(0)]);
+int LoLEngine::olol_resetTimDialogueState(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_resetTimDialogueState(%p) (%d)", (const void *)script, stackPos(0));
+ _tim->resetDialogueState(_activeTim[stackPos(0)]);
return 1;
}
@@ -1433,7 +1526,7 @@ int LoLEngine::tlol_setupPaletteFade(const TIM *tim, const uint16 *param) {
int LoLEngine::tlol_loadPalette(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_loadPalette(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]);
const char *palFile = (const char *)(tim->text + READ_LE_UINT16(tim->text + (param[0]<<1)));
- _res->loadFileToBuf(palFile, _screen->getPalette(0), 768);
+ _screen->loadPalette(palFile, _screen->getPalette(0));
return 1;
}
@@ -1747,13 +1840,13 @@ void LoLEngine::setupOpcodeTable() {
// 0x3C
Opcode(olol_loadNewLevel);
- OpcodeUnImpl();
+ Opcode(olol_getNearestMonsterFromCharacter);
Opcode(olol_dummy0);
Opcode(olol_loadMonsterProperties);
// 0x40
Opcode(olol_battleHitSkillTest);
- OpcodeUnImpl();
+ Opcode(olol_inflictDamage);
OpcodeUnImpl();
OpcodeUnImpl();
@@ -1766,7 +1859,7 @@ void LoLEngine::setupOpcodeTable() {
// 0x48
Opcode(olol_setScriptTimer);
Opcode(olol_createHandItem);
- OpcodeUnImpl();
+ Opcode(olol_playAttackSound);
Opcode(olol_characterJoinsParty);
// 0x4C
@@ -1791,17 +1884,17 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_processDialogue);
Opcode(olol_stopTimScript);
Opcode(olol_getWallFlags);
- Opcode(olol_changeMonsterSettings);
+ Opcode(olol_changeMonsterStat);
// 0x5C
- OpcodeUnImpl();
+ Opcode(olol_getMonsterStat);
OpcodeUnImpl();
Opcode(olol_playCharacterScriptChat);
Opcode(olol_update);
// 0x60
OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_healCharacter);
Opcode(olol_drawExitButton);
Opcode(olol_loadSoundFile);
@@ -1818,14 +1911,14 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_setPaletteBrightness);
// 0x6C
- OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_calcInflictableDamage);
+ Opcode(olol_getInflictedDamage);
Opcode(olol_checkForCertainPartyMember);
Opcode(olol_printMessage);
// 0x70
Opcode(olol_deleteLevelItem);
- OpcodeUnImpl();
+ Opcode(olol_calcInflictableDamagePerItem);
OpcodeUnImpl();
OpcodeUnImpl();
@@ -1857,7 +1950,7 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_setDoorState);
- Opcode(olol_processButtonClick);
+ Opcode(olol_resetTimDialogueState);
// 0x88
OpcodeUnImpl();
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp
index 461cd17083..a3f3268db3 100644
--- a/engines/kyra/script_tim.cpp
+++ b/engines/kyra/script_tim.cpp
@@ -618,6 +618,8 @@ int TIMInterpreter::cmd_playVocFile(const uint16 *param) {
if (index < ARRAYSIZE(_vocFiles) && !_vocFiles[index].empty())
vm()->sound()->voicePlay(_vocFiles[index].c_str(), volume, true);
+ else if (index == 7 && !_vm->gameFlags().isTalkie)
+ vm()->sound()->playTrack(index);
else
vm()->sound()->playSoundEffect(index);
@@ -1144,7 +1146,7 @@ uint16 TIMInterpreter_LoL::processDialogue() {
return res;
}
-void TIMInterpreter_LoL::forceDialogue(TIM *tim) {
+void TIMInterpreter_LoL::resetDialogueState(TIM *tim) {
if (!tim)
return;
diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h
index 3748867f54..6e9d5fc6b8 100644
--- a/engines/kyra/script_tim.h
+++ b/engines/kyra/script_tim.h
@@ -145,7 +145,7 @@ public:
virtual void updateBackgroundAnimation(int animIndex) {}
virtual void playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) {}
- virtual void forceDialogue(TIM *tim) {}
+ virtual void resetDialogueState(TIM *tim) {}
int _drawPage2;
@@ -231,7 +231,7 @@ public:
void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3);
uint16 processDialogue();
- void forceDialogue(TIM *tim);
+ void resetDialogueState(TIM *tim);
void setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame);
void startBackgroundAnimation(int animIndex, int part);
diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp
index 4037b9c30b..df86b4a519 100644
--- a/engines/kyra/sequences_lol.cpp
+++ b/engines/kyra/sequences_lol.cpp
@@ -88,6 +88,7 @@ void LoLEngine::setupPrologueData(bool load) {
memset(_selectionAnimTimers, 0, sizeof(_selectionAnimTimers));
memset(_screen->getPalette(1), 0, 768);
+
} else {
delete _chargenWSA; _chargenWSA = 0;
@@ -114,6 +115,13 @@ void LoLEngine::setupPrologueData(bool load) {
_eventList.clear();
}
+
+ // We have three sound.dat files, one for the intro, one for the
+ // end sequence and one for ingame, each contained in a different
+ // PAK file. Therefore a new call to loadSoundFile() is required
+ // whenever the PAK file configuration changes.
+ if (_flags.platform == Common::kPlatformPC98)
+ _sound->loadSoundFile("sound.dat");
}
void LoLEngine::showIntro() {
@@ -122,13 +130,16 @@ void LoLEngine::showIntro() {
_tim = new TIMInterpreter(this, _screen, _system);
assert(_tim);
+ if (_flags.platform == Common::kPlatformPC98)
+ showStarcraftLogo();
+
uint8 *pal = _screen->getPalette(0);
memset(pal, 0, 768);
_screen->setScreenPalette(pal);
_screen->clearPage(0);
_screen->clearPage(4);
- _screen->clearPage(8);
+ _screen->clearPage(8);
TIM *intro = _tim->load("LOLINTRO.TIM", &_timIntroOpcodes);
@@ -226,6 +237,9 @@ int LoLEngine::chooseCharacter() {
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
_screen->_curPage = 0;
+ if (_flags.use16ColorMode)
+ _screen->loadPalette("LOL.NOL", _screen->getPalette(0));
+
_screen->fadePalette(_screen->getPalette(0), 30, 0);
bool kingIntro = true;
@@ -571,6 +585,51 @@ int LoLEngine::selectionCharAccept() {
return -1;
}
+void LoLEngine::showStarcraftLogo() {
+ WSAMovie_v2 *ci = new WSAMovie_v2(this, _screen);
+ assert(ci);
+
+ _screen->clearPage(0);
+ _screen->clearPage(2);
+
+ int endframe = ci->open("ci01.wsa", 0, _screen->_currentPalette);
+ if (!ci->opened()) {
+ delete ci;
+ return;
+ }
+ _screen->hideMouse();
+ ci->setX(32);
+ ci->setY(80);
+ ci->setDrawPage(2);
+ ci->displayFrame(0, 0);
+ _screen->copyPage(2, 0);
+ _screen->fadeFromBlack();
+ int inputFlag = 0;
+ for (int i = 0; i < endframe; i++) {
+ inputFlag = checkInput(0) & 0xff;
+ if (shouldQuit() || inputFlag)
+ break;
+ ci->displayFrame(i, 0);
+ _screen->copyPage(2, 0);
+ _screen->updateScreen();
+ delay(4 * _tickLength);
+ }
+
+ if (!(shouldQuit() || inputFlag)) {
+ _sound->voicePlay("star2");
+ while(_sound->voiceIsPlaying("star2") && !(shouldQuit() || inputFlag)) {
+ inputFlag = checkInput(0) & 0xff;
+ delay(_tickLength);
+ }
+ }
+
+ _screen->fadeToBlack();
+ _screen->showMouse();
+
+ _eventList.clear();
+ delete ci;
+}
+
} // end of namespace Kyra
#endif // ENABLE_LOL
diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h
index 7b7fba8e3a..565e02e917 100644
--- a/engines/kyra/sound.h
+++ b/engines/kyra/sound.h
@@ -224,9 +224,11 @@ public:
*/
void voiceStop(const char *file = 0);
protected:
- const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->_fileListLen) ? _soundDataList->_fileList[file] : ""; }
- const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->_cdaTracks : 0; }
- int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->_cdaNumTracks : 0; }
+ const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->fileListLen) ? _soundDataList->fileList[file] : ""; }
+ int fileListLen() const { return _soundDataList->fileListLen; }
+ const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->cdaTracks : 0; }
+ int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->cdaNumTracks : 0; }
+ int extraOffset() const { return _soundDataList != 0 ? _soundDataList->extraOffset : 0; }
enum {
kNumChannelHandles = 4
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index c85c5b3ef0..9b085fc69f 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 /= 2;
+ finOut /= 4;
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 *= 7;
+ finOut *= 3;
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 * 7) / 2);
+ int32 finOut = ((output * 3) / ((_numChan + _numSSG - 3) / 3));
if (_chanInternal[i].enableLeft)
*leftSample += finOut;
@@ -4064,8 +4064,7 @@ bool SoundPC98::init() {
}
void SoundPC98::playTrack(uint8 track) {
- if (--track >= 56)
- track -= 55;
+ track += extraOffset();
if (track == _lastTrack && _musicEnabled)
return;
@@ -4074,6 +4073,10 @@ void SoundPC98::playTrack(uint8 track) {
char musicfile[13];
sprintf(musicfile, fileListEntry(0), track);
+ if (fileListLen() == 1)
+ sprintf(musicfile, fileListEntry(0), track);
+ else
+ strcpy(musicfile, fileListEntry(track));
delete[] _musicTrackData;
_musicTrackData = _vm->resource()->fileData(musicfile, 0);
if (_musicEnabled)
@@ -4126,19 +4129,25 @@ SoundTownsPC98_v2::~SoundTownsPC98_v2() {
bool SoundTownsPC98_v2::init() {
_driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ?
TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS);
- _useFmSfx = _vm->gameFlags().platform == Common::kPlatformPC98 ? true : false;
- _vm->checkCD();
- // FIXME: While checking for 'track1.XXX(X)' looks like
- // a good idea, we should definitely not be doing this
- // here. Basically our filenaming scheme could change
- // or we could add support for other audio formats. Also
- // this misses the possibility that we play the tracks
- // right off CD. So we should find another way to
- // check if we have access to CD audio.
- Resource *res = _vm->resource();
- if (_musicEnabled &&
- (res->exists("track1.mp3") || res->exists("track1.ogg") || res->exists("track1.flac") || res->exists("track1.fla")))
- _musicEnabled = 2;
+
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+ _vm->checkCD();
+ // FIXME: While checking for 'track1.XXX(X)' looks like
+ // a good idea, we should definitely not be doing this
+ // here. Basically our filenaming scheme could change
+ // or we could add support for other audio formats. Also
+ // this misses the possibility that we play the tracks
+ // right off CD. So we should find another way to
+ // check if we have access to CD audio.
+ Resource *res = _vm->resource();
+ if (_musicEnabled &&
+ (res->exists("track1.mp3") || res->exists("track1.ogg") || res->exists("track1.flac") || res->exists("track1.fla")))
+ _musicEnabled = 2;
+ _useFmSfx = false;
+
+ } else {
+ _useFmSfx = true;
+ }
return _driver->init();
}
@@ -4153,6 +4162,8 @@ void SoundTownsPC98_v2::process() {
}
void SoundTownsPC98_v2::playTrack(uint8 track) {
+ track += extraOffset();
+
if (track == _lastTrack && _musicEnabled)
return;
@@ -4171,7 +4182,10 @@ void SoundTownsPC98_v2::playTrack(uint8 track) {
beginFadeOut();
char musicfile[13];
- sprintf(musicfile, fileListEntry(0), track);
+ if (fileListLen() == 1)
+ sprintf(musicfile, fileListEntry(0), track);
+ else
+ strcpy(musicfile, fileListEntry(track));
delete[] _musicTrackData;
_musicTrackData = _vm->resource()->fileData(musicfile, 0);
@@ -4208,6 +4222,8 @@ void SoundTownsPC98_v2::beginFadeOut() {
int32 SoundTownsPC98_v2::voicePlay(const char *file, uint8, bool) {
static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 };
+ static const char patternHOF[] = "%s.PCM";
+ static const char patternLOL[] = "%s.VOC";
int h = 0;
if (_currentSFX) {
@@ -4218,10 +4234,13 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, uint8, bool) {
}
char filename[13];
- sprintf(filename, "%s.PCM", file);
+ const char *pattern = _vm->game() == GI_LOL ? patternLOL : patternHOF;
+ sprintf(filename, pattern, file);
uint8 *data = _vm->resource()->fileData(filename, 0);
uint8 *src = data;
+ if (!src)
+ return 0;
uint16 sfxRate = rates[READ_LE_UINT16(src)];
src += 2;
diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp
index 7d8ca049a3..9c9038ca71 100644
--- a/engines/kyra/sprites_lol.cpp
+++ b/engines/kyra/sprites_lol.cpp
@@ -80,8 +80,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int b) {
uint8 *tmpPal2 = new uint8[256];
uint16 *tmpPal3 = new uint16[256];
memset (tmpPal1, 0, 64);
- memset (tmpPal2, 0, 256);
- memset (tmpPal3, 0xff, 512);
+ memset (tmpPal2, 0, 256);
for (int i = 0; i < 64; i++) {
tmpPal1[i] = *p;
@@ -93,6 +92,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int b) {
for (int i = 0; i < 16; i++) {
int pos = (monsterIndex << 4) + i;
memcpy(tmpPal2, _monsterShapes[pos] + 10, 256);
+ memset (tmpPal3, 0xff, 512);
uint8 numCol = *tmpPal2;
for (int ii = 0; ii < numCol; ii++) {
@@ -152,7 +152,7 @@ int LoLEngine::deleteMonstersFromBlock(int block) {
cnt++;
setMonsterMode(m, 14);
- checkSceneUpdateNeed(m->blockPropertyIndex);
+ checkSceneUpdateNeed(m->block);
placeMonster(m, 0, 0);
@@ -184,14 +184,14 @@ void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) {
monster->mode = mode;
monster->fightCurTick = 0;
if (mode == 14)
- monster->might = 0;
+ monster->hitPoints = 0;
if (mode == 13 && (monster->flags & 0x20)) {
monster->mode = 0;
monsterDropItems(monster);
if (_currentLevel != 29)
setMonsterMode(monster, 14);
runLevelScriptCustom(0x404, -1, monster->id, monster->id, 0, 0);
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ checkSceneUpdateNeed(monster->block);
if (monster->mode == 14)
placeMonster(monster, 0, 0);
}
@@ -230,7 +230,7 @@ bool LoLEngine::updateMonsterAdjustBlocks(MonsterInPlay *monster) {
return false;
for (int i = 0; i < 18; i++)
- _visibleBlocks[i] = &_levelBlockProperties[(monster->blockPropertyIndex + _dscBlockIndex[dir + i]) & 0x3ff];
+ _visibleBlocks[i] = &_levelBlockProperties[(monster->block + _dscBlockIndex[dir + i]) & 0x3ff];
int16 fx1 = 0;
int16 fx2 = 0;
@@ -241,8 +241,8 @@ bool LoLEngine::updateMonsterAdjustBlocks(MonsterInPlay *monster) {
void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
bool cont = true;
- int t = monster->blockPropertyIndex;
- if (monster->blockPropertyIndex) {
+ int t = monster->block;
+ if (monster->block) {
removeAssignedObjectFromBlock(&_levelBlockProperties[t], ((uint16)monster->id) | 0x8000);
_levelBlockProperties[t].direction = 5;
checkSceneUpdateNeed(t);
@@ -250,7 +250,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
cont = false;
}
- monster->blockPropertyIndex = calcBlockIndex(x, y);
+ monster->block = calcBlockIndex(x, y);
if (monster->x != x || monster->y != y) {
monster->x = x;
@@ -258,26 +258,26 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
monster->currentSubFrame = (++monster->currentSubFrame) & 3;
}
- if (monster->blockPropertyIndex == 0)
+ if (monster->block == 0)
return;
- assignMonsterToBlock(&_levelBlockProperties[monster->blockPropertyIndex].assignedObjects, ((uint16)monster->id) | 0x8000);
- _levelBlockProperties[monster->blockPropertyIndex].direction = 5;
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ assignMonsterToBlock(&_levelBlockProperties[monster->block].assignedObjects, ((uint16)monster->id) | 0x8000);
+ _levelBlockProperties[monster->block].direction = 5;
+ checkSceneUpdateNeed(monster->block);
if (monster->properties->sounds[0] == 0 || cont == false)
return;
- if ((!(monster->properties->flags & 0x100) || ((monster->currentSubFrame & 1) == 0)) && monster->blockPropertyIndex == t)
+ if ((!(monster->properties->flags & 0x100) || ((monster->currentSubFrame & 1) == 0)) && monster->block == t)
return;
- if (monster->blockPropertyIndex != t)
- runLevelScriptCustom(monster->blockPropertyIndex, 0x800, -1, monster->id, 0, 0);
+ if (monster->block != t)
+ runLevelScriptCustom(monster->block, 0x800, -1, monster->id, 0, 0);
if (_updateFlags & 1)
return;
- snd_processEnvironmentalSoundEffect(monster->properties->sounds[0], monster->blockPropertyIndex);
+ snd_processEnvironmentalSoundEffect(monster->properties->sounds[0], monster->block);
}
int LoLEngine::calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
@@ -319,7 +319,7 @@ void LoLEngine::setMonsterDirection(MonsterInPlay *monster, int dir) {
if (!(dir & 1) || ((monster->direction - (monster->facing << 1)) >= 2))
monster->facing = monster->direction >> 1;
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ checkSceneUpdateNeed(monster->block);
}
void LoLEngine::monsterDropItems(MonsterInPlay *monster) {
@@ -651,45 +651,45 @@ void LoLEngine::drawMonster(uint16 id) {
}
}
- if (!m->field_1B)
+ if (!m->damageReceived)
return;
int dW = _screen->getShapeScaledWidth(shp, _dmScaleW) >> 1;
int dH = _screen->getShapeScaledHeight(shp, _dmScaleH) >> 1;
- int a = (m->mode == 13) ? (m->fightCurTick << 1) : (m->properties->might / (m->field_1B & 0x7fff));
+ int bloodAmount = (m->mode == 13) ? (m->fightCurTick << 1) : (m->properties->hitPoints / (m->damageReceived & 0x7fff));
shp = _gameShapes[6];
- int cF = m->properties->flags & 0xc000;
- if (cF == 0x4000)
- cF = 63;
- else if (cF == 0x8000)
- cF = 15;
- else if (cF == 0xc000)
- cF = 74;
+ int bloodType = m->properties->flags & 0xc000;
+ if (bloodType == 0x4000)
+ bloodType = 63;
+ else if (bloodType == 0x8000)
+ bloodType = 15;
+ else if (bloodType == 0xc000)
+ bloodType = 74;
else
- cF = 0;
+ bloodType = 0;
uint8 *tbl = new uint8[256];
- if (cF) {
+ if (bloodType) {
for (int i = 0; i < 256; i++) {
tbl[i] = i;
if (i < 2 || i > 7)
continue;
- tbl[i] += cF;
+ tbl[i] += bloodType;
}
}
- dW += m->anon8;
- dH += m->anonh;
+ dW += m->hitOffsX;
+ dH += m->hitOffsY;
- a = CLIP(a, 1, 4);
+ bloodAmount = CLIP(bloodAmount, 1, 4);
- int sW = _dmScaleW / a;
- int sH = _dmScaleH / a;
+ int sW = _dmScaleW / bloodAmount;
+ int sH = _dmScaleH / bloodAmount;
- _screen->drawShape(_sceneDrawPage1, shp, _shpDmX + dW, _shpDmY + dH, 13, 0x124, tbl, cF ? 1 : 0, sW, sH);
+ _screen->drawShape(_sceneDrawPage1, shp, _shpDmX + dW, _shpDmY + dH, 13, 0x124, tbl, bloodType ? 1 : 0, sW, sH);
delete[] tbl;
}
@@ -698,14 +698,14 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) {
switch (_monsterUnk[m->properties->shapeIndex]) {
case 0:
if (dirFlags) {
- return (m->properties->fightingStats[0] & 0xff) == 13 ? -1 : (dirFlags + m->currentSubFrame);
+ return (m->mode == 13) ? -1 : (dirFlags + m->currentSubFrame);
} else {
- if (m->field_1B)
+ if (m->damageReceived)
return 12;
switch (m->mode - 5) {
case 0:
- return m->field_1B ? 12 : ((m->properties->flags & 4) ? 13 : 0);
+ return (m->properties->flags & 4) ? 13 : 0;
case 3:
return (m->fightCurTick + 13);
case 6:
@@ -713,7 +713,7 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) {
case 8:
return -1;
default:
- return m->field_1B ? 12 : m->currentSubFrame;
+ return m->currentSubFrame;
}
}
break;
@@ -1013,9 +1013,9 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
monster->speedTick = 0;
if (monster->properties->flags & 0x40) {
- monster->might += _rnd.getRandomNumberRng(1, 8);
- if (monster->might > monster->properties->might)
- monster->might = monster->properties->might;
+ monster->hitPoints += _rnd.getRandomNumberRng(1, 8);
+ if (monster->hitPoints > monster->properties->hitPoints)
+ monster->hitPoints = monster->properties->hitPoints;
}
if (monster->flags & 8) {
@@ -1036,7 +1036,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
if ((monster->mode != 11) && (monster->mode != 14)) {
if (!(getRandomNumberSpecial() & 3)) {
monster->shiftStep = (++monster->shiftStep) & 0x0f;
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ checkSceneUpdateNeed(monster->block);
}
}
@@ -1062,7 +1062,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
if (updateMonsterAdjustBlocks(monster))
setMonsterMode(monster, 7);
for (int i = 0; i < 4; i++) {
- if (calcNewBlockPosition(monster->blockPropertyIndex, i) == _currentBlock)
+ if (calcNewBlockPosition(monster->block, i) == _currentBlock)
setMonsterMode(monster, 7);
}
break;
@@ -1096,7 +1096,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
// monster can't change mode before arriving at destination and/or attacking the party
if (!chasePartyWithDistanceAttacks(monster))
chasePartyWithCloseAttacks(monster);
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ checkSceneUpdateNeed(monster->block);
break;
case 8:
@@ -1105,7 +1105,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
setMonsterMode(monster, 5);
monster->fightCurTick = (int8) ((((8 << 8) / monster->properties->fightingStats[4]) * _monsterModifiers[6 + _monsterDifficulty]) >> 8);
}
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ checkSceneUpdateNeed(monster->block);
break;
case 9:
@@ -1119,7 +1119,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
break;
case 12:
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ checkSceneUpdateNeed(monster->block);
if (++monster->fightCurTick > 13)
runLevelScriptCustom(0x404, -1, monster->id, monster->id, 0, 0);
break;
@@ -1128,23 +1128,23 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
// monster death
if (++monster->fightCurTick > 2)
killMonster(monster);
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ checkSceneUpdateNeed(monster->block);
break;
case 14:
- monster->field_1B = 0;
+ monster->damageReceived = 0;
break;
default:
break;
}
- if (monster->field_1B) {
- if (monster->field_1B & 0x8000)
- monster->field_1B &= 0x7fff;
+ if (monster->damageReceived) {
+ if (monster->damageReceived & 0x8000)
+ monster->damageReceived &= 0x7fff;
else
- monster->field_1B = 0;
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ monster->damageReceived = 0;
+ checkSceneUpdateNeed(monster->block);
}
monster->flags &= 0xffef;
@@ -1174,10 +1174,10 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
setMonsterDirection(monster, _monsterLastWalkDirection);
} else {
setMonsterDirection(monster, s);
- if (monster->field_25) {
- if (getMonsterDistance(monster->blockPropertyIndex, _currentBlock) >= 2) {
- if (walkMonster_s3(monster->blockPropertyIndex, monster->direction, 3, _currentBlock) != 5) {
- if (monster->field_27)
+ if (monster->numDistAttacks) {
+ if (getMonsterDistance(monster->block, _currentBlock) >= 2) {
+ if (checkForPossibleDistanceAttack(monster->block, monster->direction, 3, _currentBlock) != 5) {
+ if (monster->distAttackTick)
return;
}
}
@@ -1192,9 +1192,80 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
}
bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) {
- if (!monster->field_25)
+ if (!monster->numDistAttacks)
return false;
+ if (monster->distAttackTick > 0) {
+ monster->distAttackTick--;
+ return false;
+ }
+
+ int dir = checkForPossibleDistanceAttack(monster->block, monster->facing, 4, _currentBlock);
+ if (dir == 5)
+ return false;
+
+ int s = 0;
+
+ if (monster->flags & 0x10) {
+ s = monster->properties->numDistWeapons ? _rnd.getRandomNumberRng(1, monster->properties->numDistWeapons) : 0;
+ } else {
+ s = monster->curDistWeapon++;
+ if (monster->curDistWeapon == monster->properties->numDistWeapons)
+ monster->curDistWeapon = 0;
+ }
+
+ int flyingObject = monster->properties->distWeapons[s];
+
+ if (flyingObject & 0xc000) {
+ if (getMonsterDistance(monster->block, _currentBlock) > 1) {
+ int type = flyingObject & 0x4000 ? 0 : 1;
+ flyingObject = makeItem(flyingObject & 0x3fff, 0, 0);
+
+ if (flyingObject) {
+ if (!launchObject(type, flyingObject, monster->x, monster->y, 12, dir << 1, -1, monster->id | 0x8000, 0x3f))
+ deleteItem(flyingObject);
+ }
+ }
+ } else if (!(flyingObject & 0x2000)) {
+ if (getMonsterDistance(monster->block, _currentBlock) > 1)
+ return false;
+
+ if (flyingObject == 1) {
+ snd_playSoundEffect(147, -1);
+ distObj1Sub(10, 2, 2, 1);
+
+ for (int i = 0; i < 4; i++) {
+ if (!(_characters[i].flags & 1))
+ continue;
+
+ int item = removeCharacterItem(i, 15);
+ if (item)
+ setItemPosition(item, _partyPosX, _partyPosY, 0, 1);
+
+ inflictDamage(i, 20, -1, 0, 2);
+ }
+
+ } else if (flyingObject == 3) {
+ // shriek
+ for (int i = 0; i < 30; i++) {
+ if (getMonsterDistance(monster->block, _monsters[i].block) < 7)
+ setMonsterMode(monster, 7);
+ }
+ _txt->printMessage(2, getLangString(0x401a));
+
+ } else if (flyingObject == 4) {
+ launchMagicViper();
+
+ } else {
+ return false;
+ }
+ }
+
+ if (monster->numDistAttacks != 255)
+ monster->numDistAttacks--;
+
+ monster->distAttackTick = (monster->properties->fightingStats[4] * 8) >> 8;
+
return true;
}
@@ -1209,23 +1280,24 @@ void LoLEngine::chasePartyWithCloseAttacks(MonsterInPlay *monster) {
int t = (x1 < 0) ? -x1 : x1;
if (y1 <= 160 && t <= 80) {
if ((monster->direction == dir) && (monster->facing == (dir >> 1))) {
- int dst = getClosestPartyMember(monster->x, monster->y);
+ int dst = getNearestPartyMemberFromPos(monster->x, monster->y);
snd_playSoundEffect(monster->properties->sounds[1], -1);
int m = monster->id | 0x8000;
int hit = battleHitSkillTest(m, dst, 0);
if (hit) {
- int dmg = _rnd.getRandomNumberRng(2, calcInflictableDamage(m, dst, hit));
- battleHit_sub2(dst, dmg, m, 0);
- battleHit_sub3(monster, dst, dmg);
+ int mx = calcInflictableDamage(m, dst, hit);
+ int dmg = mx ? _rnd.getRandomNumberRng(2, mx) : 0;
+ inflictDamage(dst, dmg, m, 0, 0);
+ applyMonsterAttackSkill(monster, dst, dmg);
}
setMonsterMode(monster, 8);
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ checkSceneUpdateNeed(monster->block);
} else {
setMonsterDirection(monster, dir);
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ checkSceneUpdateNeed(monster->block);
}
return;
}
@@ -1308,24 +1380,26 @@ int LoLEngine::getMonsterDistance(uint16 block1, uint16 block2) {
return (dx << 1) + dy;
}
-int LoLEngine::walkMonster_s3(uint16 monsterBlock, int direction, int distance, uint16 curBlock) {
+int LoLEngine::checkForPossibleDistanceAttack(uint16 monsterBlock, int direction, int distance, uint16 curBlock) {
int mdist = getMonsterDistance(curBlock, monsterBlock);
if (mdist > distance)
return 5;
int dir = calcMonsterDirection(monsterBlock & 0x1f, monsterBlock >> 5, curBlock & 0x1f, curBlock >> 5);
- if ((dir & 1) || ((dir << 1) != direction))
+ if ((dir & 1) || (dir != direction << 1))
return 5;
- if (((monsterBlock & 0x1f) != (curBlock & 0x1f)) || ((monsterBlock & 0xffe0) != (curBlock & 0xffe0)))
+ if (((monsterBlock & 0x1f) != (curBlock & 0x1f)) && ((monsterBlock & 0xffe0) != (curBlock & 0xffe0)))
return 5;
if (distance < 0)
return 5;
+ int p = monsterBlock;
+
for (int i = 0; i < distance; i++) {
- int p = calcNewBlockPosition(monsterBlock, direction);
+ p = calcNewBlockPosition(p, direction);
if (p == curBlock)
return direction;
@@ -1373,7 +1447,7 @@ void LoLEngine::rearrangeAttackingMonster(MonsterInPlay *monster) {
if (monster->nextAssignedObject & 0x8000) {
r = true;
} else {
- uint16 id = _levelBlockProperties[monster->blockPropertyIndex].assignedObjects;
+ uint16 id = _levelBlockProperties[monster->block].assignedObjects;
id = (id & 0x8000) ? (id & 0x7fff) : 0xffff;
if (id != monster->id) {
@@ -1381,7 +1455,7 @@ void LoLEngine::rearrangeAttackingMonster(MonsterInPlay *monster) {
} else {
for (int i = 0; i < 3; i++) {
t = (t + 1) & 3;
- id = _levelBlockProperties[calcNewBlockPosition(monster->blockPropertyIndex, t)].assignedObjects;
+ id = _levelBlockProperties[calcNewBlockPosition(monster->block, t)].assignedObjects;
id = (id & 0x8000) ? (id & 0x7fff) : 0xffff;
if (id != 0xffff)
r = true;
@@ -1465,12 +1539,12 @@ void LoLEngine::moveStrayingMonster(MonsterInPlay *monster) {
void LoLEngine::killMonster(MonsterInPlay *monster) {
setMonsterMode(monster, 14);
monsterDropItems(monster);
- checkSceneUpdateNeed(monster->blockPropertyIndex);
+ checkSceneUpdateNeed(monster->block);
- uint8 w = _levelBlockProperties[monster->blockPropertyIndex].walls[0];
- uint8 f = _levelBlockProperties[monster->blockPropertyIndex].flags;
+ uint8 w = _levelBlockProperties[monster->block].walls[0];
+ uint8 f = _levelBlockProperties[monster->block].flags;
if (_wllVmpMap[w] == 0 && _wllShapeMap[w] == 0 && !(f & 0x40) && !(monster->properties->flags & 0x1000))
- _levelBlockProperties[monster->blockPropertyIndex].flags |= 0x80;
+ _levelBlockProperties[monster->block].flags |= 0x80;
placeMonster(monster, 0, 0);
}
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index ef45c0b6e4..b60a7f1e90 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -44,7 +44,7 @@
namespace Kyra {
-#define RESFILE_VERSION 44
+#define RESFILE_VERSION 45
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
@@ -449,6 +449,8 @@ bool StaticResource::init() {
{ lolMapStringId, kLolRawDataBe16, "MAPSTRID.LST" },
//{ lolMapPal, kRawData, "MAP.PAL" },
+ { lolHealShapeFrames, kRawData, "MHEAL.SHP" },
+
{ 0, 0, 0 }
};
#endif // ENABLE_LOL
@@ -992,20 +994,13 @@ bool StaticResource::loadCharData(const char *filename, void *&ptr, int &size) {
t->id = file->readSint16LE();
t->curFaceFrame = file->readByte();
t->defaultFaceFrame = file->readByte();
- t->field_12 = file->readByte();
+ t->screamSfx = file->readByte();
file->readUint32LE();
for (int ii = 0; ii < 8; ii++)
t->itemsMight[ii] = file->readUint16LE();
- for (int ii = 0; ii < 2; ii++)
- t->field_27[ii] = file->readUint16LE();
- t->field_2B = file->readByte();
- t->field_2C = file->readUint16LE();
- t->field_2E = file->readUint16LE();
- t->field_30 = file->readUint16LE();
- t->field_32 = file->readUint16LE();
- t->field_34 = file->readUint16LE();
- t->field_36 = file->readByte();
- t->itemsProtection = file->readUint16LE();
+ for (int ii = 0; ii < 8; ii++)
+ t->protectionAgainstItems[ii] = file->readUint16LE();
+ t->itemProtection = file->readUint16LE();
t->hitPointsCur = file->readSint16LE();;
t->hitPointsMax = file->readUint16LE();;
t->magicPointsCur = file->readSint16LE();;
@@ -1027,9 +1022,9 @@ bool StaticResource::loadCharData(const char *filename, void *&ptr, int &size) {
for (int ii = 0; ii < 3; ii++)
t->experiencePts[ii] = file->readUint32LE();
for (int ii = 0; ii < 5; ii++)
- t->arrayUnk2[ii] = file->readByte();
+ t->characterUpdateEvents[ii] = file->readByte();
for (int ii = 0; ii < 5; ii++)
- t->arrayUnk1[ii] = file->readByte();
+ t->characterUpdateDelay[ii] = file->readByte();
};
ptr = charData;
@@ -1430,47 +1425,28 @@ void KyraEngine_LoK::initStaticResource() {
// FIXME: It seems Kyra1 MAC CD includes AdLib and MIDI music and sfx, thus we enable
// support for those for now. (Based on patch #2767489 "Support for Mac Kyrandia 1 CD" by satz).
+ memset(_soundData, 0, sizeof(_soundData));
if (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformMacintosh) {
- _soundData[0]._fileList = _soundFilesIntro;
- _soundData[0]._fileListLen = _soundFilesIntroSize;
- _soundData[0]._cdaTracks = 0;
- _soundData[0]._cdaNumTracks = 0;
- _soundData[1]._fileList = _soundFiles;
- _soundData[1]._fileListLen = _soundFilesSize;
- _soundData[1]._cdaTracks = 0;
- _soundData[1]._cdaNumTracks = 0;
- _soundData[2]._fileList = 0;
- _soundData[2]._fileListLen = 0;
- _soundData[2]._cdaTracks = 0;
- _soundData[2]._cdaNumTracks = 0;
+ _soundData[0].fileList = _soundFilesIntro;
+ _soundData[0].fileListLen = _soundFilesIntroSize;
+ _soundData[1].fileList = _soundFiles;
+ _soundData[1].fileListLen = _soundFilesSize;
} else if (_flags.platform == Common::kPlatformFMTowns) {
- _soundData[0]._fileList = _soundFiles;
- _soundData[0]._fileListLen = _soundFilesSize;
- _soundData[0]._cdaTracks = _cdaTrackTable;
- _soundData[0]._cdaNumTracks = _cdaTrackTableSize;
- _soundData[1]._fileList = _soundFiles;
- _soundData[1]._fileListLen = _soundFilesSize;
- _soundData[1]._cdaTracks = _cdaTrackTable;
- _soundData[1]._cdaNumTracks = _cdaTrackTableSize;
- _soundData[2]._fileList = 0;
- _soundData[2]._fileListLen = 0;
- _soundData[2]._cdaTracks = 0;
- _soundData[2]._cdaNumTracks = 0;
+ _soundData[0].fileList = _soundFiles;
+ _soundData[0].fileListLen = _soundFilesSize;
+ _soundData[0].cdaTracks = _cdaTrackTable;
+ _soundData[0].cdaNumTracks = _cdaTrackTableSize;
+ _soundData[1].fileList = _soundFiles;
+ _soundData[1].fileListLen = _soundFilesSize;
+ _soundData[1].cdaTracks = _cdaTrackTable;
+ _soundData[1].cdaNumTracks = _cdaTrackTableSize;
} else if (_flags.platform == Common::kPlatformPC98) {
- _soundData[0]._fileList = tIntro98;
- _soundData[0]._fileListLen = 1;
- _soundData[0]._cdaTracks = 0;
- _soundData[0]._cdaNumTracks = 0;
- _soundData[1]._fileList = tIngame98;
- _soundData[1]._fileListLen = 1;
- _soundData[1]._cdaTracks = 0;
- _soundData[1]._cdaNumTracks = 0;
- _soundData[2]._fileList = 0;
- _soundData[2]._fileListLen = 0;
- _soundData[2]._cdaTracks = 0;
- _soundData[2]._cdaNumTracks = 0;
- } else {
- memset(_soundData, 0, sizeof(_soundData));
+ _soundData[0].fileList = tIntro98;
+ _soundData[0].fileListLen = 1;
+ _soundData[0].extraOffset = -56;
+ _soundData[1].fileList = tIngame98;
+ _soundData[1].fileListLen = 1;
+ _soundData[1].extraOffset = -1;
}
}
@@ -1673,45 +1649,34 @@ void KyraEngine_HoF::initStaticResource() {
static const char *pc98MusicFileListFinale[] = { "finale%d.86" };
static const char *pc98MusicFileListIngame[] = { "km%02d.86" };
+ memset(_soundData, 0, sizeof(_soundData));
if (_flags.platform == Common::kPlatformPC) {
- _soundData[0]._fileList = _musicFileListIntro;
- _soundData[0]._fileListLen = _musicFileListIntroSize;
- _soundData[0]._cdaTracks = 0;
- _soundData[0]._cdaNumTracks = 0;
- _soundData[1]._fileList = _musicFileListIngame;
- _soundData[1]._fileListLen = _musicFileListIngameSize;
- _soundData[1]._cdaTracks = 0;
- _soundData[1]._cdaNumTracks = 0;
- _soundData[2]._fileList = _musicFileListFinale;
- _soundData[2]._fileListLen = _musicFileListIntroSize;
- _soundData[2]._cdaTracks = 0;
- _soundData[2]._cdaNumTracks = 0;
+ _soundData[0].fileList = _musicFileListIntro;
+ _soundData[0].fileListLen = _musicFileListIntroSize;
+ _soundData[1].fileList = _musicFileListIngame;
+ _soundData[1].fileListLen = _musicFileListIngameSize;
+ _soundData[2].fileList = _musicFileListFinale;
+ _soundData[2].fileListLen = _musicFileListIntroSize;
} else if (_flags.platform == Common::kPlatformFMTowns) {
- _soundData[0]._fileList = fmtMusicFileListIntro;
- _soundData[0]._fileListLen = 1;
- _soundData[0]._cdaTracks = _cdaTrackTableIntro;
- _soundData[0]._cdaNumTracks = _cdaTrackTableIntroSize >> 1;
- _soundData[1]._fileList = fmtMusicFileListIngame;
- _soundData[1]._fileListLen = 1;
- _soundData[1]._cdaTracks = _cdaTrackTableIngame;
- _soundData[1]._cdaNumTracks = _cdaTrackTableIngameSize >> 1;
- _soundData[2]._fileList = fmtMusicFileListFinale;
- _soundData[2]._fileListLen = 1;
- _soundData[2]._cdaTracks = _cdaTrackTableFinale;
- _soundData[2]._cdaNumTracks = _cdaTrackTableFinaleSize >> 1;
+ _soundData[0].fileList = fmtMusicFileListIntro;
+ _soundData[0].fileListLen = 1;
+ _soundData[0].cdaTracks = _cdaTrackTableIntro;
+ _soundData[0].cdaNumTracks = _cdaTrackTableIntroSize >> 1;
+ _soundData[1].fileList = fmtMusicFileListIngame;
+ _soundData[1].fileListLen = 1;
+ _soundData[1].cdaTracks = _cdaTrackTableIngame;
+ _soundData[1].cdaNumTracks = _cdaTrackTableIngameSize >> 1;
+ _soundData[2].fileList = fmtMusicFileListFinale;
+ _soundData[2].fileListLen = 1;
+ _soundData[2].cdaTracks = _cdaTrackTableFinale;
+ _soundData[2].cdaNumTracks = _cdaTrackTableFinaleSize >> 1;
} else if (_flags.platform == Common::kPlatformPC98) {
- _soundData[0]._fileList = pc98MusicFileListIntro;
- _soundData[0]._fileListLen = 1;
- _soundData[0]._cdaTracks = 0;
- _soundData[0]._cdaNumTracks = 0;
- _soundData[1]._fileList = pc98MusicFileListIngame;
- _soundData[1]._fileListLen = 1;
- _soundData[1]._cdaTracks = 0;
- _soundData[1]._cdaNumTracks = 0;
- _soundData[2]._fileList = pc98MusicFileListFinale;
- _soundData[2]._fileListLen = 1;
- _soundData[2]._cdaTracks = 0;
- _soundData[2]._cdaNumTracks = 0;
+ _soundData[0].fileList = pc98MusicFileListIntro;
+ _soundData[0].fileListLen = 1;
+ _soundData[1].fileList = pc98MusicFileListIngame;
+ _soundData[1].fileListLen = 1;
+ _soundData[2].fileList = pc98MusicFileListFinale;
+ _soundData[2].fileListLen = 1;
}
// setup sequence data
@@ -1884,10 +1849,33 @@ void LoLEngine::initStaticResource() {
memcpy (_mapCursorOverlay, tmp, tmpSize);
_staticres->unloadId(lolMapCursorOvl);
- /*tmp = _staticres->loadRawData(lolMapPal, tmpSize);
- _screen->_automapPal = new uint8[tmpSize];
- memcpy (_screen->_automapPal, tmp, tmpSize);
- _staticres->unloadId(lolMapPal);*/
+ _healShapeFrames = _staticres->loadRawData(lolHealShapeFrames, _healShapeFramesSize);
+
+ // assign music data
+ static const char *pcMusicFileListIntro[] = { "LOREINTR" };
+ static const char *pcMusicFileListFinale[] = { "LOREFINL" };
+ static const char *pcMusicFileListIngame[] = { "LORE%02d%c" };
+
+ static const char *pc98MusicFileListIntro[] = { 0, "lore84.86", "lore82.86", 0, 0, 0, "lore83.86", "lore81.86" };
+ static const char *pc98MusicFileListFinale[] = { "lore%02d.86" };
+ static const char *pc98MusicFileListIngame[] = { "lore%02d.86" };
+
+ memset(_soundData, 0, sizeof(_soundData));
+ if (_flags.platform == Common::kPlatformPC) {
+ _soundData[0].fileList = pcMusicFileListIntro;
+ _soundData[0].fileListLen = 1;
+ _soundData[1].fileList = pcMusicFileListIngame;
+ _soundData[1].fileListLen = 1;
+ _soundData[2].fileList = pcMusicFileListFinale;
+ _soundData[3].fileListLen = 1;
+ } else if (_flags.platform == Common::kPlatformPC98) {
+ _soundData[0].fileList = pc98MusicFileListIntro;
+ _soundData[0].fileListLen = ARRAYSIZE(pc98MusicFileListIntro);
+ _soundData[1].fileList = pc98MusicFileListIngame;
+ _soundData[1].fileListLen = 1;
+ _soundData[2].fileList = pc98MusicFileListFinale;
+ _soundData[2].fileListLen = ARRAYSIZE(pc98MusicFileListFinale);;
+ }
}
void LoLEngine::assignButtonCallback(Button *button, int index) {
@@ -2949,7 +2937,7 @@ const int8 KyraEngine_MR::_albumWSAY[] = {
// lands of lore static res
#ifdef ENABLE_LOL
-const ScreenDim Screen_LoL::_screenDimTable[] = {
+const ScreenDim Screen_LoL::_screenDimTable256C[] = {
{ 0x00, 0x00, 0x28, 0xC8, 0xC7, 0xCF, 0x00, 0x00 }, // Taken from Intro
{ 0x08, 0x48, 0x18, 0x38, 0xFE, 0x01, 0x00, 0x00 },
{ 0x0E, 0x00, 0x16, 0x78, 0xFE, 0x01, 0x00, 0x00 },
@@ -2966,7 +2954,24 @@ const ScreenDim Screen_LoL::_screenDimTable[] = {
{ 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 } // Main menu box (3 entries, floppy version only)
};
-const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable);
+const ScreenDim Screen_LoL::_screenDimTable16C[] = {
+ { 0x00, 0x00, 0x28, 0xC8, 0x33, 0x44, 0x00, 0x00 }, // Taken from Intro
+ { 0x08, 0x48, 0x18, 0x38, 0x33, 0x44, 0x00, 0x00 },
+ { 0x0E, 0x00, 0x16, 0x78, 0x33, 0x44, 0x00, 0x00 },
+ { 0x0B, 0x7B, 0x1C, 0x12, 0x33, 0x11, 0x00, 0x00 },
+ { 0x0B, 0x7B, 0x1C, 0x2D, 0x33, 0x11, 0x00, 0x00 },
+ { 0x55, 0x7B, 0xE9, 0x37, 0x33, 0x11, 0x00, 0x00 },
+ { 0x0B, 0x8C, 0x10, 0x2B, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (4 entries)
+ { 0x04, 0x59, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x05, 0x6E, 0x1E, 0x0C, 0x33, 0x44, 0x00, 0x00 },
+ { 0x07, 0x19, 0x1A, 0x97, 0x00, 0x00, 0x00, 0x00 },
+ { 0x03, 0x1E, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 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)
+};
+
+const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable256C);
const char * const LoLEngine::_languageExt[] = {
"ENG",
diff --git a/engines/kyra/timer.cpp b/engines/kyra/timer.cpp
index f9bb36206e..4d510abcdd 100644
--- a/engines/kyra/timer.cpp
+++ b/engines/kyra/timer.cpp
@@ -232,7 +232,7 @@ void TimerManager::pauseSingleTimer(uint8 id, bool p) {
timer->enabled &= (~2);
timer->lastUpdate += elapsedTime;
timer->nextRun += elapsedTime;
- resync();
+ resetNextRun();
timer->pauseStartTime = 0;
}
}
diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp
index f82687b2d5..79bb8d1c2d 100644
--- a/engines/kyra/timer_lol.cpp
+++ b/engines/kyra/timer_lol.cpp
@@ -40,12 +40,12 @@ void LoLEngine::setupTimers() {
_timer->addTimer(0x10, TimerV2(timerProcessMonsters), 6, true);
_timer->addTimer(0x11, TimerV2(timerProcessMonsters), 6, true);
_timer->setNextRun(0x11, _system->getMillis() + 3 * _tickLength);
- _timer->addTimer(3, TimerV2(timerSub3), 15, true);
+ _timer->addTimer(3, TimerV2(timerSpecialCharacterUpdate), 15, true);
_timer->addTimer(4, TimerV2(timerProcessFlyingObjects), 1, true);
_timer->addTimer(0x50, TimerV2(timerRunSceneAnimScript), 0, false);
_timer->addTimer(0x51, TimerV2(timerRunSceneAnimScript), 0, false);
_timer->addTimer(0x52, TimerV2(timerRunSceneAnimScript), 0, false);
- _timer->addTimer(8, TimerV2(timerSub6), 1200, true);
+ _timer->addTimer(8, TimerV2(timerRegeneratePoints), 1200, true);
_timer->addTimer(9, TimerV2(timerUpdatePortraitAnimations), 10, true);
_timer->addTimer(10, TimerV2(timerUpdateLampState), 360, true);
_timer->addTimer(11, TimerV2(timerFadeMessageText), 360, false);
@@ -104,22 +104,101 @@ void LoLEngine::timerProcessDoors(int timerNum) {
}
void LoLEngine::timerProcessMonsters(int timerNum) {
-// if (!_updateMonsters)
-// return;
-
for (int i = timerNum & 0x0f; i < 30; i += 2)
updateMonster(&_monsters[i]);
}
-void LoLEngine::timerSub3(int timerNum) {
+void LoLEngine::timerSpecialCharacterUpdate(int timerNum) {
+ int v = 0;
+ for (int i = 0; i < 4; i++) {
+ if (!(_characters[i].flags & 1))
+ continue;
+
+ for (int ii = 0; ii < 5; ii++) {
+ if (!(_characters[i].characterUpdateEvents[ii]))
+ continue;
+
+ if (--_characters[i].characterUpdateDelay[ii] > 0) {
+ if (_characters[i].characterUpdateDelay[ii] > v)
+ v = _characters[i].characterUpdateDelay[ii];
+ continue;
+ }
+
+ switch (_characters[i].characterUpdateEvents[ii] - 1) {
+ case 0:
+ if (_characters[i].weaponHit) {
+ _characters[i].weaponHit = 0;
+ _characters[i].characterUpdateDelay[ii] = calcMonsterSkillLevel(i, 6);
+ if (_characters[i].characterUpdateDelay[ii] > v)
+ v = _characters[i].characterUpdateDelay[ii];
+ } else {
+ _characters[i].flags &= 0xfffb;
+ }
+
+ gui_drawCharPortraitWithStats(i);
+ break;
+
+ case 1:
+ _characters[i].damageSuffered = 0;
+ gui_drawCharPortraitWithStats(i);
+ break;
+
+ case 2:
+ _characters[i].flags &= 0xffbf;
+ gui_drawCharPortraitWithStats(i);
+ break;
+
+ case 3:
+ v = _rnd.getRandomNumberRng(1, 2);
+ if (inflictDamage(i, v, 0x8000, 0, 0x80)) {
+ _txt->printMessage(2, getLangString(0x4022), _characters[i].name);
+ _characters[i].characterUpdateDelay[ii] = 10;
+ if (_characters[i].characterUpdateDelay[ii] > v)
+ v = _characters[i].characterUpdateDelay[ii];
+ }
+ break;
+
+ case 4:
+ _characters[i].flags &= 0xfeff;
+ _txt->printMessage(0, getLangString(0x4027), _characters[i].name);
+ gui_drawCharPortraitWithStats(i);
+ break;
+
+ case 5:
+ setTemporaryFaceFrame(i, 0, 0, 1);
+ break;
+
+ case 6:
+ _characters[i].flags &= 0xefff;
+ gui_drawCharPortraitWithStats(i);
+ break;
+
+ case 7:
+ level11specialUnk();
+ break;
+
+ default:
+ break;
+ }
+
+ if (_characters[i].characterUpdateDelay[ii] <= 0)
+ _characters[i].characterUpdateEvents[ii] = 0;
+ }
+ }
+ if (v) {
+ _timer->enable(3);
+ _timer3Para = v * 15;
+ } else {
+ _timer->disable(3);
+ }
}
void LoLEngine::timerProcessFlyingObjects(int timerNum) {
for (int i = 0; i < 8; i++) {
if (!_flyingObjects[i].enable)
continue;
- updateFlyingObjects(&_flyingObjects[i]);
+ updateFlyingObject(&_flyingObjects[i]);
}
}
@@ -127,8 +206,24 @@ void LoLEngine::timerRunSceneAnimScript(int timerNum) {
runLevelScript(0x401 + (timerNum & 0x0f), -1);
}
-void LoLEngine::timerSub6(int timerNum) {
+void LoLEngine::timerRegeneratePoints(int timerNum) {
+ for (int i = 0; i < 4; i++) {
+ if (!(_characters[i].flags & 1))
+ continue;
+ // check for Duble ring
+ int hInc = (_characters[i].flags & 8) ? 0 : (itemEquipped(i, 228) ? 4 : 1);
+ // check for Talba ring
+ int mInc = _drainMagic ? ((_characters[i].magicPointsMax >> 5) * -1) :
+ ((_characters[i].flags & 8) ? 0 : (itemEquipped(i, 227) ? (_characters[i].magicPointsMax / 10) : 1));
+
+ _characters[i].magicPointsCur = CLIP<int16>(_characters[i].magicPointsCur + mInc, 0, _characters[i].magicPointsMax);
+
+ if (!(_characters[i].flags & 0x80))
+ increaseCharacterHitpoints(i, hInc, false);
+
+ gui_drawCharPortraitWithStats(i);
+ }
}
void LoLEngine::timerUpdatePortraitAnimations(int skipUpdate) {
diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp
index 818f3c691f..50d17659a4 100644
--- a/engines/kyra/wsamovie.cpp
+++ b/engines/kyra/wsamovie.cpp
@@ -372,11 +372,20 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) {
offsPal = 0x300;
_flags |= WF_HAS_PALETTE;
if (palBuf)
- memcpy(palBuf, wsaData + 8 + ((_numFrames << 2) & 0xFFFF), 0x300);
+ _vm->screen()->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), palBuf, 0x300);
}
- if (flags & 2)
+ if (flags & 2) {
+ if (_vm->gameFlags().use16ColorMode) {
+ offsPal = 0x30;
+ _flags |= WF_HAS_PALETTE;
+ if (palBuf)
+ _vm->screen()->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), palBuf, 0x30);
+ }
+
_flags |= WF_XOR;
+ }
+
if (!(unk1 & 2)) {
_flags |= WF_OFFSCREEN_DECODE;
diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp
index 8000585eea..d8876cde3c 100644
--- a/tools/create_kyradat/create_kyradat.cpp
+++ b/tools/create_kyradat/create_kyradat.cpp
@@ -31,7 +31,7 @@
#include "md5.h"
enum {
- kKyraDatVersion = 44,
+ kKyraDatVersion = 45,
kIndexSize = 12
};
@@ -341,6 +341,8 @@ const ExtractFilename extractFilenames[] = {
{ lolMapStringId, lolTypeRaw16, "MAPSTRID.LST" },
//{ lolMapPal, kTypeRawData, "MAP.PAL" },
+ { lolHealShapeFrames, kTypeRawData, "MHEAL.SHP" },
+
{ -1, 0, 0 }
};
diff --git a/tools/create_kyradat/create_kyradat.h b/tools/create_kyradat/create_kyradat.h
index a2ffb754d3..9589340ebc 100644
--- a/tools/create_kyradat/create_kyradat.h
+++ b/tools/create_kyradat/create_kyradat.h
@@ -251,6 +251,8 @@ enum kExtractID {
lolMapStringId,
//lolMapPal,
+ lolHealShapeFrames,
+
kMaxResIDs
};
diff --git a/tools/create_kyradat/lol_cd.h b/tools/create_kyradat/lol_cd.h
index 0ccf6446ab..d05f74f05d 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 },
+ { lolHealShapeFrames, 0x000297D0, 0x00029820 },
+
{ -1, 0, 0 }
};
diff --git a/tools/create_kyradat/misc.h b/tools/create_kyradat/misc.h
index 91cde9b6e8..c154d423e5 100644
--- a/tools/create_kyradat/misc.h
+++ b/tools/create_kyradat/misc.h
@@ -557,6 +557,8 @@ const int lolCDFile2Need[] = {
lolMapStringId,
//lolMapPal,
+ lolHealShapeFrames,
+
-1
};