From 8639e34b41a22336301bff08827dfc7f0988424c Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 6 Mar 2009 22:53:08 +0000 Subject: LOL: - doors can now be opened and closed - some more work on monster walk code svn-id: r39166 --- engines/kyra/lol.cpp | 36 ++++++++------------ engines/kyra/lol.h | 38 ++++++++++++++------- engines/kyra/resource.h | 2 +- engines/kyra/scene_lol.cpp | 70 ++++++++++++++++++++++++++++++++++++-- engines/kyra/script_lol.cpp | 20 ++++++----- engines/kyra/sprites_lol.cpp | 80 +++++++++++++++++++++++++++++++------------- engines/kyra/staticres.cpp | 11 ++++-- engines/kyra/timer.cpp | 23 +++++++++++++ engines/kyra/timer.h | 5 +++ engines/kyra/timer_lol.cpp | 53 ++++++++++++++++++++++++++--- 10 files changed, 260 insertions(+), 78 deletions(-) (limited to 'engines/kyra') 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 _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]); -- cgit v1.2.3