aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorFlorian Kagerer2009-03-06 22:53:08 +0000
committerFlorian Kagerer2009-03-06 22:53:08 +0000
commit8639e34b41a22336301bff08827dfc7f0988424c (patch)
tree09dbc3a7708a889d732be20e4c3291b7b97f396a /engines
parent3753d0b5f8f4fde1c7d5be10deb980bbc1bcda65 (diff)
downloadscummvm-rg350-8639e34b41a22336301bff08827dfc7f0988424c.tar.gz
scummvm-rg350-8639e34b41a22336301bff08827dfc7f0988424c.tar.bz2
scummvm-rg350-8639e34b41a22336301bff08827dfc7f0988424c.zip
LOL: - doors can now be opened and closed
- some more work on monster walk code svn-id: r39166
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/lol.cpp36
-rw-r--r--engines/kyra/lol.h38
-rw-r--r--engines/kyra/resource.h2
-rw-r--r--engines/kyra/scene_lol.cpp70
-rw-r--r--engines/kyra/script_lol.cpp20
-rw-r--r--engines/kyra/sprites_lol.cpp80
-rw-r--r--engines/kyra/staticres.cpp11
-rw-r--r--engines/kyra/timer.cpp23
-rw-r--r--engines/kyra/timer.h5
-rw-r--r--engines/kyra/timer_lol.cpp53
10 files changed, 260 insertions, 78 deletions
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 399427ec1c..a1cf3e51ab 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -189,6 +189,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
memset(_activeTim, 0, 10 * sizeof(TIM*));
memset(_activeVoiceFile, 0, sizeof(_activeVoiceFile));
+ memset(&_openDoorState, 0, sizeof(OpenDoorState) * 3);
_pageBuffer1 = _pageBuffer2 = 0;
@@ -212,8 +213,8 @@ LoLEngine::~LoLEngine() {
delete _gui;
_gui = 0;
delete _tim;
- _tim = 0;
- delete _txt;
+ _tim = 0;
+ delete _txt;
_txt = 0;
delete[] _itemsInPlay;
@@ -359,7 +360,7 @@ Common::Error LoLEngine::init() {
memset(_itemsInPlay, 0, sizeof(ItemInPlay) * 400);
_characters = new LoLCharacter[4];
- memset(_characters, 0, sizeof(LoLCharacter) * 3);
+ memset(_characters, 0, sizeof(LoLCharacter) * 4);
if (!_sound->init())
error("Couldn't init sound");
@@ -752,16 +753,6 @@ void LoLEngine::startupNew() {
_screen->showMouse();
}
-void LoLEngine::enableSysTimer(int sysTimer) {
- if (sysTimer == 2)
- _timer->pause(false);
-}
-
-void LoLEngine::disableSysTimer(int sysTimer) {
- if (sysTimer == 2)
- _timer->pause(true);
-}
-
void LoLEngine::runLoop() {
enableSysTimer(2);
@@ -790,7 +781,7 @@ void LoLEngine::runLoop() {
checkForPartyDeath(_partyDeathFlag);
_partyDeathFlag = -1;
}*/
-
+
delay(_tickLength);
}
}
@@ -1168,6 +1159,7 @@ void LoLEngine::restoreSceneAfterDialogueSequence(int redraw) {
}
_hideInventory = 0;
+ enableSysTimer(2);
}
void LoLEngine::resetPortraitsArea() {
@@ -1175,7 +1167,7 @@ void LoLEngine::resetPortraitsArea() {
if (!textEnabled() || (!(_hideControls & 2)))
timerUpdatePortraitAnimations(1);
- disableSysTimer(2);
+ disableSysTimer(2);
}
void LoLEngine::fadeText() {
@@ -1368,7 +1360,7 @@ void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
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];
@@ -1447,7 +1439,7 @@ bool LoLEngine::characterSays(int track, int charId, bool redraw) {
charId = 0;
}
}
-
+
bool r = snd_playCharacterSpeech(track, charId, 0);
if (r && redraw) {
@@ -1465,7 +1457,7 @@ bool LoLEngine::characterSays(int track, int charId, bool redraw) {
int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex) {
int ch = 0;
bool skipAnim = false;
-
+
if ((charId == -1) || (!(charId & 0x70)))
charId = ch = (charId == 1) ? (_selectedCharacter ? _characters[_selectedCharacter].id : 0) : charId;
else
@@ -1502,7 +1494,7 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str
_updatePortraitSpeechAnimDuration = strlen(str) >> 1;
_updateCharV3 = unk1;
}
-
+
if (script)
snd_playCharacterSpeech(script->stack[script->sp + 2], ch, 0);
else if (paramList)
@@ -1519,7 +1511,7 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str
_txt->printDialogueText(4, str, script, paramList, paramIndex);
_screen->modifyScreenDim(4, 11, 123, 28, 47);
- } else if (mode == 2) {
+ } else if (mode == 2) {
_screen->setScreenDim(4);
_screen->clearDim(4);
_screen->modifyScreenDim(4, 9, 133, 30, 60);
@@ -1536,7 +1528,7 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str
}
void LoLEngine::giveItemToMonster(MonsterInPlay *monster, uint16 item) {
- uint16 *c = &monster->assignedItems;
+ uint16 *c = &monster->assignedItems;
while (*c)
c = &_itemsInPlay[*c].next;
*c = item;
@@ -1567,7 +1559,7 @@ bool LoLEngine::notEnoughMagic(int charNum, int spellNum, int spellLevel) {
return true;
} else if (_spellProperties[spellNum + 1].unkArr[spellLevel] >= _characters[charNum].hitPointsCur) {
_txt->printMessage(2, getLangString(0x4179), _characters[charNum].name);
- return true;
+ return true;
}
return false;
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index ae52627fac..dd1ce58df3 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -127,7 +127,7 @@ struct MonsterInPlay {
uint16 blockPropertyIndex;
uint16 x;
uint16 y;
- int8 level;
+ int8 shiftStep;
uint16 destX;
uint16 destY;
uint8 destDirection;
@@ -306,7 +306,7 @@ private:
void setupTimers();
void enableTimer(int id);
- void timerProcessOpenDoor(int timerNum);
+ void timerProcessDoors(int timerNum);
void timerProcessMonsters(int timerNum);
void timerSub3(int timerNum);
void timerSub4(int timerNum);
@@ -316,6 +316,9 @@ private:
void timerUpdateLampState(int timerNum);
void timerFadeMessageText(int timerNum);
+ static const uint8 _clock2Timers[];
+ static const uint8 _numClock2Timers;
+
// sound
void loadTalkFile(int index);
void snd_playVoiceFile(int track) {}
@@ -530,12 +533,12 @@ private:
int olol_loadLangFile(EMCState *script);
int olol_playSoundEffect(EMCState *script);
int olol_stopTimScript(EMCState *script);
- int olol_playCharacterScriptChat(EMCState *script);
+ int olol_playCharacterScriptChat(EMCState *script);
int olol_loadSoundFile(EMCState *script);
int olol_setPaletteBrightness(EMCState *script);
int olol_printMessage(EMCState *script);
int olol_playDialogueTalkText(EMCState *script);
- int olol_checkForMonsterMode1(EMCState *script);
+ int olol_checkForMonsterMode1(EMCState *script);
int olol_setNextFunc(EMCState *script);
int olol_setDoorState(EMCState *script);
int olol_assignCustomSfx(EMCState *script);
@@ -558,6 +561,7 @@ private:
int tlol_initDialogueSequence(const TIM *tim, const uint16 *param);
int tlol_restoreSceneAfterDialogueSequence(const TIM *tim, const uint16 *param);
int tlol_fadeClearWindow(const TIM *tim, const uint16 *param);
+ int tlol_update(const TIM *tim, const uint16 *param);
int tlol_playDialogueTalkText(const TIM *tim, const uint16 *param);
Common::Array<const TIMOpcode*> _timIngameOpcodes;
@@ -720,11 +724,10 @@ private:
int clickedWallOnlyScript(uint16 block);
int clickedDoorSwitch(uint16 block, uint16 direction);
int clicked6(uint16 block, uint16 direction);
-
+
bool clickedShape(int shapeIndex);
- void openDoorSub1(uint16 block, int unk);
- void openDoorSub2(uint16 block, int unk);
- int _emcDoorState;
+ void processDoorSwitch(uint16 block, int unk);
+ void openCloseDoor(uint16 block, int openClose);
void movePartySmoothScrollBlocked(int speed);
void movePartySmoothScrollUp(int speed);
@@ -737,6 +740,15 @@ private:
int smoothScrollDrawSpecialShape(int pageNum);
void setLF2(int block);
+ struct OpenDoorState {
+ uint16 block;
+ int8 field_2;
+ int8 state;
+ };
+
+ OpenDoorState _openDoorState[3];
+ int _emcDoorState;
+
uint8 *_scrollSceneBuffer;
uint32 _smoothScrollTimer;
int _smoothScrollModeNormal;
@@ -920,7 +932,7 @@ private:
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 drawMonstersAndItems(int block);
void drawMonster(uint16 id);
int getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags);
void recalcItemMonsterPositions(uint16 direction, uint16 itemIndex, LevelBlockProperty *l, bool flag);
@@ -930,13 +942,13 @@ private:
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 w, int h, int flags, int tblValue, bool flip);
int calcDrawingLayerParameters(int srcX, int srcY, int16 &x2, int16 &y2, int16 &w, int16 &h, uint8 *shape, int flip);
-
+
void updateMonster(MonsterInPlay *monster);
void moveMonster(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 walkMonster_s3(uint16 monsterBlock, int direction, int distance, uint16 curBlock);
int walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk);
void walkMonsterGetNextStepCoords(int16 monsterX, int16 monsterY, int &newX, int &newY, uint16 unk);
@@ -953,8 +965,8 @@ private:
const uint16 *_monsterModifiers;
int _monsterModifiersSize;
- const int8 *_monsterLevelOffs;
- int _monsterLevelOffsSize;
+ const int8 *_monsterShiftOffs;
+ int _monsterShiftOffsSize;
const uint8 *_monsterDirFlags;
int _monsterDirFlagsSize;
const int8 *_monsterScaleX;
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 06227d58d9..66cc883667 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -230,7 +230,7 @@ enum kKyraResources {
kLolCharDefsAkshel,
kLolExpRequirements,
kLolMonsterModifiers,
- kLolMonsterLevelOffsets,
+ kLolMonsterShiftOffsets,
kLolMonsterDirFlags,
kLolMonsterScaleY,
kLolMonsterScaleX,
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index 687b6a17cf..3abe72ea60 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -719,7 +719,7 @@ int LoLEngine::clickedDoorSwitch(uint16 block, uint16 direction) {
if (!_emcDoorState) {
delay(15 * _tickLength);
- openDoorSub1(block, 0);
+ processDoorSwitch(block, 0);
}
return 1;
@@ -753,12 +753,76 @@ bool LoLEngine::clickedShape(int shapeIndex) {
return false;
}
-void LoLEngine::openDoorSub1(uint16 block, int unk) {
+void LoLEngine::processDoorSwitch(uint16 block, int unk) {
+ if ((block == _currentBlock) || (_levelBlockProperties[block].itemMonsterIndex & 0x8000))
+ return;
+
+ int s = 0;
+ if (!unk) {
+ for (int i = 0; i < 3; i++) {
+ if (_openDoorState[i].block != block)
+ continue;
+ s = -_openDoorState[i].state;
+ break;
+ }
+ }
+
+ if (s == 0)
+ s = (_wllWallFlags[_levelBlockProperties[block].walls[_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8 ? 0 : 1]] & 1) ? 1 : -1;
+ openCloseDoor(block, s);
}
-void LoLEngine::openDoorSub2(uint16 block, int unk) {
+void LoLEngine::openCloseDoor(uint16 block, int openClose) {
+ int s1 = -1;
+ int s2 = -1;
+
+ int c = (_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8) ? 0 : 1;
+ int v = _levelBlockProperties[block].walls[c];
+ int flg = (openClose == 1) ? 0x10 : (openClose == -1 ? 0x20 : 0);
+
+ if (_wllWallFlags[v] & flg)
+ return;
+
+ for (int i = 0; i < 3; i++) {
+ if (_openDoorState[i].block == block) {
+ s1 = i;
+ break;
+ } else if (_openDoorState[i].block == 0 && s2 == -1) {
+ s2 = i;
+ }
+ }
+ if (s1 != -1 || s2 != -1) {
+ if (s1 == -1)
+ s1 = s2;
+
+ _openDoorState[s1].block = block;
+ _openDoorState[s1].state = openClose;
+ _openDoorState[s1].field_2 = c;
+
+ flg = (-openClose == 1) ? 0x10 : (-openClose == -1 ? 0x20 : 0);
+
+ if (_wllWallFlags[v] & flg) {
+ _levelBlockProperties[block].walls[c] += openClose;
+ _levelBlockProperties[block].walls[c ^ 2] += openClose;
+
+ int snd = (openClose == -1) ? 32 : 31;
+
+ snd_processEnvironmentalSoundEffect(snd, block);
+ if (!checkSceneUpdateNeed(block))
+ updateEnvironmentalSfx(0);
+ }
+
+ enableTimer(0);
+
+ } else {
+ while (!(flg & _wllWallFlags[v]))
+ v += openClose;
+
+ _levelBlockProperties[block].walls[c] = _levelBlockProperties[block].walls[c ^ 2] = v;
+ checkSceneUpdateNeed(block);
+ }
}
void LoLEngine::movePartySmoothScrollBlocked(int speed) {
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index d21494cc85..622332cd3c 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -35,7 +35,7 @@
namespace Kyra {
void LoLEngine::runInitScript(const char *filename, int optionalFunc) {
- _suspendScript = true;
+ _suspendScript = true;
EMCData scriptData;
EMCState scriptState;
memset(&scriptData, 0, sizeof(EMCData));
@@ -449,7 +449,6 @@ int LoLEngine::olol_setUnkArrayVal(EMCState *script) {
int LoLEngine::olol_setGlobalVar(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setGlobalVar(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
- //uint16 a = stackPos(1);
uint16 b = stackPos(2);
switch (stackPos(0)) {
@@ -539,10 +538,10 @@ int LoLEngine::olol_initMonster(EMCState *script) {
uint16 y = 0;
calcCoordinates(x, y, stackPos(0), stackPos(1), stackPos(2));
uint16 w = _monsterProperties[stackPos(4)].maxWidth;
-
+
if (checkBlockBeforeMonsterPlacement(x, y, w, 7, 7))
return -1;
-
+
for (uint8 i = 0; i < 30; i++) {
MonsterInPlay *l = &_monsters[i];
if (l->might || l->mode == 13)
@@ -577,7 +576,7 @@ int LoLEngine::olol_initMonster(EMCState *script) {
for (int ii = 0; ii < 4; ii++)
l->field_2A[ii] = stackPos(7 + ii);
- checkSceneUpdateNeed(l->blockPropertyIndex);
+ checkSceneUpdateNeed(l->blockPropertyIndex);
return i;
}
@@ -648,11 +647,10 @@ int LoLEngine::olol_loadMonsterProperties(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->destX, m->destY, stackPos(1), stackPos(2), stackPos(3));
m->destDirection = stackPos(4) << 1;
-
if (m->x != m->destX || m->y != m->destY)
setMonsterDirection(m, calcMonsterDirection(m->x, m->y, m->destX, m->destY));
}
@@ -954,6 +952,12 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
return 1;
}
+int LoLEngine::tlol_update(const TIM *tim, const uint16 *param) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_update(%p, %p)", (const void*)tim, (const void*)param);
+ update();
+ return 1;
+}
+
int LoLEngine::tlol_playDialogueTalkText(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_playDialogueTalkText(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]);
if (!snd_playCharacterSpeech(param[0], 0, 0) || textEnabled())
@@ -1296,7 +1300,7 @@ void LoLEngine::setupOpcodeTable() {
// 0x08
OpcodeTimUnImpl();
- OpcodeTimUnImpl();
+ OpcodeTim(tlol_update);
OpcodeTimUnImpl();
OpcodeTimUnImpl();
diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp
index b95e95d18f..7180671ec5 100644
--- a/engines/kyra/sprites_lol.cpp
+++ b/engines/kyra/sprites_lol.cpp
@@ -312,7 +312,7 @@ int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth,
int xOffs = 0;
int yOffs = 0;
int flag = 0;
-
+
int r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y), x, y, monsterWidth, testFlag, wallFlag);
if (r)
return r;
@@ -416,7 +416,7 @@ int LoLEngine::calcMonsterSkillLevel(int id, int a) {
return r;
else if (_characters[id].skillLevels[1] <= 7)
return (r- (r >> 2));
-
+
return (r- (r >> 1));
}
@@ -438,7 +438,7 @@ int LoLEngine::checkBlockForWallsAndSufficientSpace(int block, int x, int y, int
uint16 b = _levelBlockProperties[block].itemMonsterIndex;
while (b & 0x8000) {
MonsterInPlay *monster = &_monsters[b & 0x7fff];
-
+
if (monster->mode < 13) {
int r = checkMonsterSpace(x, y, monster->x, monster->y);
if ((monsterWidth + monster->properties->maxWidth) > r)
@@ -460,7 +460,7 @@ bool LoLEngine::checkBlockOccupiedByParty(int x, int y, int testFlag) {
void LoLEngine::drawMonstersAndItems(int block) {
LevelBlockProperty *l = _curBlockCaps[block];
- uint16 s = l->itemMonsterIndex;
+ uint16 s = l->itemMonsterIndex;
ItemInPlay *i = findItem(s);
if (l->direction != _currentDirection) {
@@ -491,7 +491,7 @@ void LoLEngine::drawMonstersAndItems(int block) {
}
void LoLEngine::drawMonster(uint16 id) {
- MonsterInPlay *m = &_monsters[id];
+ MonsterInPlay *m = &_monsters[id];
int16 flg = _monsterDirFlags[(_currentDirection << 2) + m->facing];
int curFrm = getMonsterCurFrame(m, flg & 0xffef);
@@ -505,12 +505,12 @@ void LoLEngine::drawMonster(uint16 id) {
bool flip = m->properties->flags & 0x200 ? true : false;
flg &= 0x10;
uint8 *shp = _monsterShapes[(m->properties->shapeIndex << 4) + curFrm];
-
+
if (m->properties->flags & 0x800)
flg |= 0x20;
uint8 *ovl1 = d ? _monsterPalettes[(m->properties->shapeIndex << 4) + (curFrm & 0x0f)] + (shp[10] * (d - 1)) : 0;
- uint8 *ovl2 = drawItemOrMonster(shp, ovl1, m->x + _monsterLevelOffs[m->level << 1], m->y + _monsterLevelOffs[(m->level << 1) + 1], 0, 0, flg | 1, -1, flip);
+ uint8 *ovl2 = drawItemOrMonster(shp, ovl1, m->x + _monsterShiftOffs[m->shiftStep << 1], m->y + _monsterShiftOffs[(m->shiftStep << 1) + 1], 0, 0, flg | 1, -1, flip);
for (int i = 0; i < 4; i++) {
int v = m->field_2A[i] - 1;
@@ -536,9 +536,9 @@ void LoLEngine::drawMonster(uint16 id) {
int dH = _screen->getShapeScaledHeight(shp, _dmScaleH) >> 1;
int a = (m->mode == 13) ? (m->field_15 << 1) : (m->properties->might / (m->field_1B & 0x7fff));
-
+
shp = _gameShapes[6];
-
+
int cF = m->properties->flags & 0xc000;
if (cF == 0x4000)
cF = 63;
@@ -550,7 +550,7 @@ void LoLEngine::drawMonster(uint16 id) {
cF = 0;
uint8 *tbl = new uint8[256];
- if (cF) {
+ if (cF) {
for (int i = 0; i < 256; i++) {
tbl[i] = i;
if (i < 2 || i > 7)
@@ -772,7 +772,7 @@ uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *table, int x, int y, in
r = 7 - ((r / 3) - 1);
r = CLIP(r, 0, 7);
ovl = _screen->getLevelOverlay(r);
- } else {
+ } else {
memset (tmpOvl + 1, tblValue, 15);
table = tmpOvl;
ovl = _screen->getLevelOverlay(7);
@@ -829,7 +829,7 @@ int LoLEngine::calcDrawingLayerParameters(int x1, int y1, int16 &x2, int16 &y2,
if (flip)
y2 = ((120 - y2) >> 1) + _screen->getShapeScaledHeight(shape, _dmScaleH);
- else
+ else
y2 -= (_screen->getShapeScaledHeight(shape, _dmScaleH) >> 1);
return l;
@@ -868,8 +868,12 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
if ((s & 1) && (monster->flags & 0x10))
setMonsterMode(monster, 7);
- ////
- // TODO
+ if ((monster->mode != 11) && (monster->mode != 14)) {
+ if (!(_rnd.getRandomNumberRng(1, 100) & 3)) {
+ monster->shiftStep = (++monster->shiftStep) & 0x0f;
+ checkSceneUpdateNeed(monster->blockPropertyIndex);
+ }
+ }
switch (monster->mode) {
case 0:
@@ -923,7 +927,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
void LoLEngine::moveMonster(MonsterInPlay *monster) {
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);
+ walkMonster(monster);
} else if (monster->direction != monster->destDirection) {
int i = (monster->facing << 2) + (monster->destDirection >> 1);
setMonsterDirection(monster, turnPos[i]);
@@ -935,7 +939,7 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
return;
int s = walkMonsterCalcNextStep(monster);
-
+
if (s == -1) {
if (walkMonsterCheckDest(monster->x, monster->y, monster, 4) != 1)
return;
@@ -951,7 +955,7 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
return;
}
}
- }
+ }
}
int fx = 0;
@@ -973,7 +977,7 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {
const int8 *tbl = _monsterShiftAlt ? walkMonsterTable2 : walkMonsterTable1;
int sx = monster->x;
- int sy = monster->y;
+ int sy = monster->y;
int s = monster->direction;
int d = calcMonsterDirection(monster->x, monster->y, monster->destX, monster->destY);
@@ -1002,10 +1006,10 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {
continue;
uint8 w = _levelBlockProperties[_monsterCurBlock].walls[(s >> 1) ^ 2];
-
+
if (_wllWallFlags[w] & 0x20) {
if (_wllBuffer3[w] == 5)
- openDoorSub2(_monsterCurBlock, 1);
+ openCloseDoor(_monsterCurBlock, 1);
}
if (_wllWallFlags[w] & 8)
@@ -1017,9 +1021,9 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {
int LoLEngine::getMonsterDistance(uint16 block1, uint16 block2) {
int8 b1x = block1 & 0x1f;
- int8 b1y = (block1 >> 8) & 0x1f;
+ int8 b1y = block1 >> 5;
int8 b2x = block2 & 0x1f;
- int8 b2y = (block2 >> 8) & 0x1f;
+ int8 b2y = block2 >> 5;
uint8 dy = ABS(b2y - b1y);
uint8 dx = ABS(b2x - b1x);
@@ -1030,8 +1034,36 @@ int LoLEngine::getMonsterDistance(uint16 block1, uint16 block2) {
return (dx << 1) + dy;
}
-int LoLEngine::walkMonster_s3(uint16 monsterBlock, int unk1, int unk2, uint16 curBlock) {
- return 0;
+int LoLEngine::walkMonster_s3(uint16 monsterBlock, int direction, int distance, uint16 curBlock) {
+ int mdist = getMonsterDistance(curBlock, monsterBlock);
+
+ if (mdist > distance)
+ return 5;
+
+ int dir = calcMonsterDirection(monsterBlock & 0x1f, monsterBlock >> 5, curBlock & 0x1f, curBlock >> 5);
+ if ((dir & 1) || ((dir << 1) != direction))
+ return 5;
+
+ if (((monsterBlock & 0x1f) != (curBlock & 0x1f)) || ((monsterBlock & 0xffe0) != (curBlock & 0xffe0)))
+ return 5;
+
+ if (distance < 0)
+ return 5;
+
+ for (int i = 0; i < distance; i++) {
+ int p = calcNewBlockPosition(monsterBlock, direction);
+
+ if (p == curBlock)
+ return direction;
+
+ if (_wllWallFlags[_levelBlockProperties[p].walls[direction ^ 2]] & 2)
+ return 5;
+
+ if (_levelBlockProperties[p].itemMonsterIndex & 0x8000)
+ return 5;
+ }
+
+ return 5;
}
int LoLEngine::walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk) {
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 588ce4ac1d..d06957350f 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -391,7 +391,7 @@ bool StaticResource::init() {
{ kLolCharDefsAkshel, kLolRawDataBe16, "CHAKSHEL.DEF" },
{ kLolExpRequirements, kLolRawDataBe32, "EXPERIENCE.DEF" },
{ kLolMonsterModifiers, kLolRawDataBe16, "MONSTMOD.DEF" },
- { kLolMonsterLevelOffsets, kRawData, "MONSTLVL.DEF" },
+ { kLolMonsterShiftOffsets, kRawData, "MONSTLVL.DEF" },
{ kLolMonsterDirFlags, kRawData, "MONSTDIR.DEF" },
{ kLolMonsterScaleY, kRawData, "MONSTZY.DEF" },
{ kLolMonsterScaleX, kRawData, "MONSTZX.DEF" },
@@ -1762,7 +1762,7 @@ void LoLEngine::initStaticResource() {
_charDefsAkshel = _staticres->loadRawDataBe16(kLolCharDefsAkshel, _charDefsAkshelSize);
_expRequirements = (const int32*)_staticres->loadRawDataBe32(kLolExpRequirements, _expRequirementsSize);
_monsterModifiers = _staticres->loadRawDataBe16(kLolMonsterModifiers, _monsterModifiersSize);
- _monsterLevelOffs = (const int8*)_staticres->loadRawData(kLolMonsterLevelOffsets, _monsterLevelOffsSize);
+ _monsterShiftOffs = (const int8*)_staticres->loadRawData(kLolMonsterShiftOffsets, _monsterShiftOffsSize);
_monsterDirFlags = _staticres->loadRawData(kLolMonsterDirFlags, _monsterDirFlagsSize);
_monsterScaleX = (const int8*)_staticres->loadRawData(kLolMonsterScaleX, _monsterScaleXSize);
_monsterScaleY = (const int8*)_staticres->loadRawData(kLolMonsterScaleY, _monsterScaleYSize);
@@ -2988,6 +2988,13 @@ const uint8 LoLEngine::_charInfoFrameTable[] = {
0x8, 0x9, 0xA, 0xB, 0xA, 0x9, 0x8, 0x7
};
+const uint8 LoLEngine::_clock2Timers[] = {
+ 0x00, 0x10, 0x11, 0x03, 0x04, 0x50,
+ 0x51, 0x52, 0x08, 0x09, 0x0A
+};
+
+const uint8 LoLEngine::_numClock2Timers = ARRAYSIZE(LoLEngine::_clock2Timers);
+
#endif // ENABLE_LOL
} // End of namespace Kyra
diff --git a/engines/kyra/timer.cpp b/engines/kyra/timer.cpp
index da7e22f684..88b86393c8 100644
--- a/engines/kyra/timer.cpp
+++ b/engines/kyra/timer.cpp
@@ -108,6 +108,7 @@ void TimerManager::addTimer(uint8 id, TimerFunc *func, int countdown, bool enabl
newTimer.enabled = enabled ? 1 : 0;
newTimer.lastUpdate = newTimer.nextRun = 0;
newTimer.func = func;
+ newTimer.pauseStartTime = 0;
_timers.push_back(newTimer);
}
@@ -217,6 +218,28 @@ uint32 TimerManager::getNextRun(uint8 id) const {
return 0xFFFFFFFF;
}
+void TimerManager::pauseSingleTimer(uint8 id, bool p) {
+ debugC(9, kDebugLevelTimer, "TimerManager::pauseSingleTimer(%d, %d)", id, (int) p);
+ Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
+
+ if (timer == _timers.end()) {
+ warning("TimerManager::pauseSingleTimer: No timer %d", id);
+ return;
+ }
+
+ if (p) {
+ timer->pauseStartTime = _system->getMillis();
+ timer->enabled = 0;
+ } else if (timer->pauseStartTime) {
+ int32 elapsedTime = _system->getMillis() - timer->pauseStartTime;
+ timer->enabled = 1;
+ timer->lastUpdate += elapsedTime;
+ timer->nextRun += elapsedTime;
+ resync();
+ timer->pauseStartTime = 0;
+ }
+}
+
bool TimerManager::isEnabled(uint8 id) const {
debugC(9, kDebugLevelTimer, "TimerManager::isEnabled(%d)", id);
diff --git a/engines/kyra/timer.h b/engines/kyra/timer.h
index 691bac3fb5..3892ecd580 100644
--- a/engines/kyra/timer.h
+++ b/engines/kyra/timer.h
@@ -45,6 +45,8 @@ struct TimerEntry {
uint32 nextRun;
TimerFunc *func;
+
+ uint32 pauseStartTime;
};
class TimerManager {
@@ -70,12 +72,15 @@ public:
void setNextRun(uint8 id, uint32 nextRun);
uint32 getNextRun(uint8 id) const;
+ void pauseSingleTimer(uint8 id, bool p);
+
bool isEnabled(uint8 id) const;
void enable(uint8 id);
void disable(uint8 id);
void loadDataFromFile(Common::SeekableReadStream &file, int version);
void saveDataToFile(Common::WriteStream &file) const;
+
private:
void resync();
diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp
index 39b89416e0..d646b13f0e 100644
--- a/engines/kyra/timer_lol.cpp
+++ b/engines/kyra/timer_lol.cpp
@@ -35,8 +35,8 @@ namespace Kyra {
void LoLEngine::setupTimers() {
debugC(9, kDebugLevelMain | kDebugLevelTimer, "LoLEngine::setupTimers()");
-
- _timer->addTimer(0, TimerV2(timerProcessOpenDoor), 15, true);
+
+ _timer->addTimer(0, TimerV2(timerProcessDoors), 15, true);
_timer->addTimer(0x10, TimerV2(timerProcessMonsters), 6, true);
_timer->addTimer(0x11, TimerV2(timerProcessMonsters), 6, true);
_timer->setNextRun(0x11, _system->getMillis() + 3 * _tickLength);
@@ -56,13 +56,56 @@ void LoLEngine::enableTimer(int id) {
_timer->setNextRun(id, _system->getMillis() + _timer->getDelay(id) * _tickLength);
}
-void LoLEngine::timerProcessOpenDoor(int timerNum) {
+void LoLEngine::enableSysTimer(int sysTimer) {
+ if (sysTimer != 2)
+ return;
+
+ for (int i = 0; i < _numClock2Timers; i++)
+ _timer->pauseSingleTimer(_clock2Timers[i], false);
+}
+
+void LoLEngine::disableSysTimer(int sysTimer) {
+ if (sysTimer != 2)
+ return;
+
+ for (int i = 0; i < _numClock2Timers; i++)
+ _timer->pauseSingleTimer(_clock2Timers[i], true);
+}
+
+void LoLEngine::timerProcessDoors(int timerNum) {
+ for (int i = 0; i < 3; i++) {
+ uint16 b = _openDoorState[i].block;
+ if (!b)
+ continue;
+ int v = _openDoorState[i].state;
+ int c = _openDoorState[i].field_2;
+
+ _levelBlockProperties[b].walls[c] += v;
+ _levelBlockProperties[b].walls[c ^ 2] += v;
+
+ int snd = 31;
+
+ int flg = _wllWallFlags[_levelBlockProperties[b].walls[c]];
+ if (flg & 0x20)
+ snd = 33;
+ else if (v == -1)
+ snd = 32;
+
+ if (!(_updateFlags & 1)) {
+ snd_processEnvironmentalSoundEffect(snd, b);
+ if (!checkSceneUpdateNeed(b))
+ updateEnvironmentalSfx(0);
+ }
+
+ if (flg & 0x30)
+ _openDoorState[i].block = 0;
+ }
}
void LoLEngine::timerProcessMonsters(int timerNum) {
- //if (!_updateMonsters)
- // return;
+// if (!_updateMonsters)
+// return;
for (int i = timerNum & 0x0f; i < 30; i += 2)
updateMonster(&_monsters[i]);