aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorFlorian Kagerer2009-03-03 22:32:39 +0000
committerFlorian Kagerer2009-03-03 22:32:39 +0000
commit3f2af1e8a1f7033846747f744fc0f53875824e4b (patch)
treed1efb50eab843008c796d138d47c7af0a31531f2 /engines
parent1956c1c68f4822943a48ae58fcfbdccb44055be4 (diff)
downloadscummvm-rg350-3f2af1e8a1f7033846747f744fc0f53875824e4b.tar.gz
scummvm-rg350-3f2af1e8a1f7033846747f744fc0f53875824e4b.tar.bz2
scummvm-rg350-3f2af1e8a1f7033846747f744fc0f53875824e4b.zip
LOL: implemented some walking code for the monsters
svn-id: r39097
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/gui_lol.cpp4
-rw-r--r--engines/kyra/lol.cpp90
-rw-r--r--engines/kyra/lol.h53
-rw-r--r--engines/kyra/scene_lol.cpp2
-rw-r--r--engines/kyra/script_lol.cpp41
-rw-r--r--engines/kyra/sprites_lol.cpp231
-rw-r--r--engines/kyra/timer_lol.cpp2
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);