From b55602180decd888084797a7e7a8fb8778d6c7ee Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sat, 21 Mar 2009 14:30:25 +0000 Subject: LOL: The guards will now attack you when you throw certain items at them. They can't do any damage though, since this isn't implemented yet. svn-id: r39582 --- engines/kyra/gui_lol.cpp | 12 +- engines/kyra/items_lol.cpp | 18 +-- engines/kyra/lol.cpp | 126 +++++++++++++++- engines/kyra/lol.h | 60 +++++--- engines/kyra/scene_lol.cpp | 50 +++++-- engines/kyra/script_lol.cpp | 44 +++--- engines/kyra/sprites_lol.cpp | 341 ++++++++++++++++++++++++++++++++++++++----- engines/kyra/staticres.cpp | 4 +- 8 files changed, 542 insertions(+), 113 deletions(-) (limited to 'engines') 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(); -- cgit v1.2.3