diff options
Diffstat (limited to 'engines/kyra/timer.cpp')
-rw-r--r-- | engines/kyra/timer.cpp | 393 |
1 files changed, 176 insertions, 217 deletions
diff --git a/engines/kyra/timer.cpp b/engines/kyra/timer.cpp index a35b701697..dff191cbe0 100644 --- a/engines/kyra/timer.cpp +++ b/engines/kyra/timer.cpp @@ -11,7 +11,7 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License @@ -24,269 +24,228 @@ */ #include "kyra/kyra.h" -#include "kyra/screen.h" -#include "kyra/animator.h" +#include "kyra/timer.h" -#include "common/system.h" +#include "common/func.h" +#include "common/savefile.h" namespace Kyra { -void KyraEngine::setupTimers() { - debugC(9, kDebugLevelMain, "KyraEngine::setupTimers()"); - memset(_timers, 0, sizeof(_timers)); - - for (int i = 0; i < 34; i++) - _timers[i].active = 1; - - _timers[0].func = _timers[1].func = _timers[2].func = _timers[3].func = _timers[4].func = 0; //Unused. - _timers[5].func = _timers[6].func = _timers[7].func = _timers[8].func = _timers[9].func = 0; //_nullsub51; - _timers[10].func = _timers[11].func = _timers[12].func = _timers[13].func = 0; //_nullsub50; - _timers[14].func = &KyraEngine::timerCheckAnimFlag2; //_nullsub52; - _timers[15].func = &KyraEngine::timerUpdateHeadAnims; //_nullsub48; - _timers[16].func = &KyraEngine::timerSetFlags1; //_nullsub47; - _timers[17].func = 0; //sub_15120; - _timers[18].func = &KyraEngine::timerCheckAnimFlag1; //_nullsub53; - _timers[19].func = &KyraEngine::timerRedrawAmulet; //_nullsub54; - _timers[20].func = 0; //offset _timerDummy1 - _timers[21].func = 0; //sub_1517C; - _timers[22].func = 0; //offset _timerDummy2 - _timers[23].func = 0; //offset _timerDummy3, - _timers[24].func = 0; //_nullsub45; - _timers[25].func = 0; //offset _timerDummy4 - _timers[26].func = 0; //_nullsub46; - _timers[27].func = 0; //offset _timerDummy5, - _timers[28].func = 0; //offset _timerDummy6 - _timers[29].func = 0; //offset _timerDummy7, - _timers[30].func = 0; //offset _timerDummy8, - _timers[31].func = &KyraEngine::timerFadeText; //sub_151F8; - _timers[32].func = &KyraEngine::updateAnimFlag1; //_nullsub61; - _timers[33].func = &KyraEngine::updateAnimFlag2; //_nullsub62; - - _timers[0].countdown = _timers[1].countdown = _timers[2].countdown = _timers[3].countdown = _timers[4].countdown = -1; - _timers[5].countdown = 5; - _timers[6].countdown = 7; - _timers[7].countdown = 8; - _timers[8].countdown = 9; - _timers[9].countdown = 7; - _timers[10].countdown = _timers[11].countdown = _timers[12].countdown = _timers[13].countdown = 420; - _timers[14].countdown = 600; - _timers[15].countdown = 11; - _timers[16].countdown = _timers[17].countdown = 7200; - _timers[18].countdown = _timers[19].countdown = 600; - _timers[20].countdown = 7200; - _timers[21].countdown = 18000; - _timers[22].countdown = 7200; - _timers[23].countdown = _timers[24].countdown = _timers[25].countdown = _timers[26].countdown = _timers[27].countdown = 10800; - _timers[28].countdown = 21600; - _timers[29].countdown = 7200; - _timers[30].countdown = 10800; - _timers[31].countdown = -1; - _timers[32].countdown = 9; - _timers[33].countdown = 3; -} - -void KyraEngine::updateGameTimers() { - debugC(9, kDebugLevelMain, "KyraEngine::updateGameTimers()"); - - if (_system->getMillis() < _timerNextRun) - return; - _timerNextRun += 99999; - - for (int i = 0; i < 34; i++) { - if (_timers[i].active && _timers[i].countdown > -1) { - if (_timers[i].nextRun <=_system->getMillis()) { - if (i > 4 && _timers[i].func) - (*this.*_timers[i].func)(i); - - _timers[i].nextRun = _system->getMillis() + _timers[i].countdown * _tickLength; - } +namespace { +struct TimerResync : public Common::UnaryFunction<TimerEntry&, void> { + uint32 _tickLength, _curTime; + TimerResync(KyraEngine *vm, uint32 curTime) : _tickLength(vm->tickLength()), _curTime(curTime) {} + + void operator()(TimerEntry &entry) const { + if (entry.lastUpdate < 0) { + if ((entry.lastUpdate + _curTime) <= 0) + entry.nextRun = 0; + else + entry.nextRun = _curTime + entry.lastUpdate + entry.countdown * _tickLength; + } else { + uint32 nextRun = entry.lastUpdate + entry.countdown * _tickLength; + if (_curTime < nextRun) + nextRun = 0; + entry.nextRun = nextRun; } - if (_timers[i].nextRun < _timerNextRun) - _timerNextRun = _timers[i].nextRun; } -} - -void KyraEngine::clearNextEventTickCount() { - debugC(9, kDebugLevelMain, "KyraEngine::clearNextEventTickCount()"); - _timerNextRun = 0; -} +}; -void KyraEngine::setTimerDelay(uint8 timer, int32 countdown) { - debugC(9, kDebugLevelMain, "KyraEngine::setTimerDelay(%i, %d)", timer, countdown); - _timers[timer].countdown = countdown; -} +struct TimerEqual : public Common::UnaryFunction<const TimerEntry&, bool> { + uint8 _id; + + TimerEqual(uint8 id) : _id(id) {} -int16 KyraEngine::getTimerDelay(uint8 timer) { - debugC(9, kDebugLevelMain, "KyraEngine::getTimerDelay(%i)", timer); - return _timers[timer].countdown; -} + bool operator()(const TimerEntry &entry) const { + return entry.id == _id; + } +}; +} // end of anonymous namespace -void KyraEngine::setTimerCountdown(uint8 timer, int32 countdown) { - debugC(9, kDebugLevelMain, "KyraEngine::setTimerCountdown(%i, %i)", timer, countdown); - _timers[timer].countdown = countdown; - _timers[timer].nextRun = _system->getMillis() + countdown * _tickLength; +void TimerManager::reset() { + for (Iterator pos = _timers.begin(); pos != _timers.end(); ++pos) { + delete pos->func; + } - uint32 nextRun = _system->getMillis() + countdown * _tickLength; - if (nextRun < _timerNextRun) - _timerNextRun = nextRun; + _timers.clear(); } -void KyraEngine::enableTimer(uint8 timer) { - debugC(9, kDebugLevelMain, "KyraEngine::enableTimer(%i)", timer); - _timers[timer].active = 1; -} +void TimerManager::addTimer(uint8 id, TimerFunc *func, int countdown, bool enabled) { + debugC(9, kDebugLevelTimer, "TimerManager::addTimer(%d, %p, %d, %d)", id, (const void*)func, countdown, enabled); -void KyraEngine::disableTimer(uint8 timer) { - debugC(9, kDebugLevelMain, "KyraEngine::disableTimer(%i)", timer); - _timers[timer].active = 0; + TimerEntry newTimer; + + newTimer.id = id; + newTimer.countdown = countdown; + newTimer.enabled = enabled ? 1 : 0; + newTimer.lastUpdate = newTimer.nextRun = 0; + newTimer.func = func; + + _timers.push_back(newTimer); } -void KyraEngine::timerUpdateHeadAnims(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerUpdateHeadAnims(%i)", timerNum); - static int8 currentFrame = 0; - static const int8 frameTable[] = {4, 5, 4, 5, 4, 5, 0, 1, 4, 5, - 4, 4, 6, 4, 8, 1, 9, 4, -1}; +void TimerManager::update() { + debugC(9, kDebugLevelTimer, "TimerManager::update()"); - if (_talkingCharNum < 0) + if (_system->getMillis() < _nextRun) return; + + _nextRun += 99999; + + for (Iterator pos = _timers.begin(); pos != _timers.end(); ++pos) { + if (pos->enabled && pos->countdown >= 0 && pos->nextRun <= _system->getMillis()) { + if (pos->func && *pos->func) + (*pos->func)(pos->id); + + uint32 curTime = _system->getMillis(); + pos->lastUpdate = curTime; + pos->nextRun = curTime + pos->countdown * _vm->tickLength(); + + _nextRun = MIN(_nextRun, pos->nextRun); + } + } +} - _currHeadShape = frameTable[currentFrame]; - currentFrame++; +void TimerManager::resync() { + debugC(9, kDebugLevelTimer, "TimerManager::resync()"); - if (frameTable[currentFrame] == -1) - currentFrame = 0; + _nextRun = 0; // force rerun + Common::for_each(_timers.begin(), _timers.end(), TimerResync(_vm, _system->getMillis())); +} - _animator->animRefreshNPC(0); - _animator->animRefreshNPC(_talkingCharNum); +void TimerManager::resetNextRun() { + debugC(9, kDebugLevelTimer, "TimerManager::resetNextRun()"); + _nextRun = 0; } -void KyraEngine::timerSetFlags1(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerSetFlags(%i)", timerNum); - if (_currentCharacter->sceneId == 0x1C) - return; +void TimerManager::setCountdown(uint8 id, int32 countdown) { + debugC(9, kDebugLevelTimer, "TimerManager::setCountdown(%d, %d)", id, countdown); - int rndNr = _rnd.getRandomNumberRng(0, 3); + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) { + timer->countdown = countdown; - for (int i = 0; i < 4; i++) { - if (!queryGameFlag(rndNr + 17)) { - setGameFlag(rndNr + 17); - break; - } else { - rndNr++; - if (rndNr > 3) - rndNr = 0; + if (countdown >= 0) { + uint32 curTime = _system->getMillis(); + timer->lastUpdate = curTime; + timer->nextRun = curTime + countdown * _vm->tickLength(); + + _nextRun = MIN(_nextRun, timer->nextRun); } + } else { + warning("TimerManager::setCountdown: No timer %d", id); } } -void KyraEngine::timerFadeText(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerFadeText(%i)", timerNum); - _fadeText = true; -} +void TimerManager::setDelay(uint8 id, int32 countdown) { + debugC(9, kDebugLevelTimer, "TimerManager::setDelay(%d, %d)", id, countdown); -void KyraEngine::updateAnimFlag1(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::updateAnimFlag1(%d)", timerNum); - if (_brandonStatusBit & 2) { - _brandonStatusBit0x02Flag = 1; - } + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) + timer->countdown = countdown; + else + warning("TimerManager::setDelay: No timer %d", id); } -void KyraEngine::updateAnimFlag2(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::updateAnimFlag2(%d)", timerNum); - if (_brandonStatusBit & 0x20) { - _brandonStatusBit0x20Flag = 1; - } -} +int32 TimerManager::getDelay(uint8 id) const { + debugC(9, kDebugLevelTimer, "TimerManager::getDelay(%d)", id); -void KyraEngine::setTextFadeTimerCountdown(int16 countdown) { - debugC(9, kDebugLevelMain, "KyraEngine::setTextFadeTimerCountdown(%i)", countdown); - //if (countdown == -1) - //countdown = 32000; + CIterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) + return timer->countdown; - setTimerCountdown(31, countdown*60); + warning("TimerManager::getDelay: No timer %d", id); + return -1; } -void KyraEngine::timerSetFlags2(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerSetFlags2(%i)", timerNum); - if (!((uint32*)(_flagsTable+0x2D))[timerNum]) - ((uint32*)(_flagsTable+0x2D))[timerNum] = 1; -} +bool TimerManager::isEnabled(uint8 id) const { + debugC(9, kDebugLevelTimer, "TimerManager::isEnabled(%d)", id); -void KyraEngine::timerCheckAnimFlag1(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerCheckAnimFlag1(%i)", timerNum); - if (_brandonStatusBit & 0x20) { - checkAmuletAnimFlags(); - setTimerCountdown(18, -1); - } -} + CIterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) + return (timer->enabled == 1); -void KyraEngine::timerCheckAnimFlag2(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerCheckAnimFlag1(%i)", timerNum); - if (_brandonStatusBit & 0x2) { - checkAmuletAnimFlags(); - setTimerCountdown(14, -1); - } + warning("TimerManager::isEnabled: No timer %d", id); + return false; } -void KyraEngine::checkAmuletAnimFlags() { - debugC(9, kDebugLevelMain, "KyraEngine::checkSpecialAnimFlags()"); - if (_brandonStatusBit & 2) { - seq_makeBrandonNormal2(); - setTimerCountdown(19, 300); - } - - if (_brandonStatusBit & 0x20) { - seq_makeBrandonNormal(); - setTimerCountdown(19, 300); - } -} +void TimerManager::enable(uint8 id) { + debugC(9, kDebugLevelTimer, "TimerManager::enable(%d)", id); -void KyraEngine::timerRedrawAmulet(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerRedrawAmulet(%i)", timerNum); - if (queryGameFlag(0xF1)) { - drawAmulet(); - setTimerCountdown(19, -1); - } + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) + timer->enabled = 1; + else + warning("TimerManager::enable: No timer %d", id); } -void KyraEngine::drawAmulet() { - debugC(9, kDebugLevelMain, "KyraEngine::drawAmulet()"); - static const int16 amuletTable1[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x150, 0x155, 0x15A, 0x15F, 0x164, 0x145, -1}; - static const int16 amuletTable3[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x14F, 0x154, 0x159, 0x15E, 0x163, 0x144, -1}; - static const int16 amuletTable2[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x152, 0x157, 0x15C, 0x161, 0x166, 0x147, -1}; - static const int16 amuletTable4[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x151, 0x156, 0x15B, 0x160, 0x165, 0x146, -1}; +void TimerManager::disable(uint8 id) { + debugC(9, kDebugLevelTimer, "TimerManager::disable(%d)", id); - resetGameFlag(0xF1); - _screen->hideMouse(); - - int i = 0; - while (amuletTable1[i] != -1) { - if (queryGameFlag(87)) - _screen->drawShape(0, _shapes[amuletTable1[i]], _amuletX[0], _amuletY[0], 0, 0); - - if (queryGameFlag(89)) - _screen->drawShape(0, _shapes[amuletTable2[i]], _amuletX[1], _amuletY[1], 0, 0); - - if (queryGameFlag(86)) - _screen->drawShape(0, _shapes[amuletTable3[i]], _amuletX[2], _amuletY[2], 0, 0); - - if (queryGameFlag(88)) - _screen->drawShape(0, _shapes[amuletTable4[i]], _amuletX[3], _amuletY[3], 0, 0); + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) + timer->enabled = 0; + else + warning("TimerManager::disable: No timer %d", id); +} - _screen->updateScreen(); - delayWithTicks(3); - i++; +void TimerManager::loadDataFromFile(Common::InSaveFile *file, int version) { + debugC(9, kDebugLevelTimer, "TimerManager::loadDataFromFile(%p, %d)", (const void*)file, version); + + if (version <= 7) { + _nextRun = 0; + for (int i = 0; i < 32; ++i) { + uint8 enabled = file->readByte(); + int32 countdown = file->readSint32BE(); + uint32 nextRun = file->readUint32BE(); + + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(i)); + if (timer != _timers.end()) { + timer->enabled = enabled; + timer->countdown = countdown; + + if (nextRun) { + timer->nextRun = nextRun + _system->getMillis(); + timer->lastUpdate = timer->nextRun - countdown * _vm->tickLength(); + } else { + uint32 curTime = _system->getMillis(); + timer->nextRun = curTime; + timer->lastUpdate = curTime - countdown * _vm->tickLength(); + } + } else { + warning("Loading timer data for non existing timer %d", i); + } + } + } else { + int entries = file->readByte(); + for (int i = 0; i < entries; ++i) { + uint8 id = file->readByte(); + + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) { + timer->enabled = file->readByte(); + timer->countdown = file->readSint32BE(); + timer->lastUpdate = file->readSint32BE(); + } else { + warning("Loading timer data for non existing timer %d", id); + file->seek(7, SEEK_CUR); + } + } + + resync(); } - _screen->showMouse(); } -void KyraEngine::setWalkspeed(uint8 newSpeed) { - debugC(9, kDebugLevelMain, "KyraEngine::setWalkspeed(%i)", newSpeed); - static const uint8 speeds[] = {11, 9, 6, 5, 3}; - - assert(newSpeed < ARRAYSIZE(speeds)); - setTimerDelay(5, speeds[newSpeed]); +void TimerManager::saveDataToFile(Common::OutSaveFile *file) const { + debugC(9, kDebugLevelTimer, "TimerManager::saveDataToFile(%p)", (const void*)file); + + file->writeByte(count()); + for (CIterator pos = _timers.begin(); pos != _timers.end(); ++pos) { + file->writeByte(pos->id); + file->writeByte(pos->enabled); + file->writeSint32BE(pos->countdown); + file->writeSint32BE(pos->lastUpdate - _system->getMillis()); + } } } // end of namespace Kyra - |