aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/timer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/kyra/timer.cpp')
-rw-r--r--engines/kyra/timer.cpp393
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
-