aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/gui_lol.cpp12
-rw-r--r--engines/kyra/items_lol.cpp18
-rw-r--r--engines/kyra/lol.cpp126
-rw-r--r--engines/kyra/lol.h60
-rw-r--r--engines/kyra/scene_lol.cpp50
-rw-r--r--engines/kyra/script_lol.cpp44
-rw-r--r--engines/kyra/sprites_lol.cpp341
-rw-r--r--engines/kyra/staticres.cpp4
8 files changed, 542 insertions, 113 deletions
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp
index e4ba477f2a..de531a8c66 100644
--- a/engines/kyra/gui_lol.cpp
+++ b/engines/kyra/gui_lol.cpp
@@ -943,7 +943,7 @@ void LoLEngine::gui_initButton(int index, int x, int y, int val) {
}
int LoLEngine::clickedUpArrow(Button *button) {
- if (button->data2Val2 && !(_unkGameFlag & 4))
+ if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
moveParty(_currentDirection, ((button->flags2 & 0x1080) == 0x1080) ? 1 : 0, 0, 80);
@@ -952,7 +952,7 @@ int LoLEngine::clickedUpArrow(Button *button) {
}
int LoLEngine::clickedDownArrow(Button *button) {
- if (button->data2Val2 && !(_unkGameFlag & 4))
+ if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
moveParty(_currentDirection ^ 2, 0, 1, 83);
@@ -961,7 +961,7 @@ int LoLEngine::clickedDownArrow(Button *button) {
}
int LoLEngine::clickedLeftArrow(Button *button) {
- if (button->data2Val2 && !(_unkGameFlag & 4))
+ if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
moveParty((_currentDirection - 1) & 3, ((button->flags2 & 0x1080) == 0x1080) ? 1 : 0, 2, 82);
@@ -970,7 +970,7 @@ int LoLEngine::clickedLeftArrow(Button *button) {
}
int LoLEngine::clickedRightArrow(Button *button) {
- if (button->data2Val2 && !(_unkGameFlag & 4))
+ if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
moveParty((_currentDirection + 1) & 3, ((button->flags2 & 0x1080) == 0x1080) ? 1 : 0, 3, 84);
@@ -979,7 +979,7 @@ int LoLEngine::clickedRightArrow(Button *button) {
}
int LoLEngine::clickedTurnLeftArrow(Button *button) {
- if (button->data2Val2 && !(_unkGameFlag & 4))
+ if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
gui_toggleButtonDisplayMode(79, 1);
@@ -1001,7 +1001,7 @@ int LoLEngine::clickedTurnLeftArrow(Button *button) {
}
int LoLEngine::clickedTurnRightArrow(Button *button) {
- if (button->data2Val2 && !(_unkGameFlag & 4))
+ if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
gui_toggleButtonDisplayMode(81, 1);
diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp
index 06667023ad..1977ba9a60 100644
--- a/engines/kyra/items_lol.cpp
+++ b/engines/kyra/items_lol.cpp
@@ -413,7 +413,7 @@ void LoLEngine::updateObjectFlightPosition(FlyingObject *t) {
}
void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objectOnNextBlock) {
- int r = 0;
+ uint16 r = 0;
if (objectOnNextBlock == 1) {
runLevelScriptCustom(calcNewBlockPosition(_itemsInPlay[t->item].blockPropertyIndex, t->direction >> 1), 0x8000, -1, t->item, 0, 0);
@@ -432,7 +432,7 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec
return;
} else {
- r = flyingObjectHitMonsters(x, y);
+ r = getClosestMonster(x, y);
}
} else if (objectOnNextBlock == 4) {
@@ -445,25 +445,13 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec
return;
} else {
- r = flyingObjectHitParty(x, y);
+ r = getClosestPartyMember(x, y);
}
}
runItemScript(t->charNum, t->item, 0x8000, r, 0);
}
-uint16 LoLEngine::flyingObjectHitMonsters(int x, int y) {
- ////////////
- // TODO
- return 0;
-}
-
-uint16 LoLEngine::flyingObjectHitParty(int x, int y) {
- ////////////
- // TODO
- return 0;
-}
-
void LoLEngine::updateFlyingObjects(FlyingObject *t) {
int x = 0;
int y = 0;
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 09e3ca14c9..39428f29e1 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -149,7 +149,6 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_tempBuffer5120 = 0;
_flyingItems = 0;
_monsters = 0;
- _unkGameFlag = 0;
_lastMouseRegion = 0;
_monsterLastWalkDirection = _monsterCountUnk = _monsterShiftAlt = 0;
_monsterCurBlock = 0;
@@ -206,6 +205,10 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_activeButtons = 0;
_preserveEvents = false;
_buttonList1 = _buttonList2 = _buttonList3 = _buttonList4 = _buttonList5 = _buttonList6 = _buttonList7 = _buttonList8 = 0;
+
+ _monsterDifficulty = 1;
+ _smoothScrollingEnabled = true;
+ _floatingCursorsEnabled = false;
}
LoLEngine::~LoLEngine() {
@@ -730,7 +733,7 @@ void LoLEngine::startupNew() {
_compassDirection = _compassDirectionIndex = -1;
_lastMouseRegion = -1;
- _unkGameFlag |= 0x1B;
+
/*
_unk5 = 1;
_unk6 = 1;
@@ -1080,7 +1083,7 @@ int LoLEngine::calculateProtection(int index) {
if (index & 0x8000) {
// Monster
index &= 0x7fff;
- c = (_monsters[index].properties->itemProtection * _monsters[index].properties->protection) >> 8;
+ c = (_monsters[index].properties->itemProtection * _monsters[index].properties->fightingStats[2]) >> 8;
} else {
// Character
c = _characters[index].itemsProtection + _characters[index].protection;
@@ -1521,7 +1524,7 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) {
}
void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
- if (!(_unkGameFlag & 1))
+ if (!_sound->sfxEnabled())
return;
if (_environmentSfx)
@@ -1560,7 +1563,7 @@ void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
}
void LoLEngine::snd_loadSoundFile(int track) {
- if (_unkGameFlag & 2) {
+ if (_sound->musicEnabled()) {
char filename[13];
int t = (track - 250) * 3;
@@ -1585,7 +1588,7 @@ int LoLEngine::snd_playTrack(int track) {
int res = _lastMusicTrack;
_lastMusicTrack = track;
- if (_unkGameFlag & 2) {
+ if (_sound->musicEnabled()) {
snd_loadSoundFile(track);
int t = (track - 250) * 3;
_sound->playTrack(_musicTrackMap[t + 2]);
@@ -1595,7 +1598,7 @@ int LoLEngine::snd_playTrack(int track) {
}
int LoLEngine::snd_stopMusic() {
- if (_unkGameFlag & 2) {
+ if (_sound->musicEnabled()) {
if (_sound->isPlaying()) {
_sound->beginFadeOut();
_system->delayMillis(3 * _tickLength);
@@ -1716,7 +1719,7 @@ void LoLEngine::giveItemToMonster(MonsterInPlay *monster, uint16 item) {
}
const uint16 *LoLEngine::getCharacterOrMonsterStats(int id) {
- return (id & 0x8000) ? (const uint16*)_monsters[id & 0x7fff].properties->pos : _characters[id].defaultModifiers;
+ return (id & 0x8000) ? (const uint16*)_monsters[id & 0x7fff].properties->fightingStats : _characters[id].defaultModifiers;
}
void LoLEngine::delay(uint32 millis, bool cUpdate, bool isMainLoop) {
@@ -1771,6 +1774,113 @@ bool LoLEngine::notEnoughMagic(int charNum, int spellNum, int spellLevel) {
return false;
}
+int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) {
+ if (target == -1)
+ return 0;
+ if (attacker == -1)
+ return 1;
+
+ if (target & 0x8000) {
+ if (_monsters[target & 0x7fff].mode >= 13)
+ return 0;
+ }
+
+ uint16 hitChanceModifier = 0;
+ uint16 evadeChanceModifier = 0;
+ int sk = 0;
+
+ if (attacker & 0x8000) {
+ hitChanceModifier = _monsters[target & 0x7fff].properties->fightingStats[0];
+ sk = 100 - _monsters[target & 0x7fff].properties->skillLevel;
+ } else {
+ hitChanceModifier = _characters[attacker].defaultModifiers[0];
+ uint8 m = _characters[attacker].skillModifiers[skill];
+ if (skill == 1)
+ m *= 3;
+ sk = 100 - (_characters[attacker].skillLevels[skill] + m);
+ }
+
+ if (target & 0x8000) {
+ evadeChanceModifier = _monsters[target & 0x7fff].properties->fightingStats[3];
+ _monsters[target & 0x7fff].flags |= 0x10;
+ } else {
+ evadeChanceModifier = _characters[target].defaultModifiers[3];
+ }
+
+ int r = _rnd.getRandomNumberRng(1, 100);
+ if (r >= sk)
+ return 2;
+
+ uint16 v = ((_monsterModifiers[9 + _monsterDifficulty] * evadeChanceModifier) & 0xffffff00) / hitChanceModifier;
+
+ if (r < v)
+ return 0;
+
+ return 1;
+}
+
+int LoLEngine::calcInflictableDamage(int16 attacker, int16 target, int hitType) {
+ const uint16 *s = getCharacterOrMonsterStats(attacker);
+
+ int res = 0;
+ for (int i = 0; i < 8; i++)
+ res += calcInflictableDamagePerStat(attacker, target, s[2 + i], i, hitType);
+
+ return res;
+}
+
+void LoLEngine::battleHit_sub2(int16 target, int damageInflicted, int16 attacker, uint32 b) {
+
+}
+
+void LoLEngine::battleHit_sub3(MonsterInPlay *monster, int16 target, int16 damageInflicted) {
+
+}
+
+int LoLEngine::calcInflictableDamagePerStat(int16 attacker, int16 target, uint16 stat2m, int index, int hitType) {
+ return 1;
+}
+
+uint16 LoLEngine::getClosestMonster(int x, int y) {
+ uint16 id = 0xffff;
+ int minDist = 0x7fff;
+
+ for (int i = 0; i < 30; i++) {
+ if (_monsters[i].mode > 13)
+ continue;
+
+ int d = ABS(x - _monsters[i].x) + ABS(y - _monsters[i].y);
+ if (d < minDist) {
+ minDist = d;
+ id = 0x8000 | i;
+ }
+ }
+
+ return id;
+}
+
+uint16 LoLEngine::getClosestPartyMember(int x, int y) {
+ uint16 id = 0xffff;
+ int minDist = 0x7fff;
+
+ for (int i = 0; i < 4; i++) {
+ if (!(_characters[i].flags & 1) || _characters[i].hitPointsCur <= 0)
+ continue;
+
+ int16 charX = 0;
+ int16 charY = 0;
+ calcCoordinatesForSingleCharacter(i, charX, charY);
+
+ int d = ABS(x - charX) + ABS(y - charY);
+ if (d < minDist) {
+ minDist = d;
+ id = i;
+ }
+ }
+
+ return id;
+}
+
} // end of namespace Kyra
#endif // ENABLE_LOL
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index acd385dfb8..f0b1f00b16 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -62,9 +62,9 @@ struct LoLCharacter {
uint16 field_34;
uint8 field_36;
uint16 itemsProtection;
- uint16 hitPointsCur;
+ int16 hitPointsCur;
uint16 hitPointsMax;
- uint16 magicPointsCur;
+ int16 magicPointsCur;
uint16 magicPointsMax;
uint8 field_41;
uint16 damageSuffered;
@@ -100,15 +100,13 @@ struct LevelBlockProperty {
struct MonsterProperty {
uint8 shapeIndex;
uint8 maxWidth;
- uint16 field2[2];
- uint16 protection;
- uint16 unk[6];
- uint16 *pos;
+ uint16 fightingStats[10];
uint16 unk2[8];
uint16 unk3[8];
uint16 itemProtection;
uint16 might;
- uint8 waitTicks;
+ uint8 speedTotalWaitTicks;
+ uint8 skillLevel;
uint16 flags;
uint16 unk5;
uint16 unk6[5];
@@ -129,10 +127,10 @@ struct MonsterInPlay {
uint8 destDirection;
uint8 anon8;
uint8 anonh;
- uint8 anon9;
+ uint8 currentSubFrame;
uint8 mode;
- uint8 field_15;
+ int8 fightCurTick;
uint8 id;
uint8 direction;
uint8 facing;
@@ -140,7 +138,7 @@ struct MonsterInPlay {
uint8 field_1B;
uint8 field_1C;
int16 might;
- uint8 tick;
+ uint8 speedTick;
uint8 type;
MonsterProperty *properties;
uint8 field_25;
@@ -163,7 +161,7 @@ struct ItemInPlay {
uint8 destDirection;
uint8 anon8;
uint8 anonh;
- uint8 anon9;
+ uint8 currentSubFrame;
};
struct ItemProperty {
@@ -266,6 +264,11 @@ private:
void startup();
void startupNew();
+ // options
+ int _monsterDifficulty;
+ bool _smoothScrollingEnabled;
+ bool _floatingCursorsEnabled;
+
// main loop
void runLoop();
void update();
@@ -569,7 +572,9 @@ private:
int olol_initMonster(EMCState *script);
int olol_fadeClearSceneWindow(EMCState *script);
int olol_fadeSequencePalette(EMCState *script);
+ int olol_dummy0(EMCState *script);
int olol_loadMonsterProperties(EMCState *script);
+ int olol_battleHitSkillTest(EMCState *script);
int olol_moveMonster(EMCState *script);
int olol_dialogueBox(EMCState *script);
int olol_giveTakeMoney(EMCState *script);
@@ -597,7 +602,7 @@ private:
int olol_setPaletteBrightness(EMCState *script);
int olol_printMessage(EMCState *script);
int olol_playDialogueTalkText(EMCState *script);
- int olol_checkForMonsterMode1(EMCState *script);
+ int olol_checkMonsterTypeHostility(EMCState *script);
int olol_setNextFunc(EMCState *script);
int olol_setDoorState(EMCState *script);
int olol_processButtonClick(EMCState *script);
@@ -804,7 +809,9 @@ private:
uint16 calcNewBlockPosition(uint16 curBlock, uint16 direction);
uint16 calcBlockIndex(uint16 x, uint16 y);
- void calcCoordinates(uint16 & x, uint16 & y, int block, uint16 xOffs, uint16 yOffs);
+ void calcCoordinates(uint16 &x, uint16 &y, int block, uint16 xOffs, uint16 yOffs);
+ void calcCoordinatesForSingleCharacter(int charNum, int16 &x, int16 &y);
+ void calcCoordinatesAddDirectionOffset(int16 &x, int16 &y, int direction);
int clickedWallShape(uint16 block, uint16 direction);
int clicked2(uint16 block, uint16 direction);
@@ -906,8 +913,7 @@ private:
int _lastMouseRegion;
int _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2, _seqTrigger;
- uint8 _unkGameFlag;
-
+
uint8 *_tempBuffer5120;
const char *const * _levelDatList;
@@ -979,8 +985,6 @@ private:
void processObjectFlight(FlyingObject *t, int x, int y);
void updateObjectFlightPosition(FlyingObject *t);
void objectFlightProcessHits(FlyingObject *t, int x, int y, int objectOnNextBlock);
- uint16 flyingObjectHitMonsters(int x, int y);
- uint16 flyingObjectHitParty(int x, int y);
void updateFlyingObjects(FlyingObject *t);
void assignItemToBlock(uint16 *assignedBlockObjects, int id);
@@ -1022,11 +1026,12 @@ private:
void loadMonsterShapes(const char *file, int monsterIndex, int b);
void releaseMonsterShapes(int monsterIndex);
int disableMonstersForBlock(int block);
- void setMonsterMode(MonsterInPlay *monster, int a);
+ void setMonsterMode(MonsterInPlay *monster, int mode);
+ bool updateMonsterAdjustBlocks(MonsterInPlay *monster);
void placeMonster(MonsterInPlay *monster, uint16 x, uint16 y);
int calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void setMonsterDirection(MonsterInPlay *monster, int dir);
- void cmzS3(MonsterInPlay *monster);
+ void monsterDropItems(MonsterInPlay *monster);
void removeAssignedObjectFromBlock(LevelBlockProperty *l, int id);
void removeDrawObjectFromBlock(LevelBlockProperty *l, int id);
void assignMonsterToBlock(uint16 *assignedBlockObjects, int id);
@@ -1042,7 +1047,7 @@ private:
void reassignDrawObjects(uint16 direction, uint16 itemIndex, LevelBlockProperty *l, bool flag);
void redrawSceneItem();
int calcItemMonsterPosition(ItemInPlay *i, uint16 direction);
- void recalcSpritePosition(uint16 partyX, uint16 partyY, int &itemX, int &itemY, uint16 direction);
+ void calcSpriteRelPosition(uint16 x1, uint16 y1, int &x2, int &y2, uint16 direction);
void drawDoor(uint8 *shape, uint8 *table, int index, int unk2, int w, int h, int flags);
void drawDoorOrMonsterShape(uint8 *shape, uint8 *table, int x, int y, int flags, const uint8 *ovl);
uint8 *drawItemOrMonster(uint8 *shape, uint8 *ovl, int x, int y, int fineX, int fineY, int flags, int tblValue, bool flip);
@@ -1051,11 +1056,16 @@ private:
void updateMonster(MonsterInPlay *monster);
void moveMonster(MonsterInPlay *monster);
void walkMonster(MonsterInPlay *monster);
+ bool chasePartyWithDistanceAttacks(MonsterInPlay *monster);
+ 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 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);
+ void moveStrayingMonster(MonsterInPlay *monster);
+ void mode13sub(MonsterInPlay *monster);
MonsterInPlay *_monsters;
MonsterProperty *_monsterProperties;
@@ -1093,6 +1103,16 @@ private:
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);
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index 705fc042a1..ce3393fc62 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -273,7 +273,7 @@ void LoLEngine::loadLevelCmzFile(int index) {
}
}
- loadCMZ_Sub(tmpLvlVal, (_unkGameFlag & 0x30) >> 4);
+ loadCMZ_Sub(tmpLvlVal, _monsterDifficulty);
delete[] cmzdata;
}
@@ -654,11 +654,43 @@ uint16 LoLEngine::calcBlockIndex(uint16 x, uint16 y) {
return ((y & 0xff00) >> 3) | (x >> 8);
}
-void LoLEngine::calcCoordinates(uint16 & x, uint16 & y, int block, uint16 xOffs, uint16 yOffs) {
+void LoLEngine::calcCoordinates(uint16 &x, uint16 &y, int block, uint16 xOffs, uint16 yOffs) {
x = (block & 0x1f) << 8 | xOffs;
y = ((block & 0xffe0) << 3) | yOffs;
}
+void LoLEngine::calcCoordinatesForSingleCharacter(int charNum, int16 &x, int16 &y) {
+ static const uint8 xOffsets[] = { 0x80, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x40, 0x80, 0xC0 };
+ int c = countActiveCharacters();
+ if (!c)
+ return;
+
+ c = (c - 1) * 3 + charNum;
+
+ x = xOffsets[c];
+ y = 0x80;
+
+ calcCoordinatesAddDirectionOffset(x, y, _currentDirection);
+
+ x |= (_partyPosX & 0xff00);
+ y |= (_partyPosY & 0xff00);
+}
+
+void LoLEngine::calcCoordinatesAddDirectionOffset(int16 &x, int16 &y, int direction) {
+ if (!direction)
+ return;
+
+ if (direction & 1)
+ SWAP(x, y);
+
+ if (direction == 1)
+ y = (y - 256) * -1;
+
+ if (direction == 3) {
+ x = (x - 256) * -1;
+ }
+}
+
bool LoLEngine::checkBlockPassability(uint16 block, uint16 direction) {
if (testWallFlag(block, direction, 1))
return false;
@@ -825,7 +857,7 @@ void LoLEngine::openCloseDoor(uint16 block, int openClose) {
}
void LoLEngine::movePartySmoothScrollBlocked(int speed) {
- if (!(_unkGameFlag & 8) || ((_unkGameFlag & 8) && _hideInventory))
+ if (!_smoothScrollingEnabled || (_smoothScrollingEnabled && _hideInventory))
return;
_screen->backupSceneWindow(_sceneDrawPage2 == 2 ? 2 : 6, 6);
@@ -863,7 +895,7 @@ void LoLEngine::movePartySmoothScrollBlocked(int speed) {
}
void LoLEngine::movePartySmoothScrollUp(int speed) {
- if (!(_unkGameFlag & 8) || ((_unkGameFlag & 8) && _hideInventory))
+ if (!_smoothScrollingEnabled || (_smoothScrollingEnabled && _hideInventory))
return;
int d = 0;
@@ -908,7 +940,7 @@ void LoLEngine::movePartySmoothScrollUp(int speed) {
}
void LoLEngine::movePartySmoothScrollDown(int speed) {
- if (!(_unkGameFlag & 8))
+ if (!_smoothScrollingEnabled)
return;
//int d = smoothScrollDrawSpecialShape(2);
@@ -943,7 +975,7 @@ void LoLEngine::movePartySmoothScrollDown(int speed) {
}
void LoLEngine::movePartySmoothScrollLeft(int speed) {
- if (!(_unkGameFlag & 8))
+ if (!_smoothScrollingEnabled)
return;
speed <<= 1;
@@ -969,7 +1001,7 @@ void LoLEngine::movePartySmoothScrollLeft(int speed) {
}
void LoLEngine::movePartySmoothScrollRight(int speed) {
- if (!(_unkGameFlag & 8))
+ if (!_smoothScrollingEnabled)
return;
speed <<= 1;
@@ -1008,7 +1040,7 @@ void LoLEngine::movePartySmoothScrollRight(int speed) {
}
void LoLEngine::movePartySmoothScrollTurnLeft(int speed) {
- if (!(_unkGameFlag & 8))
+ if (!_smoothScrollingEnabled)
return;
speed <<= 1;
@@ -1052,7 +1084,7 @@ void LoLEngine::movePartySmoothScrollTurnLeft(int speed) {
}
void LoLEngine::movePartySmoothScrollTurnRight(int speed) {
- if (!(_unkGameFlag & 8))
+ if (!_smoothScrollingEnabled)
return;
speed <<= 1;
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index c7dd99de29..dce08e6462 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -684,7 +684,7 @@ int LoLEngine::olol_initMonster(EMCState *script) {
if (l->might || l->mode == 13)
continue;
- memset(l, 0, sizeof(MonsterInPlay));
+ memset(l, 0, sizeof(MonsterInPlay));
l->id = i;
l->x = x;
l->y = y;
@@ -692,7 +692,7 @@ 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[((_unkGameFlag & 0x30) >> 4)]) >> 8;
+ l->might = (l->properties->might * _monsterModifiers[_monsterDifficulty]) >> 8;
if (_currentLevel == 12 && l->type == 2)
l->might = (l->might * (_rnd.getRandomNumberRng(1, 128) + 192)) >> 8;
@@ -735,6 +735,10 @@ int LoLEngine::olol_fadeSequencePalette(EMCState *script) {
return 1;
}
+int LoLEngine::olol_dummy0(EMCState *script) {
+ return 0;
+}
+
int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadMonsterProperties(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
(const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5),
@@ -757,25 +761,25 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
l->maxWidth = shpWidthMax;
- l->field2[0] = (stackPos(2) << 8) / 100;
- l->field2[1] = 256;
- l->protection = (stackPos(3) << 8) / 100;
- l->unk[0] = stackPos(4);
- l->unk[1] = (stackPos(5) << 8) / 100;
- l->unk[2] = (stackPos(6) << 8) / 100;
- l->unk[3] = (stackPos(7) << 8) / 100;
- l->unk[4] = (stackPos(8) << 8) / 100;
- l->unk[5] = 0;
+ l->fightingStats[0] = (stackPos(2) << 8) / 100; // hit chance
+ l->fightingStats[1] = 256; //
+ l->fightingStats[2] = (stackPos(3) << 8) / 100; // protection
+ l->fightingStats[3] = stackPos(4); // evade chance
+ l->fightingStats[4] = (stackPos(5) << 8) / 100; // speed
+ l->fightingStats[5] = (stackPos(6) << 8) / 100; //
+ 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->pos = &l->field2[0];
l->itemProtection = stackPos(25);
l->might = stackPos(26);
- l->waitTicks = 1;
+ l->speedTotalWaitTicks = 1;
l->flags = stackPos(27);
l->unk5 = stackPos(28);
// FIXME???
@@ -796,6 +800,11 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
return 1;
}
+int LoLEngine::olol_battleHitSkillTest(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_battleHitSkillTest(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ return battleHitSkillTest(stackPos(0), stackPos(1), stackPos(2));
+}
+
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)];
@@ -1022,7 +1031,8 @@ int LoLEngine::olol_playDialogueTalkText(EMCState *script) {
return 1;
}
-int LoLEngine::olol_checkForMonsterMode1(EMCState *script) {
+int LoLEngine::olol_checkMonsterTypeHostility(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_checkMonsterTypeHostility(%p) (%d)", (const void *)script, stackPos(0));
for (int i = 0; i < 30; i++) {
if (stackPos(0) != _monsters[i].type && stackPos(0) != -1)
continue;
@@ -1445,11 +1455,11 @@ void LoLEngine::setupOpcodeTable() {
// 0x3C
OpcodeUnImpl();
OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_dummy0);
Opcode(olol_loadMonsterProperties);
// 0x40
- OpcodeUnImpl();
+ Opcode(olol_battleHitSkillTest);
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
@@ -1536,7 +1546,7 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_playDialogueTalkText);
- Opcode(olol_checkForMonsterMode1);
+ Opcode(olol_checkMonsterTypeHostility);
// 0x7C
Opcode(olol_setNextFunc);
diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp
index 7253d6ba32..76e14d44d4 100644
--- a/engines/kyra/sprites_lol.cpp
+++ b/engines/kyra/sprites_lol.cpp
@@ -162,9 +162,10 @@ int LoLEngine::disableMonstersForBlock(int block) {
void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) {
if (monster->mode == 13 && mode != 14)
return;
+
if (mode == 7) {
monster->destX = _partyPosX;
- monster->destY = _partyPosX;
+ monster->destY = _partyPosY;
}
if (monster->mode == 1 && mode == 7) {
@@ -172,19 +173,19 @@ void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) {
if (monster->mode != 1)
continue;
monster->mode = mode;
- monster->field_15 = 0;
+ monster->fightCurTick = 0;
monster->destX = _partyPosX;
monster->destY = _partyPosY;
setMonsterDirection(monster, calcMonsterDirection(monster->x, monster->y, monster->destX, monster->destY));
}
} else {
monster->mode = mode;
- monster->field_15 = 0;
+ monster->fightCurTick = 0;
if (mode == 14)
monster->might = 0;
if (mode == 13 && (monster->flags & 0x20)) {
monster->mode = 0;
- cmzS3(monster);
+ monsterDropItems(monster);
if (_currentLevel != 29)
setMonsterMode(monster, 14);
runLevelScriptCustom(0x404, -1, monster->id, monster->id, 0, 0);
@@ -195,6 +196,47 @@ void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) {
}
}
+bool LoLEngine::updateMonsterAdjustBlocks(MonsterInPlay *monster) {
+ static const uint8 dims[] = { 0, 13, 9, 3 };
+ if (monster->properties->flags & 8)
+ return true;
+
+ uint16 x1 = (monster->x & 0xff00) | 0x80;
+ uint16 y1 = (monster->y & 0xff00) | 0x80;
+ int x2 = _partyPosX;
+ int y2 = _partyPosY;
+
+ uint16 dir = 0;
+ if (monster->properties->flags & 1) {
+ dir = monster->direction >> 1;
+ } else {
+ dir = calcMonsterDirection(x1, y1, x2, y2);
+ if ((monster->properties->flags & 2) && (dir == (monster->direction ^ 4)))
+ return false;
+ dir >>= 1;
+ }
+
+ calcSpriteRelPosition(x1, y1, x2, y2, dir);
+ x2 >>= 8;
+ y2 >>= 8;
+
+ if (y2 < 0 || y2 > 3)
+ return false;
+
+ int t = (x2 < 0) ? -x2 : x2;
+ if (t > y2)
+ return false;
+
+ for (int i = 0; i < 18; i++)
+ _curBlockCaps[i] = &_levelBlockProperties[(monster->blockPropertyIndex + _dscBlockIndex[dir + i]) & 0x3ff];
+
+ int16 fx1 = 0;
+ int16 fx2 = 0;
+ setLevelShapesDim(x2 + dims[y2], fx1, fx2, 13);
+
+ return (fx1 >= fx2) ? false : true;
+}
+
void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
bool cont = true;
int t = monster->blockPropertyIndex;
@@ -211,7 +253,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
if (monster->x != x || monster->y != y) {
monster->x = x;
monster->y = y;
- monster->anon9 = (++monster->anon9) & 3;
+ monster->currentSubFrame = (++monster->currentSubFrame) & 3;
}
if (monster->blockPropertyIndex == 0)
@@ -224,7 +266,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
if (monster->properties->sounds[0] == 0 || cont == false)
return;
- if ((!(monster->properties->flags & 0x100) || ((monster->anon9 & 1) == 0)) && monster->blockPropertyIndex == t)
+ if ((!(monster->properties->flags & 0x100) || ((monster->currentSubFrame & 1) == 0)) && monster->blockPropertyIndex == t)
return;
if (monster->blockPropertyIndex != t)
@@ -238,6 +280,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
int LoLEngine::calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
int16 r = 0;
+
int16 t1 = y1 - y2;
if (t1 < 0) {
r++;
@@ -247,19 +290,15 @@ int LoLEngine::calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2)
r <<= 1;
int16 t2 = x2 - x1;
-
if (t2 < 0) {
r++;
t2 = -t2;
}
- uint8 f = 1;
+ uint8 f = (t1 > t2) ? 1 : 0;
- if (t2 >= t1) {
- if (t2 > t1)
- f = 0;
+ if (t2 >= t1)
SWAP(t1, t2);
- }
r = (r << 1) | f;
@@ -281,8 +320,13 @@ void LoLEngine::setMonsterDirection(MonsterInPlay *monster, int dir) {
checkSceneUpdateNeed(monster->blockPropertyIndex);
}
-void LoLEngine::cmzS3(MonsterInPlay *l) {
- // TODO
+void LoLEngine::monsterDropItems(MonsterInPlay *monster) {
+ uint16 a = monster->assignedItems;
+ while (a) {
+ uint16 b = a;
+ a = _itemsInPlay[a].nextAssignedObject;
+ setItemPosition(b, monster->x, monster->y, 0, 1);
+ }
}
void LoLEngine::removeAssignedObjectFromBlock(LevelBlockProperty *l, int id) {
@@ -459,7 +503,7 @@ int LoLEngine::calcMonsterSkillLevel(int id, int a) {
int r = (a << 8) / c[4];
if (!(id & 0x8000))
- r = (r * _monsterModifiers[3 + ((_unkGameFlag & 0x30) << 4)]) >> 8;
+ r = (r * _monsterModifiers[3 + _monsterDifficulty]) >> 8;
id &= 0x7fff;
@@ -519,7 +563,6 @@ void LoLEngine::drawBlockObjects(int blockArrayIndex) {
if ((_itemProperties[i->itemPropertyIndex].flags & 0x1000) && !(i->shpCurFrame_flg & 0xC000)) {
int shpIndex = _itemProperties[i->itemPropertyIndex].flags & 0x800 ? 7 : _itemProperties[i->itemPropertyIndex].shpIndex;
- shpIndex=12;
int ii = 0;
for (; ii < 8; ii++) {
if (!_flyingItems[ii].enable)
@@ -612,7 +655,7 @@ void LoLEngine::drawMonster(uint16 id) {
int dW = _screen->getShapeScaledWidth(shp, _dmScaleW) >> 1;
int dH = _screen->getShapeScaledHeight(shp, _dmScaleH) >> 1;
- int a = (m->mode == 13) ? (m->field_15 << 1) : (m->properties->might / (m->field_1B & 0x7fff));
+ int a = (m->mode == 13) ? (m->fightCurTick << 1) : (m->properties->might / (m->field_1B & 0x7fff));
shp = _gameShapes[6];
@@ -654,7 +697,7 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) {
switch (_monsterUnk[m->properties->shapeIndex]) {
case 0:
if (dirFlags) {
- return (*m->properties->pos & 0xff) == 13 ? -1 : (dirFlags + m->anon9);
+ return (m->properties->fightingStats[0] & 0xff) == 13 ? -1 : (dirFlags + m->currentSubFrame);
} else {
if (m->field_1B)
return 12;
@@ -663,13 +706,13 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) {
case 0:
return m->field_1B ? 12 : ((m->properties->flags & 4) ? 13 : 0);
case 3:
- return (m->field_15 + 13);
+ return (m->fightCurTick + 13);
case 6:
return 14;
case 8:
return -1;
default:
- return m->field_1B ? 12 : m->anon9;
+ return m->field_1B ? 12 : m->currentSubFrame;
}
}
break;
@@ -738,8 +781,7 @@ void LoLEngine::redrawSceneItem() {
int t = (i << 7) + 1;
while (s) {
if (s & 0x8000) {
- s &= 0x7fff;
- s = _monsters[i].nextDrawObject;
+ s = _monsters[s & 0x7fff].nextDrawObject;
} else {
ItemInPlay *item = &_itemsInPlay[s];
@@ -769,7 +811,7 @@ int LoLEngine::calcItemMonsterPosition(ItemInPlay *i, uint16 direction) {
int x = i->x;
int y = i->y;
- recalcSpritePosition(_partyPosX, _partyPosY, x, y, direction);
+ calcSpriteRelPosition(_partyPosX, _partyPosY, x, y, direction);
if (y < 0)
y = 0;
@@ -780,9 +822,9 @@ int LoLEngine::calcItemMonsterPosition(ItemInPlay *i, uint16 direction) {
return res;
}
-void LoLEngine::recalcSpritePosition(uint16 partyX, uint16 partyY, int &itemX, int &itemY, uint16 direction) {
- int a = itemX - partyX;
- int b = partyY - itemY;
+void LoLEngine::calcSpriteRelPosition(uint16 x1, uint16 y1, int &x2, int &y2, uint16 direction) {
+ int a = x2 - x1;
+ int b = y1 - y2;
if (direction) {
if (direction != 2)
@@ -796,8 +838,8 @@ void LoLEngine::recalcSpritePosition(uint16 partyX, uint16 partyY, int &itemX, i
}
}
- itemX = a;
- itemY = b;
+ x2 = a;
+ y2 = b;
}
void LoLEngine::drawDoor(uint8 *shape, uint8 *table, int index, int unk2, int w, int h, int flags) {
@@ -938,7 +980,7 @@ uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *table, int x, int y, in
}
int LoLEngine::calcDrawingLayerParameters(int x1, int y1, int &x2, int &y2, uint16 &w, uint16 &h, uint8 *shape, int flip) {
- recalcSpritePosition(_partyPosX, _partyPosY, x1, y1, _currentDirection);
+ calcSpriteRelPosition(_partyPosX, _partyPosY, x1, y1, _currentDirection);
if (y1 < 0) {
w = h = x2 = y2 = 0;
@@ -965,10 +1007,10 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
return;
int f = flags[monster->mode];
- if ((monster->tick++ < monster->properties->waitTicks) && (!(f & 4)))
+ if ((monster->speedTick++ < monster->properties->speedTotalWaitTicks) && (!(f & 4)))
return;
- monster->tick = 0;
+ monster->speedTick = 0;
if (monster->properties->flags & 0x40) {
monster->might += _rnd.getRandomNumberRng(1, 8);
@@ -982,11 +1024,12 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
}
if (f & 2) {
-
- /////
- // TODO
+ if (updateMonsterAdjustBlocks(monster)) {
+ setMonsterMode(monster, 7);
+ f &= 6;
+ }
}
-
+
if ((f & 1) && (monster->flags & 0x10))
setMonsterMode(monster, 7);
@@ -1000,6 +1043,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
switch (monster->mode) {
case 0:
case 1:
+ // friendly mode
if (monster->flags & 0x10) {
for (int i = 0; i < 30; i++) {
if (_monsters[i].mode == 1)
@@ -1009,28 +1053,87 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
moveMonster(monster);
}
break;
+
case 2:
+ moveMonster(monster);
break;
- case 3:
+
+ case 3:
+ if (updateMonsterAdjustBlocks(monster))
+ setMonsterMode(monster, 7);
+ for (int i = 0; i < 4; i++) {
+ if (calcNewBlockPosition(monster->blockPropertyIndex, i) == _currentBlock)
+ setMonsterMode(monster, 7);
+ }
break;
+
case 4:
+ // straying around not tracing the party
+ moveStrayingMonster(monster);
break;
+
case 5:
+ // second recovery phase after delivering an attack
+ // monsters will rearrange positions in this phase so as to allow a maximum
+ // number of monsters possible attacking at the same time
+ _unkDrawLevelBool = true;
+ monster->fightCurTick--;
+ if ((monster->fightCurTick <= 0) || (checkDrawObjectSpace(_partyPosX, _partyPosY, monster->x, monster->y) > 256) || (monster->flags & 8))
+ setMonsterMode(monster, 7);
+ else
+ rearrangeAttackingMonster(monster);
break;
+
case 6:
+ // same as mode 5, but without rearranging
+ if (--monster->fightCurTick <= 0)
+ setMonsterMode(monster, 7);
break;
+
case 7:
+ // monster destination is set to current party position
+ // depending on the flag setting this gets updated each round
+ // monster can't change mode before arriving at destination and/or attacking the party
+ if (!chasePartyWithDistanceAttacks(monster))
+ chasePartyWithCloseAttacks(monster);
+ checkSceneUpdateNeed(monster->blockPropertyIndex);
break;
+
case 8:
+ // first recovery phase after delivering an attack
+ if (++monster->fightCurTick > 2) {
+ setMonsterMode(monster, 5);
+ monster->fightCurTick = (int8) ((((8 << 8) / monster->properties->fightingStats[4]) * _monsterModifiers[6 + _monsterDifficulty]) >> 8);
+ }
+ checkSceneUpdateNeed(monster->blockPropertyIndex);
break;
+
case 9:
+ if (--monster->fightCurTick) {
+ chasePartyWithCloseAttacks(monster);
+ } else {
+ setMonsterMode(monster, 7);
+ monster->flags &= 0xfff7;
+ }
+
break;
+
case 12:
+ checkSceneUpdateNeed(monster->blockPropertyIndex);
+ if (++monster->fightCurTick > 13)
+ runLevelScriptCustom(0x404, -1, monster->id, monster->id, 0, 0);
break;
+
case 13:
+ if (++monster->fightCurTick > 2)
+ mode13sub(monster);
+ checkSceneUpdateNeed(monster->blockPropertyIndex);
break;
+
case 14:
+ monster->field_1B = 0;
break;
+
default:
break;
}
@@ -1087,6 +1190,54 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
placeMonster(monster, fx, fy);
}
+bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) {
+ if (!monster->field_25)
+ return false;
+
+ return true;
+}
+
+void LoLEngine::chasePartyWithCloseAttacks(MonsterInPlay *monster) {
+ if (!(monster->flags & 8)) {
+ int dir = calcMonsterDirection(monster->x & 0xff00, monster->y & 0xff00, _partyPosX & 0xff00, _partyPosY & 0xff00);
+ int x1 = _partyPosX;
+ int y1 = _partyPosY;
+
+ calcSpriteRelPosition(monster->x, monster->y, x1, y1, dir >> 1);
+
+ 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);
+ 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);
+ }
+
+ setMonsterMode(monster, 8);
+ checkSceneUpdateNeed(monster->blockPropertyIndex);
+
+ } else {
+ setMonsterDirection(monster, dir);
+ checkSceneUpdateNeed(monster->blockPropertyIndex);
+ }
+ return;
+ }
+ }
+
+ if (monster->x != monster->destX || monster->y != monster->destY) {
+ walkMonster(monster);
+ } else {
+ setMonsterDirection(monster, monster->destDirection);
+ setMonsterMode(monster, (_rnd.getRandomNumberRng(1, 100) <= 50) ? 4 : 3);
+ }
+}
+
int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {
static const int8 walkMonsterTable1[] = { 7, -6, 5, -4, 3, -2, 1, 0 };
static const int8 walkMonsterTable2[] = { -7, 6, -5, 4, -3, 2, -1, 0 };
@@ -1206,6 +1357,124 @@ void LoLEngine::getNextStepCoords(int16 srcX, int16 srcY, int &newX, int &newY,
newY = (srcY + shiftTableY[direction]) & 0x1fff;
}
+void LoLEngine::rearrangeAttackingMonster(MonsterInPlay *monster) {
+ int t = (monster->direction >> 1);
+ uint16 mx = monster->x;
+ uint16 my = monster->y;
+ uint16 *c = (t & 1) ? &my : &mx;
+ bool centered = (*c & 0x7f) ? false : true;
+
+ bool posFlag = true;
+ if (monster->properties->maxWidth <= 63) {
+ if (centered) {
+ bool r = false;
+
+ if (_levelBlockProperties[monster->blockPropertyIndex].assignedObjects & 0x8000) {
+ r = true;
+ } else {
+ uint16 id = _levelBlockProperties[monster->blockPropertyIndex].assignedObjects;
+ id = (id & 0x8000) ? (id & 0x7fff) : 0xffff;
+
+ if (id != monster->id) {
+ r = true;
+ } else {
+ for (int i = 0; i < 3; i++) {
+ t = (t + 1) & 3;
+ calcNewBlockPosition(monster->blockPropertyIndex, t);
+ id = _levelBlockProperties[monster->blockPropertyIndex].assignedObjects;
+ id = (id & 0x8000) ? (id & 0x7fff) : 0xffff;
+ if (id != 0xffff)
+ r = true;
+ }
+ }
+ }
+
+ if (r)
+ posFlag = false;
+ } else {
+ posFlag = false;
+ }
+ }
+
+ if (centered && posFlag)
+ return;
+
+ if (posFlag) {
+ if (*c & 0x80)
+ *c -= 32;
+ else
+ *c += 32;
+ } else {
+ if (*c & 0x80)
+ *c += 32;
+ else
+ *c -= 32;
+ }
+
+ if (walkMonsterCheckDest(mx, my, monster, 4))
+ return;
+
+ int fx = _partyPosX;
+ int fy = _partyPosY;
+ calcSpriteRelPosition(mx, my, fx, fy, monster->direction >> 1);
+
+ t = (fx < 0) ? -fx : fx;
+ if (fy > 160 || t > 80)
+ return;
+
+ placeMonster(monster, mx, my);
+}
+
+void LoLEngine::moveStrayingMonster(MonsterInPlay *monster) {
+ int x = 0;
+ int y = 0;
+
+ if (monster->fightCurTick) {
+ uint8 d = (monster->direction - monster->fightCurTick) & 6;
+ uint8 id = monster->id;
+
+ for (int i = 0; i < 7; i++) {
+ getNextStepCoords(monster->x, monster->y, x, y, d);
+
+ if (!walkMonsterCheckDest(x, y, monster, 4)) {
+ placeMonster(monster, x, y);
+ setMonsterDirection(monster, d);
+ if (!i) {
+ if (++id > 3)
+ monster->fightCurTick = 0;
+ }
+ return;
+ }
+
+ d = (d + monster->fightCurTick) & 6;
+ }
+ setMonsterMode(monster, 3);
+
+ } else {
+ monster->direction &= 6;
+ getNextStepCoords(monster->x, monster->y, x, y, monster->direction);
+ if (!walkMonsterCheckDest(x, y, monster, 4)) {
+ placeMonster(monster, x, y);
+ } else {
+ monster->fightCurTick = _rnd.getRandomBit() ? 2 : -2;
+ monster->direction = (monster->direction + monster->fightCurTick) & 6;
+ }
+ }
+}
+
+void LoLEngine::mode13sub(MonsterInPlay *monster) {
+ setMonsterMode(monster, 14);
+ monsterDropItems(monster);
+ checkSceneUpdateNeed(monster->blockPropertyIndex);
+
+ uint8 w = _levelBlockProperties[monster->blockPropertyIndex].walls[0];
+ uint8 f = _levelBlockProperties[monster->blockPropertyIndex].flags;
+ if (_wllVmpMap[w] == 0 && _wllShapeMap[w] == 0 && !(f & 0x40) && !(monster->properties->flags & 0x1000))
+ _levelBlockProperties[monster->blockPropertyIndex].flags |= 0x80;
+
+ placeMonster(monster, 0, 0);
+}
+
} // end of namespace Kyra
#endif // ENABLE_LOL
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 3442ba3ced..5d2fda8c53 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -1001,9 +1001,9 @@ bool StaticResource::loadCharData(const char *filename, void *&ptr, int &size) {
t->field_34 = file->readUint16LE();
t->field_36 = file->readByte();
t->itemsProtection = file->readUint16LE();
- t->hitPointsCur = file->readUint16LE();;
+ t->hitPointsCur = file->readSint16LE();;
t->hitPointsMax = file->readUint16LE();;
- t->magicPointsCur = file->readUint16LE();;
+ t->magicPointsCur = file->readSint16LE();;
t->magicPointsMax = file->readUint16LE();;
t->field_41 = file->readByte();
t->damageSuffered = file->readUint16LE();