aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/kyra/gui_lol.cpp3
-rw-r--r--engines/kyra/lol.cpp203
-rw-r--r--engines/kyra/lol.h12
-rw-r--r--engines/kyra/saveload.cpp2
-rw-r--r--engines/kyra/saveload_lol.cpp19
-rw-r--r--engines/kyra/scene_lol.cpp10
-rw-r--r--engines/kyra/screen_lol.cpp10
-rw-r--r--engines/kyra/screen_lol.h2
-rw-r--r--engines/kyra/script_lol.cpp43
-rw-r--r--engines/kyra/sprites_lol.cpp2
-rw-r--r--engines/kyra/timer_lol.cpp2
11 files changed, 258 insertions, 50 deletions
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp
index 0500411b98..bedc1a2d39 100644
--- a/engines/kyra/gui_lol.cpp
+++ b/engines/kyra/gui_lol.cpp
@@ -1048,7 +1048,7 @@ int LoLEngine::clickedAttackButton(Button *button) {
int bl = calcNewBlockPosition(_currentBlock, _currentDirection);
if (_levelBlockProperties[bl].flags & 0x10) {
- attackWall(0, 0);
+ breakIceWall(0, 0);
return 1;
}
@@ -1750,6 +1750,7 @@ int LoLEngine::clickedAutomap(Button *button) {
if (!(_gameFlags[15] & 0x1000))
return 0;
+ removeInputTop();
displayAutomap();
gui_drawPlayField();
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 724a9316bb..14b9cad751 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -123,7 +123,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_lastButtonShape = 0;
_buttonPressTimer = 0;
_selectedCharacter = 0;
- _unkFlag = 0;
+ _gameFlags[36] = 0;
_suspendScript = _sceneUpdateRequired = false;
_scriptDirection = 0;
_currentDirection = 0;
@@ -226,7 +226,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_floatingCursorsEnabled = false;
memset(_lvlTempData, 0, sizeof(_lvlTempData));
- _freezeStateFlags = 0;
+ _gameFlags[26] = 0;
_mapOverlay = 0;
_automapShapes = 0;
@@ -868,7 +868,7 @@ void LoLEngine::runLoop() {
enableSysTimer(2);
bool _runFlag = true;
- _unkFlag |= 0x800;
+ _gameFlags[36] |= 0x800;
while (!shouldQuit() && _runFlag) {
if (_nextScriptFunc) {
@@ -2411,26 +2411,143 @@ void LoLEngine::processMagicIce(int charNum, int spellLevel) {
gui_drawScene(0);
_screen->copyPage(0, 12);
- //uint8 pal2[768];
- //uint8 pal3[768];
+ uint8 *tpal = new uint8[768];
+ uint8 *swampCol = new uint8[768];
- if (_currentLevel == 11 && !(_freezeStateFlags & 4)) {
- for (int i = 1; i < 384; i++) {
+ if (_currentLevel == 11 && !(_gameFlags[26] & 4)) {
+ uint8 *sc = _screen->_currentPalette;
+ uint8 *dc = _screen->getPalette(2);
+ for (int i = 1; i < 768; i++)
+ SWAP(sc[i], dc[i]);
+ _gameFlags[26] |= 4;
+ static const uint8 freezeTimes[] = { 20, 28, 40, 60 };
+ setCharacterUpdateEvent(charNum, 8, freezeTimes[spellLevel], 1);
+ }
- ///////// TODO
+ uint8 *sc = _res->fileData("swampice.col", 0);
+ memcpy(swampCol, sc, 384);
+ uint8 *s = _screen->getPalette(1);
+ for (int i = 384; i < 768; i++)
+ swampCol[i] = tpal[i] = s[i] & 0x3f;
+
+ for (int i = 1; i < 128; i++) {
+ tpal[i * 3] = 0;
+ uint16 v = (s[i * 3] + s[i * 3 + 1] + s[i * 3 + 2]) / 3;
+ tpal[i * 3 + 1] = v;
+ tpal[i * 3 + 2] = v << 1;
+
+ if (tpal[i * 3 + 2] > 0x3f)
+ tpal[i * 3 + 2] = 0x3f;
+ }
+ generateBrightnessPalette(tpal, tpal, _brightness, _lampEffect);
+ generateBrightnessPalette(swampCol, swampCol, _brightness, _lampEffect);
+ swampCol[0] = swampCol[1] = swampCol[2] = tpal[0] = tpal[1] = tpal[2] = 0;
+
+ generateBrightnessPalette(_screen->_currentPalette, s, _brightness, _lampEffect);
+
+ int sX = 112;
+ int sY = 0;
+ WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+
+ if (spellLevel == 0) {
+ sX = 0;
+ } if (spellLevel == 1 || spellLevel == 2) {
+ mov->open("snow.wsa", 1, 0);
+ if (!mov->opened())
+ error("Ice: Unable to load snow.wsa");
+ } if (spellLevel == 3) {
+ mov->open("ice.wsa", 1, 0);
+ if (!mov->opened())
+ error("Ice: Unable to load ice.wsa");
+ sX = 136;
+ sY = 12;
+ }
- }
+ snd_playSoundEffect(71, -1);
- _freezeStateFlags |= 4;
- static const uint8 freezeTimes[] = { 20, 28, 40, 60 };
- setCharacterUpdateEvent(charNum, 8, freezeTimes[spellLevel], 1);
+ playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s, tpal, 40, false);
+
+ _screen->fadePaletteStep(s, tpal, _system->getMillis(), _tickLength);
+ if (mov->opened()) {
+ int r = true;
+ if (spellLevel > 2) {
+ _levelBlockProperties[calcNewBlockPosition(_currentBlock, _currentDirection)].flags |= 0x10;
+ snd_playSoundEffect(165, -1);
+ r = false;
+ };
+
+ playSpellAnimation(mov, 0, mov->frames(), 2, sX, sY, 0, 0, 0, 0, r);
+ mov->close();
+ }
+
+ delete mov;
+ static const uint8 snowDamage[] = { 10, 20, 30, 55 };
+ static const uint8 iceDamageMax[] = {1, 2, 15, 20, 35};
+ static const uint8 iceDamageMin[] = {10, 10, 3, 4, 4};
+ static const uint8 iceDamageAdd[] = {5, 10, 30, 10, 10};
+
+ bool breakWall = false;
+
+ if (spellLevel < 3) {
+ inflictMagicalDamageForBlock(calcNewBlockPosition(_currentBlock, _currentDirection), charNum, snowDamage[spellLevel], 3);
+ } else {
+ uint16 o = _levelBlockProperties[calcNewBlockPosition(_currentBlock, _currentDirection)].assignedObjects;
+ while (o & 0x8000) {
+ int might = _rnd.getRandomNumberRng(iceDamageMin[spellLevel], iceDamageMax[spellLevel]) + iceDamageAdd[spellLevel];
+ int dmg = calcInflictableDamagePerItem(charNum, 0, might, 3, 2);
+
+ MonsterInPlay *m = &_monsters[o & 0x7fff];
+ if (m->hitPoints <= dmg) {
+ increaseExperience(charNum, 2, m->hitPoints);
+ o = m->nextAssignedObject;
+
+ if (m->flags & 0x20) {
+ m->mode = 0;
+ monsterDropItems(m);
+ if (_currentLevel != 29)
+ setMonsterMode(m, 14);
+ runLevelScriptCustom(0x404, -1, o, o, 0, 0);
+ checkSceneUpdateNeed(m->block);
+ if (m->mode != 14)
+ placeMonster(m, 0, 0);
+
+ } else {
+ killMonster(m);
+ }
+
+ } else {
+ breakWall = true;
+ inflictDamage(o, dmg, charNum, 2, 3);
+ m->damageReceived = 0;
+ o = m->nextAssignedObject;
+ }
+
+ if (m->flags & 0x20)
+ break;
+ }
}
- ////////// TODO
- generateBrightnessPalette(_screen->_currentPalette, _screen->getPalette(1), _brightness, _lampEffect);
+ updateDrawPage2();
+ gui_drawScene(0);
+ enableSysTimer(2);
- ////////// TODO
+ if (_currentLevel != 11)
+ generateBrightnessPalette(_screen->_currentPalette, swampCol, _brightness, _lampEffect);
+ playSpellAnimation(0, 0, 0, 2, 0, 0, 0, tpal, swampCol, 40, 0);
+
+ _screen->fadePaletteStep(tpal, swampCol, _system->getMillis(), _tickLength);
+
+ if (breakWall)
+ breakIceWall(tpal, swampCol);
+
+ static const uint8 freezeTime[] = { 20, 28, 40, 60 };
+ if (_currentLevel == 11)
+ setCharacterUpdateEvent(charNum, 8, freezeTime[spellLevel], 1);
+
+ delete[] sc;
+ delete[] swampCol;
+ delete[] tpal;
_screen->setCurPage(cp);
}
@@ -2724,15 +2841,15 @@ void LoLEngine::playSpellAnimation(WSAMovie_v2 *mov, int firstFrame, int lastFra
int step = del > _tickLength ? _tickLength : del;
if (!pal1 || !pal2) {
- delay(step);
+ delay(step, false, true);
del -= step;
continue;
}
- if (!_screen->fadePalSpecial(pal1, pal2, _system->getMillis() - startTime, _tickLength * fadeDelay) && !mov)
+ if (!_screen->fadePaletteStep(pal1, pal2, _system->getMillis() - startTime, _tickLength * fadeDelay) && !mov)
return;
- delay(step);
+ delay(step, false, true);
del -= step;
} while (del > 0);
@@ -2793,6 +2910,16 @@ void LoLEngine::inflictMagicalDamage(int target, int attacker, int damage, int i
inflictDamage(target, damage, attacker, 2, index);
}
+void LoLEngine::inflictMagicalDamageForBlock(int block, int attacker, int damage, int index) {
+ uint16 o = _levelBlockProperties[block].assignedObjects;
+ while (o & 0x8000) {
+ inflictDamage(o, calcInflictableDamagePerItem(attacker, o, damage, index, 2), attacker, 2, index);
+ if ((_monsters[o & 0x7fff].flags & 0x20) && (_currentLevel != 22))
+ break;
+ o = _monsters[o & 0x7fff].nextAssignedObject;
+ }
+}
+
// fight
int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) {
@@ -3221,13 +3348,49 @@ void LoLEngine::stunCharacter(int charNum) {
_txt->printMessage(6, getLangString(0x4026), _characters[charNum].name);
}
-void LoLEngine::level11specialUnk() {
+void LoLEngine::restoreSwampPalette() {
+ _gameFlags[26] &= 0xfffb;
+ if (_currentLevel != 11)
+ return;
+
+ uint8 *s = _screen->getPalette(2);
+ uint8 *d = _screen->_currentPalette;
+ uint8 *d2 = _screen->getPalette(1);
+
+ for (int i = 1; i < 768; i++)
+ SWAP(s[i], d[i]);
+
+ generateBrightnessPalette(d, d2, _brightness, _lampEffect);
+ _screen->loadSpecialColors(s);
+ _screen->loadSpecialColors(d2);
+
+ playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s, d2, 40, 0);
}
void LoLEngine::launchMagicViper() {
}
-void LoLEngine::attackWall(int a, int b) {
+void LoLEngine::breakIceWall(uint8 *pal1, uint8 *pal2) {
+ _screen->hideMouse();
+ uint16 bl = calcNewBlockPosition(_currentBlock, _currentDirection);
+ _levelBlockProperties[bl].flags &= 0xef;
+ _screen->copyPage(0, 2);
+ gui_drawScene(2);
+ _screen->copyPage(2, 10);
+
+ WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
+ int numFrames = mov->open("shatter.wsa", 1, 0);
+ if (!mov->opened())
+ error("Shatter: Unable to load shatter.wsa");
+ snd_playSoundEffect(166, -1);
+ playSpellAnimation(mov, 0, numFrames, 1, 58, 0, 0, pal1, pal2, 20, true);
+ mov->close();
+ delete mov;
+
+ _screen->copyPage(10, 0);
+ updateDrawPage2();
+ gui_drawScene(0);
+ _screen->showMouse();
}
uint16 LoLEngine::getNearestMonsterFromCharacter(int charNum) {
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index 79c7ead338..fa1d58fac4 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -568,7 +568,7 @@ private:
uint16 _currentBlock;
bool _sceneUpdateRequired;
int16 _visibleBlockIndex[18];
- uint16 _gameFlags[16];
+ uint16 _gameFlags[40];
int16 _globalScriptVars[24];
// emc opcode
@@ -639,6 +639,7 @@ private:
int olol_createHandItem(EMCState *script);
int olol_playAttackSound(EMCState *script);
int olol_characterJoinsParty(EMCState *script);
+ int olol_giveItem(EMCState *script);
int olol_loadTimScript(EMCState *script);
int olol_runTimScript(EMCState *script);
int olol_releaseTimScript(EMCState *script);
@@ -710,6 +711,7 @@ private:
int olol_getNextActiveCharacter(EMCState *script);
int olol_paralyzePoisonCharacter(EMCState *script);
int olol_drawCharPortrait(EMCState *script);
+ int olol_placeInventoryItemInHand(EMCState *script);
int olol_castSpell(EMCState *script);
int olol_pitDrop(EMCState *script);
int olol_paletteFlash(EMCState *script);
@@ -967,7 +969,6 @@ private:
const uint8 *_scrollYBottom;
int _scrollYBottomSize;
- int _unkFlag;
int _nextScriptFunc;
uint8 _currentLevel;
int _sceneDefaultUpdate;
@@ -1270,6 +1271,8 @@ private:
int checkMagic(int charNum, int spellNum, int spellLevel);
int getSpellTargetBlock(int currentBlock, int direction, int maxDistance, uint16 &targetBlock);
void inflictMagicalDamage(int target, int attacker, int damage, int index, int hitType);
+ void inflictMagicalDamageForBlock(int block, int attacker, int damage, int index);
+
ActiveSpell _activeSpell;
int8 _availableSpells[7];
@@ -1278,7 +1281,6 @@ private:
int _spellPropertiesSize;
int _subMenuIndex;
- uint16 _freezeStateFlags;
uint8 *_healOverlay;
uint8 _swarmSpellStatus;
@@ -1311,12 +1313,12 @@ private:
int 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 restoreSwampPalette();
void distObj1Sub(int a, int b, int c, int d);
void launchMagicViper();
- void attackWall(int a, int b);
+ void breakIceWall(uint8 *pal1, uint8 *pal2);
uint16 getNearestMonsterFromCharacter(int charNum);
uint16 getNearestMonsterFromCharacterForBlock(uint16 block, int charNum);
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp
index f6302d39c1..7349cab9b5 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload.cpp
@@ -30,7 +30,7 @@
#include "kyra/kyra_v1.h"
-#define CURRENT_SAVE_VERSION 14
+#define CURRENT_SAVE_VERSION 15
#define GF_FLOPPY (1 << 0)
#define GF_TALKIE (1 << 1)
diff --git a/engines/kyra/saveload_lol.cpp b/engines/kyra/saveload_lol.cpp
index 11e18d0f31..4998795f73 100644
--- a/engines/kyra/saveload_lol.cpp
+++ b/engines/kyra/saveload_lol.cpp
@@ -119,10 +119,15 @@ Common::Error LoLEngine::loadGameState(int slot) {
_inventoryCurItem = in.readSint16BE();
_itemInHand = in.readSint16BE();
_lastMouseRegion = in.readSint16BE();
- for (int i = 0; i < 16; i++)
- _gameFlags[i] = in.readUint16BE();
- _freezeStateFlags = in.readUint16BE();
- _unkFlag = in.readUint16BE();
+ if (header.version == 14) {
+ for (int i = 0; i < 16; i++)
+ _gameFlags[i] = in.readUint16BE();
+ _gameFlags[26] = in.readUint16BE();
+ _gameFlags[36] = in.readUint16BE();
+ } else {
+ for (int i = 0; i < 40; i++)
+ _gameFlags[i] = in.readUint16BE();
+ }
for (int i = 0; i < 24; i++)
_globalScriptVars[i] = in.readUint16BE();
_brightness = in.readByte();
@@ -240,7 +245,7 @@ Common::Error LoLEngine::loadGameState(int slot) {
loadLevel(_currentLevel);
gui_drawPlayField();
timerSpecialCharacterUpdate(0);
- _unkFlag |= 0x800;
+ _gameFlags[36] |= 0x800;
while (!_screen->isMouseVisible())
_screen->showMouse();
@@ -318,10 +323,8 @@ Common::Error LoLEngine::saveGameState(int slot, const char *saveName, const Gra
out->writeSint16BE(_inventoryCurItem);
out->writeSint16BE(_itemInHand);
out->writeSint16BE(_lastMouseRegion);
- for (int i = 0; i < 16; i++)
+ for (int i = 0; i < 40; i++)
out->writeUint16BE(_gameFlags[i]);
- out->writeUint16BE(_freezeStateFlags);
- out->writeUint16BE(_unkFlag);
for (int i = 0; i < 24; i++)
out->writeUint16BE(_globalScriptVars[i]);
out->writeByte(_brightness);
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index dcdecb15e8..7682da754b 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -36,7 +36,7 @@
namespace Kyra {
void LoLEngine::loadLevel(int index) {
- _unkFlag |= 0x800;
+ _gameFlags[36] |= 0x800;
setMouseCursorToIcon(0x85);
_nextScriptFunc = 0;
@@ -395,10 +395,10 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight
if (_currentLevel == 11) {
uint8 *swampPal = _res->fileData("SWAMPICE.COL", 0);
memcpy(_screen->getPalette(2), swampPal, 384);
- memcpy(_screen->getPalette(2) + 0x180, _screen->_currentPalette, 384);
+ memcpy(_screen->getPalette(2) + 384, _screen->_currentPalette + 384, 384);
delete[] swampPal;
- if (_freezeStateFlags & 4) {
+ if (_gameFlags[26] & 4) {
uint8 *pal0 = _screen->_currentPalette;
uint8 *pal2 = _screen->getPalette(2);
for (int i = 1; i < 768; i++)
@@ -651,12 +651,12 @@ void LoLEngine::moveParty(uint16 direction, int unk1, int unk2, int buttonShape)
_sceneDefaultUpdate = 1;
calcCoordinates(_partyPosX, _partyPosY, _currentBlock, 0x80, 0x80);
- _unkFlag &= 0xfdff;
+ _gameFlags[36] &= 0xfdff;
runLevelScript(opos, 4);
runLevelScript(npos, 1);
- if (!(_unkFlag & 0x200)) {
+ if (!(_gameFlags[36] & 0x200)) {
initTextFading(2, 0);
if (_sceneDefaultUpdate) {
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index edc95fd36a..2f7a938374 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -815,20 +815,20 @@ bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedT
return res;
}
-bool Screen_LoL::fadePalSpecial(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime) {
+bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime) {
uint8 tpal[768];
- uint8 *p1 = _palettes[1];
+ uint8 *p1 = _palettes[0];
bool res = false;
for (int i = 0; i < 768; i++) {
uint8 out = 0;
if (elapsedTime < targetTime) {
- int d = (pal2[i] & 0x3f) - (pal1[i] & 0x3f);
+ int32 d = ((pal2[i] & 0x3f) - (pal1[i] & 0x3f));
if (d)
res = true;
- int val = ((((d << 8) / targetTime) * elapsedTime) >> 8) & 0xff;
- out = ((pal1[i] & 0x3f) + val) & 0xff;
+ int32 val = ((((d << 8) / (int32)targetTime) * (int32)elapsedTime) >> 8);
+ out = ((pal1[i] & 0x3f) + (int8)val);
} else {
out = p1[i] = (pal2[i] & 0x3f);
res = false;
diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h
index 6de38ff78d..7ef73bddcb 100644
--- a/engines/kyra/screen_lol.h
+++ b/engines/kyra/screen_lol.h
@@ -70,7 +70,7 @@ public:
void loadSpecialColors(uint8 *destPalette);
void copyColor(int dstColorIndex, int srcColorIndex);
bool fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime);
- bool fadePalSpecial(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime);
+ bool fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime);
void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors);
uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight);
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index b17d17685d..5b41b3da27 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -202,6 +202,9 @@ int LoLEngine::olol_delay(EMCState *script) {
int LoLEngine::olol_setGameFlag(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setGameFlag(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+
+ assert((stackPos(0) >> 4) < 40);
+
if (stackPos(1))
_gameFlags[stackPos(0) >> 4] |= (1 << (stackPos(0) & 0x0f));
else
@@ -215,6 +218,8 @@ int LoLEngine::olol_testGameFlag(EMCState *script) {
if (stackPos(0) < 0)
return 0;
+ assert((stackPos(0) >> 4) < 40);
+
if (_gameFlags[stackPos(0) >> 4] & (1 << (stackPos(0) & 0x0f)))
return 1;
@@ -1104,6 +1109,15 @@ int LoLEngine::olol_characterJoinsParty(EMCState *script) {
return 1;
}
+int LoLEngine::olol_giveItem(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_giveItem(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ int item = makeItem(stackPos(0), stackPos(1), stackPos(2));
+ if (addItemToInventory(item))
+ return 1;
+
+ deleteItem(item);
+ return 0;
+}
int LoLEngine::olol_loadTimScript(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadTimScript(%p) (%d, %s)", (const void *)script, stackPos(0), stackPosString(1));
@@ -1854,6 +1868,31 @@ int LoLEngine::olol_drawCharPortrait(EMCState *script) {
return 1;
}
+int LoLEngine::olol_placeInventoryItemInHand(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_placeInventoryItemInHand(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ int itemType = stackPos(0);
+ int i = 0;
+ for (; i < 48; i++) {
+ if (!_inventory[i])
+ continue;
+ if (_itemsInPlay[_inventory[i]].itemPropertyIndex == itemType)
+ break;
+ }
+
+ if (i == 48)
+ return -1;
+
+ _inventoryCurItem = i;
+ int r = _itemInHand;
+ setHandItem(_inventory[i]);
+ _inventory[i] = r;
+
+ if (stackPos(1))
+ gui_drawInventory();
+
+ return r;
+}
+
int LoLEngine::olol_castSpell(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_castSpell(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
return castSpell(stackPos(0), stackPos(1), stackPos(2));
@@ -2328,7 +2367,7 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_characterJoinsParty);
// 0x4C
- OpcodeUnImpl();
+ Opcode(olol_giveItem);
OpcodeUnImpl();
Opcode(olol_loadTimScript);
Opcode(olol_runTimScript);
@@ -2472,7 +2511,7 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
// 0xAC
- OpcodeUnImpl();
+ Opcode(olol_placeInventoryItemInHand);
Opcode(olol_castSpell);
Opcode(olol_pitDrop);
OpcodeUnImpl();
diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp
index 7b66907733..35350103fc 100644
--- a/engines/kyra/sprites_lol.cpp
+++ b/engines/kyra/sprites_lol.cpp
@@ -1232,7 +1232,7 @@ bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) {
s = monster->properties->numDistWeapons ? _rnd.getRandomNumberRng(1, monster->properties->numDistWeapons) : 0;
} else {
s = monster->curDistWeapon++;
- if (monster->curDistWeapon == monster->properties->numDistWeapons)
+ if (monster->curDistWeapon >= monster->properties->numDistWeapons)
monster->curDistWeapon = 0;
}
diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp
index b17fdc7d46..eb0ecb5537 100644
--- a/engines/kyra/timer_lol.cpp
+++ b/engines/kyra/timer_lol.cpp
@@ -172,7 +172,7 @@ void LoLEngine::timerSpecialCharacterUpdate(int timerNum) {
break;
case 7:
- level11specialUnk();
+ restoreSwampPalette();
break;
default: