diff options
-rw-r--r-- | engines/kyra/gui_lol.cpp | 4 | ||||
-rw-r--r-- | engines/kyra/lol.cpp | 90 | ||||
-rw-r--r-- | engines/kyra/lol.h | 53 | ||||
-rw-r--r-- | engines/kyra/scene_lol.cpp | 2 | ||||
-rw-r--r-- | engines/kyra/script_lol.cpp | 41 | ||||
-rw-r--r-- | engines/kyra/sprites_lol.cpp | 231 | ||||
-rw-r--r-- | engines/kyra/timer_lol.cpp | 2 |
7 files changed, 286 insertions, 137 deletions
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp index 379eb304b6..009ba3063f 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -1084,7 +1084,7 @@ int LoLEngine::clickedScreen(Button *button) { } int LoLEngine::clickedPortraitLeft(Button *button) { - removeUnkFlags(2); + disableSysTimer(2); if (!_weaponsDisabled) { _screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2); @@ -1184,7 +1184,7 @@ int LoLEngine::clickedExitCharInventory(Button *button) { _lastCharInventory = -1; updateSceneWindow(); - setUnkFlags(2); + enableSysTimer(2); return 1; } diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 513f45fd51..0cd3e14469 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -33,6 +33,7 @@ #include "sound/voc.h" #include "sound/audiostream.h" +#include "common/config-manager.h" #include "common/endian.h" #include "base/version.h" @@ -147,6 +148,8 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _monsters = 0; _unkGameFlag = 0; _lastMouseRegion = 0; + _monsterUnkDir = _monsterCountUnk = _monsterShiftAlt = 0; + _monsterCurBlock = 0; //_preSeq_X1 = _preSeq_Y1 = _preSeq_X2 = _preSeq_Y2 = 0; _dscUnk1 = 0; @@ -174,12 +177,12 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _curMusicTheme = -1; _curMusicFileExt = 0; _curMusicFileIndex = -1; + _environmentSfx = _environmentSfxVol = _environmentSfxDistThreshold = 0; _sceneDrawVar1 = _sceneDrawVar2 = _sceneDrawVar3 = _wllProcessFlag = 0; _partyPosX = _partyPosY = 0; _shpDmX = _shpDmY = _dmScaleW = _dmScaleH = 0; - _intFlag3 = 3; _floatingMouseArrowControl = 0; memset(_activeTim, 0, 10 * sizeof(TIM*)); @@ -335,6 +338,8 @@ Common::Error LoLEngine::init() { KyraEngine_v1::init(); initStaticResource(); + _environmentSfxDistThreshold = (MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB) == MD_ADLIB || ConfMan.getBool("multi_midi")) ? 15 : 3; + _gui = new GUI_LoL(this); assert(_gui); @@ -506,7 +511,7 @@ Common::Error LoLEngine::go() { if (!shouldQuit() && (processSelection == 0 || processSelection == 3)) { _screen->_fadeFlag = 3; _sceneUpdateRequired = true; - setUnkFlags(1); + enableSysTimer(1); runLoop(); } @@ -746,28 +751,18 @@ void LoLEngine::startupNew() { _screen->showMouse(); } -int LoLEngine::setUnkFlags(int unk) { - if (unk < 1 || unk > 14) - return 0; - - int r = (_intFlag3 & (2 << unk)) ? 1 : 0; - _intFlag3 |= (2 << unk); - - return r; +void LoLEngine::enableSysTimer(int sysTimer) { + if (sysTimer == 2) + _timer->pause(false); } -int LoLEngine::removeUnkFlags(int unk) { - if (unk < 1 || unk > 14) - return 0; - - int r = (_intFlag3 & (2 << unk)) ? 1 : 0; - _intFlag3 &= ~(2 << unk); - - return r; +void LoLEngine::disableSysTimer(int sysTimer) { + if (sysTimer == 2) + _timer->pause(true); } void LoLEngine::runLoop() { - setUnkFlags(2); + enableSysTimer(2); bool _runFlag = true; _unkFlag |= 0x800; @@ -788,7 +783,7 @@ void LoLEngine::runLoop() { if (_sceneUpdateRequired) gui_drawScene(0); else - runLoopSub4(0); + updateEnvironmentalSfx(0); /*if (_partyDeathFlag != -1) { checkForPartyDeath(_partyDeathFlag); @@ -1179,7 +1174,7 @@ void LoLEngine::resetPortraitsArea() { if (!textEnabled() || (!(_hideControls & 2))) timerUpdatePortraitAnimations(1); - removeUnkFlags(2); + disableSysTimer(2); } void LoLEngine::fadeText() { @@ -1331,6 +1326,7 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) { volume = -volIndex; // volume TODO + volume = 254 - volume; int16 vocIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2]); if (vocIndex != -1) { @@ -1340,8 +1336,6 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) { track = track < _ingameMT32SoundIndexSize ? _ingameMT32SoundIndex[track] - 1 : -1; else if (_sound->getSfxType() == Sound::kMidiGM) track = track < _ingameGMSoundIndexSize ? _ingameGMSoundIndex[track] - 1: -1; - //else if (_sound->getSfxType() == Sound::kAdlib) - // track = track < _ingameADLSoundIndexSize ? _ingameADLSoundIndex[track] - 1: -1; if (track == 168) track = 167; @@ -1351,6 +1345,45 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) { } } +void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) { + if (!(_unkGameFlag & 1)) + return; + + if (_environmentSfx) + snd_playSoundEffect(_environmentSfx, _environmentSfxVol); + + int dist = 0; + if (block) { + dist = getMonsterDistance(_currentBlock, block); + if (dist > _environmentSfxDistThreshold) { + _environmentSfx = 0; + return; + } + } + + _environmentSfx = soundId; + _environmentSfxVol = (15 - ((block || dist < 2) ? dist : 0)) << 4; + + if (block != _currentBlock) { + static const int8 blockShiftTable[] = { -32, -31, 1, 33, 32, 31, -1, -33 }; + uint16 cbl = _currentBlock; + + for (int i = 3; i > 0; i--) { + int dir = calcMonsterDirection(cbl & 0x1f, cbl >> 5, block & 0x1f, block >> 5); + cbl += blockShiftTable[dir]; + if (cbl != block) { + if (testWallFlag(cbl, 0, 1)) + _environmentSfxVol >>= 1; + } + } + } + + if (!soundId || _sceneUpdateRequired) + return; + + snd_processEnvironmentalSoundEffect(0, 0); +} + void LoLEngine::snd_loadSoundFile(int track) { if (_unkGameFlag & 2) { char filename[13]; @@ -1501,13 +1534,6 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str return 1; } -void LoLEngine::cmzS7(int a, int block) { - if (!(_unkGameFlag & 1)) - return; - - // TODO -} - void LoLEngine::giveItemToMonster(MonsterInPlay *monster, uint16 item) { uint16 *c = &monster->assignedItems; while (*c) @@ -1529,8 +1555,8 @@ void LoLEngine::delay(uint32 millis, bool cUpdate, bool isMainLoop) { } } -void LoLEngine::runLoopSub4(int a) { - cmzS7(a, _currentBlock); +void LoLEngine::updateEnvironmentalSfx(int soundId) { + snd_processEnvironmentalSoundEffect(soundId, _currentBlock); } bool LoLEngine::notEnoughMagic(int charNum, int spellNum, int spellLevel) { diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 673dbdd9dd..a3cb4342cd 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -115,7 +115,7 @@ struct MonsterProperty { uint16 unk5; uint16 unk6[5]; uint8 unk7[4]; - uint8 unk8[3]; + uint8 sounds[3]; }; struct MonsterInPlay { @@ -126,9 +126,9 @@ struct MonsterInPlay { uint16 x; uint16 y; int8 level; - uint16 itemPosX; - uint16 itemPosY; - uint8 field10; + uint16 destX; + uint16 destY; + uint8 destDirection; uint8 anon8; uint8 anonh; uint8 anon9; @@ -136,7 +136,7 @@ struct MonsterInPlay { uint8 mode; uint8 field_15; uint8 id; - uint8 field_17; + uint8 direction; uint8 facing; uint16 flags; uint8 field_1B; @@ -162,7 +162,7 @@ struct ItemInPlay { int8 level; uint16 itemPropertyIndex; uint16 shpCurFrame_flg; - uint8 field10; + uint8 destDirection; uint8 anon8; uint8 anonh; uint8 anon9; @@ -241,11 +241,7 @@ private: // main loop void runLoop(); void update(); - - int setUnkFlags(int unk); - int removeUnkFlags(int unk); - - int _intFlag3; + void updateEnvironmentalSfx(int soundId); // mouse void setMouseCursorToIcon(int icon); @@ -325,6 +321,7 @@ private: int snd_characterSpeaking(); void snd_stopSpeech(bool setFlag); void snd_playSoundEffect(int track, int volume); + void snd_processEnvironmentalSoundEffect(int soundId, int block); void snd_loadSoundFile(int track); int snd_playTrack(int track); int snd_stopMusic(); @@ -336,6 +333,9 @@ private: int _lastMusicTrack; int _curMusicFileIndex; char _curMusicFileExt; + int _environmentSfx; + int _environmentSfxVol; + int _environmentSfxDistThreshold; int _curTlkFile; int _speechFlag; @@ -517,7 +517,7 @@ private: int olol_resetBlockShapeAssignment(EMCState *script); int olol_initMonster(EMCState *script); int olol_loadMonsterProperties(EMCState *script); - int olol_68(EMCState *script); + int olol_moveMonster(EMCState *script); int olol_setScriptTimer(EMCState *script); int olol_loadTimScript(EMCState *script); int olol_runTimScript(EMCState *script); @@ -538,7 +538,7 @@ private: int olol_setDoorState(EMCState *script); int olol_assignCustomSfx(EMCState *script); int olol_resetPortraitsArea(EMCState *script); - int olol_setUnkFlags(EMCState *script); + int olol_enableSysTimer(EMCState *script); // tim scripts TIM *_activeTim[10]; @@ -907,17 +907,16 @@ private: int placeMonstersUnk(int block); void setMonsterMode(MonsterInPlay *monster, int a); void placeMonster(MonsterInPlay *monster, uint16 x, uint16 y); - int cmzS1(uint16 x1, uint16 y1, uint16 x2, uint16 y2); - void cmzS2(MonsterInPlay *monster, int a); + int calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2); + void setMonsterDirection(MonsterInPlay *monster, int dir); void cmzS3(MonsterInPlay *monster); void removeItemOrMonsterFromBlock(uint16 *blockItemIndex, int id); void assignItemOrMonsterToBlock(uint16 *blockItemIndex, int id); - void cmzS7(int a, int block); - void giveItemToMonster(MonsterInPlay *monster, uint16 a); - int checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, int p1, int p2); + void giveItemToMonster(MonsterInPlay *monster, uint16 item); + int checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, int testFlag, int wallFlag); int calcMonsterSkillLevel(int id, int a); - int checkBlockForWallsAndSufficientSpace(int block, int x, int y, int monsterWidth, int p1, int p2); - bool checkBlockOccupiedByParty(int x, int y, int p1); + int checkBlockForWallsAndSufficientSpace(int block, int x, int y, int monsterWidth, int testFlag, int wallFlag); + bool checkBlockOccupiedByParty(int x, int y, int testFlag); const uint16 *getCharacterOrMonsterStats(int id); void drawMonstersAndItems(int block); void drawMonster(uint16 id); @@ -932,7 +931,12 @@ private: void updateMonster(MonsterInPlay *monster); void moveMonster(MonsterInPlay *monster); - void shiftMonster(MonsterInPlay *monster); + void walkMonster(MonsterInPlay *monster); + int walkMonsterCalcNextStep(MonsterInPlay *monster); + int getMonsterDistance(uint16 block1, uint16 block2); + int walkMonster_s3(uint16 monsterBlock, int unk1, int unk2, uint16 curBlock); + int walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk); + void walkMonsterGetNextStepCoords(int16 monsterX, int16 monsterY, int &newX, int &newY, uint16 unk); MonsterInPlay *_monsters; MonsterProperty *_monsterProperties; @@ -940,6 +944,10 @@ private: uint8 **_monsterPalettes; uint8 **_monsterShapesEx; uint8 _monsterUnk[3]; + uint16 _monsterCurBlock; + int _monsterUnkDir; + int _monsterCountUnk; + int _monsterShiftAlt; const uint16 *_monsterModifiers; int _monsterModifiersSize; @@ -956,7 +964,8 @@ private: // misc void delay(uint32 millis, bool cUpdate = false, bool isMainLoop = false); - void runLoopSub4(int a); + void enableSysTimer(int sysTimer); + void disableSysTimer(int sysTimer); uint8 *_pageBuffer1; uint8 *_pageBuffer2; diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 7922345973..dbb3fe82ad 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -1066,7 +1066,7 @@ void LoLEngine::drawScene(int pageNum) { SWAP(_sceneDrawPage1, _sceneDrawPage2); } - runLoopSub4(0); + updateEnvironmentalSfx(0); gui_drawCompass(); _sceneUpdateRequired = false; diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index c81e0e4aa2..8d0ba48f8a 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -489,9 +489,9 @@ int LoLEngine::olol_setGlobalVar(EMCState *script) { if (b == 1) { if (!textEnabled() || (!(_hideControls & 2))) timerUpdatePortraitAnimations(1); - removeUnkFlags(2); + disableSysTimer(2); } else { - setUnkFlags(2); + enableSysTimer(2); } break; @@ -553,7 +553,7 @@ int LoLEngine::olol_initMonster(EMCState *script) { l->facing = stackPos(3); l->type = stackPos(4); l->properties = &_monsterProperties[l->type]; - l->field_17 = l->facing << 1; + l->direction = l->facing << 1; l->might = (l->properties->might * _monsterModifiers[((_unkGameFlag & 0x30) >> 4)]) >> 8; if (_currentLevel == 12 && l->type == 2) @@ -568,9 +568,9 @@ int LoLEngine::olol_initMonster(EMCState *script) { setMonsterMode(l, stackPos(6)); placeMonster(l, l->x, l->y); - l->itemPosX = l->x; - l->itemPosY = l->y; - l->field10 = l->field_17; + l->destX = l->x; + l->destY = l->y; + l->destDirection = l->direction; for (int ii = 0; ii < 4; ii++) l->field_2A[ii] = stackPos(7 + ii); @@ -638,21 +638,21 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) { } for (int i = 0; i < 3; i++) - l->unk8[i] = stackPos(39 + i); + l->sounds[i] = stackPos(39 + i); return 1; } -int LoLEngine::olol_68(EMCState *script) { - +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)]; if (m->mode == 1 || m->mode == 2) { - calcCoordinates(m->itemPosX, m->itemPosY, stackPos(1), stackPos(2), stackPos(3)); - m->field10 = stackPos(4); + calcCoordinates(m->destX, m->destY, stackPos(1), stackPos(2), stackPos(3)); + m->destDirection = stackPos(4) << 1; - if (m->x != m->itemPosX || m->y != m->itemPosY) - cmzS2(m, cmzS1(m->x, m->y, m->itemPosX, m->itemPosY)); + if (m->x != m->destX || m->y != m->destY) + setMonsterDirection(m, calcMonsterDirection(m->x, m->y, m->destX, m->destY)); } return 1; @@ -810,10 +810,11 @@ int LoLEngine::olol_assignCustomSfx(EMCState *script) { if (!c || i > 250) return 0; - if (_ingameSoundIndex[i] == 0xffff) + uint16 t = READ_LE_UINT16(&_ingameSoundIndex[i << 1]); + if (t == 0xffff) return 0; - strcpy(_ingameSoundList[_ingameSoundIndex[i]], c); + strcpy(_ingameSoundList[t], c); return 0; } @@ -823,9 +824,9 @@ int LoLEngine::olol_resetPortraitsArea(EMCState *script) { return 1; } -int LoLEngine::olol_setUnkFlags(EMCState *script) { +int LoLEngine::olol_enableSysTimer(EMCState *script) { _hideInventory = 0; - setUnkFlags(2); + enableSysTimer(2); return 1; } @@ -891,7 +892,7 @@ int LoLEngine::tlol_displayText(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_initDialogueSequence(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_initDialogueSequence(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]); - this->initDialogueSequence(param[0]); + initDialogueSequence(param[0]); return 1; } @@ -1077,7 +1078,7 @@ void LoLEngine::setupOpcodeTable() { OpcodeUnImpl(); // 0x44 - Opcode(olol_68); + Opcode(olol_moveMonster); OpcodeUnImpl(); OpcodeUnImpl(); OpcodeUnImpl(); @@ -1206,7 +1207,7 @@ void LoLEngine::setupOpcodeTable() { OpcodeUnImpl(); OpcodeUnImpl(); Opcode(olol_resetPortraitsArea); - Opcode(olol_setUnkFlags); + Opcode(olol_enableSysTimer); // 0x9C OpcodeUnImpl(); diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index 84d4fbce87..d4a2421953 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -161,8 +161,8 @@ void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) { if (monster->mode == 13 && mode != 14) return; if (mode == 7) { - monster->itemPosX = _partyPosX; - monster->itemPosY = _partyPosX; + monster->destX = _partyPosX; + monster->destY = _partyPosX; } if (monster->mode == 1 && mode == 7) { @@ -171,9 +171,9 @@ void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) { continue; monster->mode = mode; monster->field_15 = 0; - monster->itemPosX = _partyPosX; - monster->itemPosY = _partyPosY; - cmzS2(monster, cmzS1(monster->x, monster->y, monster->itemPosX, monster->itemPosY)); + monster->destX = _partyPosX; + monster->destY = _partyPosY; + setMonsterDirection(monster, calcMonsterDirection(monster->x, monster->y, monster->destX, monster->destY)); } } else { monster->mode = mode; @@ -197,9 +197,9 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) { bool cont = true; int t = monster->blockPropertyIndex; if (monster->blockPropertyIndex) { - removeItemOrMonsterFromBlock(&_levelBlockProperties[monster->blockPropertyIndex].itemMonsterIndex, ((uint16)monster->id) | 0x8000); - _levelBlockProperties[monster->blockPropertyIndex].direction = 5; - checkSceneUpdateNeed(monster->blockPropertyIndex); + removeItemOrMonsterFromBlock(&_levelBlockProperties[t].itemMonsterIndex, ((uint16)monster->id) | 0x8000); + _levelBlockProperties[t].direction = 5; + checkSceneUpdateNeed(t); } else { cont = false; } @@ -219,7 +219,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) { _levelBlockProperties[monster->blockPropertyIndex].direction = 5; checkSceneUpdateNeed(monster->blockPropertyIndex); - if (monster->properties->unk8[0] == 0 || cont == false) + if (monster->properties->sounds[0] == 0 || cont == false) return; if ((!(monster->properties->flags & 0x100) || ((monster->anon9 & 1) == 0)) && monster->blockPropertyIndex == t) @@ -231,10 +231,10 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) { if (_updateFlags & 1) return; - cmzS7(monster->properties->unk3[5], monster->blockPropertyIndex); + snd_processEnvironmentalSoundEffect(monster->properties->sounds[0], monster->blockPropertyIndex); } -int LoLEngine::cmzS1(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { +int LoLEngine::calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { int16 r = 0; int16 t1 = y1 - y2; if (t1 < 0) { @@ -251,11 +251,11 @@ int LoLEngine::cmzS1(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { t2 = -t2; } - uint8 f = 0; + uint8 f = 1; if (t2 >= t1) { if (t2 > t1) - f = 1; + f = 0; SWAP(t1, t2); } @@ -263,19 +263,18 @@ int LoLEngine::cmzS1(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { t1 = (t1 + 1) >> 1; - f = 0; - f = (t2 > t1) ? 1 : 0; + f = (t1 > t2) ? 1 : 0; r = (r << 1) | f; static const uint8 retVal[] = { 1, 2, 1, 0, 7, 6, 7, 0, 3, 2, 3, 4, 5, 6, 5, 4}; return retVal[r]; } -void LoLEngine::cmzS2(MonsterInPlay *monster, int a) { - monster->field_17 = a; +void LoLEngine::setMonsterDirection(MonsterInPlay *monster, int dir) { + monster->direction = dir; - if (!(a & 1) || ((monster->field_17 - (monster->facing << 1)) < 2)) - monster->facing = monster->field_17 >> 1; + if (!(dir & 1) || ((monster->direction - (monster->facing << 1)) >= 2)) + monster->facing = monster->direction >> 1; checkSceneUpdateNeed(monster->blockPropertyIndex); } @@ -288,7 +287,7 @@ void LoLEngine::removeItemOrMonsterFromBlock(uint16 *blockItemIndex, int id) { while (*blockItemIndex) { if (*blockItemIndex == id) { ItemInPlay *t = findItem(id); - blockItemIndex = &t->next; + *blockItemIndex = t->next; t->next = 0; return; } else { @@ -304,33 +303,33 @@ void LoLEngine::assignItemOrMonsterToBlock(uint16 *blockItemIndex, int id) { *blockItemIndex = id; } -int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, int p1, int p2) { - int monsterUnk_ = 0; +int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, int testFlag, int wallFlag) { + _monsterUnkDir = 0; int x2 = 0; int y2 = 0; int xOffs = 0; int yOffs = 0; int flag = 0; - int r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y), x, y, monsterWidth, p1, p2); + int r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y), x, y, monsterWidth, testFlag, wallFlag); if (r) return r; - r = checkBlockOccupiedByParty(x, y, p1); + r = checkBlockOccupiedByParty(x, y, testFlag); if (r) return 4; if (x & 0x80) { if (((x & 0xff) + monsterWidth) & 0xff00) { xOffs = 1; - monsterUnk_ = 2; + _monsterUnkDir = 2; x2 = x + monsterWidth; - r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y), x, y, monsterWidth, p1, p2); + r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y), x, y, monsterWidth, testFlag, wallFlag); if (r) return r; - r = checkBlockOccupiedByParty(x + xOffs, y, p1); + r = checkBlockOccupiedByParty(x + xOffs, y, testFlag); if (r) return 4; @@ -339,14 +338,14 @@ int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, } else { if (((x & 0xff) - monsterWidth) & 0xff00) { xOffs = -1; - monsterUnk_ = 6; + _monsterUnkDir = 6; x2 = x - monsterWidth; - r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y), x, y, monsterWidth, p1, p2); + r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y), x, y, monsterWidth, testFlag, wallFlag); if (r) return r; - r = checkBlockOccupiedByParty(x + xOffs, y, p1); + r = checkBlockOccupiedByParty(x + xOffs, y, testFlag); if (r) return 4; @@ -357,14 +356,14 @@ int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, if (y & 0x80) { if (((y & 0xff) + monsterWidth) & 0xff00) { yOffs = 1; - monsterUnk_ = 4; + _monsterUnkDir = 4; y2 = y + monsterWidth; - r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y2), x, y, monsterWidth, p1, p2); + r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y2), x, y, monsterWidth, testFlag, wallFlag); if (r) return r; - r = checkBlockOccupiedByParty(x, y + yOffs, p1); + r = checkBlockOccupiedByParty(x, y + yOffs, testFlag); if (r) return 4; } else { @@ -373,14 +372,14 @@ int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, } else { if (((y & 0xff) - monsterWidth) & 0xff00) { yOffs = -1; - monsterUnk_ = 0; + _monsterUnkDir = 0; y2 = y - monsterWidth; - r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y2), x, y, monsterWidth, p1, p2); + r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y2), x, y, monsterWidth, testFlag, wallFlag); if (r) return r; - r = checkBlockOccupiedByParty(x, y + yOffs, p1); + r = checkBlockOccupiedByParty(x, y + yOffs, testFlag); if (r) return 4; } else { @@ -391,11 +390,11 @@ int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, if (!flag) return 0; - r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y2), x, y, monsterWidth, p1, p2); + r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y2), x, y, monsterWidth, testFlag, wallFlag); if (r) return r; - r = checkBlockOccupiedByParty(x + xOffs, y + yOffs, p1); + r = checkBlockOccupiedByParty(x + xOffs, y + yOffs, testFlag); if (r) return 4; @@ -419,21 +418,19 @@ int LoLEngine::calcMonsterSkillLevel(int id, int a) { return (r- (r >> 1)); } -int LoLEngine::checkBlockForWallsAndSufficientSpace(int block, int x, int y, int monsterWidth, int p1, int p2) { +int LoLEngine::checkBlockForWallsAndSufficientSpace(int block, int x, int y, int monsterWidth, int testFlag, int wallFlag) { if (block == _currentBlock) - p1 &= 0xfffe; - - int _monsterBlock = 0; + testFlag &= 0xfffe; - if (p1 & 1) { - _monsterBlock = block; - if (testWallFlag(block, -1, p2)) + if (testFlag & 1) { + _monsterCurBlock = block; + if (testWallFlag(block, -1, wallFlag)) return 1; } - _monsterBlock = 0; + _monsterCurBlock = 0; - if (!(p1 & 2)) + if (!(testFlag & 2)) return 0; uint16 b = _levelBlockProperties[block].itemMonsterIndex; @@ -452,8 +449,8 @@ int LoLEngine::checkBlockForWallsAndSufficientSpace(int block, int x, int y, int return 0; } -bool LoLEngine::checkBlockOccupiedByParty(int x, int y, int p1) { - if ((p1 & 4) && (_currentBlock == calcBlockIndex(x, y))) +bool LoLEngine::checkBlockOccupiedByParty(int x, int y, int testFlag) { + if ((testFlag & 4) && (_currentBlock == calcBlockIndex(x, y))) return true; return false; @@ -627,7 +624,7 @@ void LoLEngine::recalcItemMonsterPositions(uint16 direction, uint16 itemIndex, L uint16 *b = &l->field_6; ItemInPlay *i2 = 0; - while (b) { + while (*b) { i2 = findItem(itemIndex); if (flag) { @@ -856,8 +853,8 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) { } if (monster->flags & 8) { - monster->itemPosX = _partyPosX; - monster->itemPosY = _partyPosY; + monster->destX = _partyPosX; + monster->destY = _partyPosY; } if (s & 2) { @@ -922,19 +919,135 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) { } void LoLEngine::moveMonster(MonsterInPlay *monster) { - static const int8 pos[] = { 0, 1, 3, 3, 0, 1, 2, 2, 1, 1, 2, 3, 0, 0, 2, 3, 0 }; - if (monster->x != monster->itemPosX || monster->y != monster->itemPosY) { - shiftMonster(monster); - } else if (monster->field_17 != monster->field10) { - int i = (monster->facing << 2) + (monster->field10 >> 1); - cmzS2(monster, pos[i]); + static const int8 turnPos[] = { 0, 2, 6, 6, 0, 2, 4, 4, 2, 2, 4, 6, 0, 0, 4, 6, 0 }; + if (monster->x != monster->destX || monster->y != monster->destY) { + walkMonster(monster); + } else if (monster->direction != monster->destDirection) { + int i = (monster->facing << 2) + (monster->destDirection >> 1); + setMonsterDirection(monster, turnPos[i]); } } -void LoLEngine::shiftMonster(MonsterInPlay *monster) { +void LoLEngine::walkMonster(MonsterInPlay *monster) { if (monster->properties->flags & 0x400) return; + int s = walkMonsterCalcNextStep(monster); + + if (s == -1) { + if (walkMonsterCheckDest(monster->x, monster->y, monster, 4) != 1) + return; + + _monsterUnkDir ^= 4; + setMonsterDirection(monster, _monsterUnkDir); + } else { + setMonsterDirection(monster, s); + if (monster->field_25) { + if (getMonsterDistance(monster->blockPropertyIndex, _currentBlock) >= 2) { + if (walkMonster_s3(monster->blockPropertyIndex, monster->direction, 3, _currentBlock) != 5) { + if (monster->field_27) + return; + } + } + } + } + + int fx = 0; + int fy = 0; + + walkMonsterGetNextStepCoords(monster->x, monster->y, fx, fy, (s == -1) ? _monsterUnkDir : s); + placeMonster(monster, fx, fy); +} + +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 }; + + if (++_monsterCountUnk > 10) { + _monsterCountUnk = 0; + _monsterShiftAlt ^= 1; + } + + const int8 *tbl = _monsterShiftAlt ? walkMonsterTable2 : walkMonsterTable1; + + int sx = monster->x; + int sy = monster->y; + int s = monster->direction; + int d = calcMonsterDirection(monster->x, monster->y, monster->destX, monster->destY); + + if (monster->flags & 8) + d ^= 4; + + d = (d - s) & 7; + + if (d >= 5) + s = (s - 1) & 7; + else if (d) + s = (s + 1) & 7; + + for (int i = 7; i > -1; i--) { + s = (s + tbl[i]) & 7; + + int fx = 0; + int fy = 0; + walkMonsterGetNextStepCoords(sx, sy, fx, fy, s); + d = walkMonsterCheckDest(fx, fy, monster, 4); + + if (!d) + return s; + + if ((d != 1) || (s & 1) || (!(monster->properties->flags & 0x80))) + continue; + + uint8 w = _levelBlockProperties[_monsterCurBlock].walls[(s >> 1) ^ 2]; + + if (_wllWallFlags[w] & 0x20) { + if (_wllBuffer3[w] == 5) + openDoorSub2(_monsterCurBlock, 1); + } + + if (_wllWallFlags[w] & 8) + return -1; + } + + return -1; +} + +int LoLEngine::getMonsterDistance(uint16 block1, uint16 block2) { + int8 b1x = block1 & 0x1f; + int8 b1y = (block1 >> 8) & 0x1f; + int8 b2x = block2 & 0x1f; + int8 b2y = (block2 >> 8) & 0x1f; + + uint8 dy = ABS(b2y - b1y); + uint8 dx = ABS(b2x - b1x); + + if (dx > dy) + SWAP(dx, dy); + + return (dx << 1) + dy; +} + +int LoLEngine::walkMonster_s3(uint16 monsterBlock, int unk1, int unk2, uint16 curBlock) { + return 0; +} + +int LoLEngine::walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk) { + uint8 m = monster->mode; + monster->mode = 15; + + int res = checkBlockBeforeMonsterPlacement(x, y, monster->properties->maxWidth, 7, monster->properties->flags & 0x1000 ? 32 : unk); + + monster->mode = m; + return res; +} + +void LoLEngine::walkMonsterGetNextStepCoords(int16 srcX, int16 srcY, int &newX, int &newY, uint16 unk) { + static const int8 shiftTableX[] = { 0, 32, 32, 32, 0, -32, -32, -32 }; + static const int8 shiftTableY[] = { -32, -32, 0, 32, 32, 32, 0, -32 }; + + newX = (srcX + shiftTableX[unk]) & 0x1fff; + newY = (srcY + shiftTableY[unk]) & 0x1fff; } } // end of namespace Kyra diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp index 994c691aa8..6bbb9e6b2c 100644 --- a/engines/kyra/timer_lol.cpp +++ b/engines/kyra/timer_lol.cpp @@ -37,7 +37,7 @@ void LoLEngine::setupTimers() { _timer->addTimer(0, TimerV2(timerProcessOpenDoor), 15, true); _timer->addTimer(0x10, TimerV2(timerProcessMonsters), 6, true); _timer->addTimer(0x11, TimerV2(timerProcessMonsters), 6, true); - _timer->setNextRun(0x11, 3); + _timer->setNextRun(0x11, _system->getMillis() + 3 * _tickLength); _timer->addTimer(3, TimerV2(timerSub3), 15, true); _timer->addTimer(4, TimerV2(timerSub4), 1, true); _timer->addTimer(0x50, TimerV2(timerSub5), 0, false); |