MOHAWK: Switch timers to script commands

This commit is contained in:
Bastien Bouclet 2017-07-01 22:44:22 +02:00 committed by Eugene Sandulenko
parent ee70244fbf
commit ea303ab682
11 changed files with 101 additions and 62 deletions

View File

@ -72,8 +72,6 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
DebugMan.addDebugChannel(kRivenDebugScript, "Script", "Track Script Execution");
removeTimer();
// NOTE: We can never really support CD swapping. All of the music files
// (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive
// during install and used from there. The same goes for the extras.mhk
@ -195,7 +193,6 @@ Common::Error MohawkEngine_Riven::run() {
void MohawkEngine_Riven::doFrame() {
// Update background running things
checkTimer();
_sound->updateSLST();
_video->updateMovies();
@ -425,7 +422,7 @@ void MohawkEngine_Riven::changeToCard(uint16 dest) {
void MohawkEngine_Riven::refreshCard() {
// Clear any timer still floating around
removeTimer();
_stack->removeTimer();
_card->enter(true);
@ -471,27 +468,6 @@ Common::Error MohawkEngine_Riven::saveGameState(int slot, const Common::String &
return _saveLoad->saveGame(slot, desc);
}
void MohawkEngine_Riven::installTimer(TimerProc *proc, uint32 time) {
removeTimer();
_timerProc = Common::SharedPtr<TimerProc>(proc);
_timerTime = time + getTotalPlayTime();
}
void MohawkEngine_Riven::checkTimer() {
if (!_timerProc)
return;
// NOTE: If the specified timer function is called, it is its job to remove the timer!
if (getTotalPlayTime() >= _timerTime) {
(*_timerProc)();
}
}
void MohawkEngine_Riven::removeTimer() {
_timerProc.reset();
_timerTime = 0;
}
void MohawkEngine_Riven::addZipVisitedCard(uint16 cardId, uint16 cardNameId) {
Common::String cardName = getStack()->getName(kCardNames, cardNameId);
if (cardName.empty())

View File

@ -99,11 +99,6 @@ public:
Common::Error saveGameState(int slot, const Common::String &desc);
bool hasFeature(EngineFeature f) const;
typedef Common::Functor0<void> TimerProc;
#define TIMER(cls, method) \
new Common::Functor0Mem<void, cls>(this, &cls::method)
void doFrame();
private:
@ -123,10 +118,6 @@ private:
// Variables
void initVars();
// Timer
Common::SharedPtr<TimerProc> _timerProc;
uint32 _timerTime;
void pauseEngineIntern(bool) override;
public:
// Stack/card/script funtions
@ -153,11 +144,6 @@ public:
bool _activatedSLST;
void runLoadDialog();
void delay(uint32 ms);
// Timer
void installTimer(TimerProc *proc, uint32 time);
void checkTimer();
void removeTimer();
};
} // End of namespace Mohawk

View File

@ -817,4 +817,19 @@ void RivenStackChangeCommand::dump(byte tabs) {
debugN("changeStack(%d, %d);\n", _stackId, _cardId);
}
RivenTimerCommand::RivenTimerCommand(MohawkEngine_Riven *vm, const Common::SharedPtr<RivenStack::TimerProc> &timerProc) :
RivenCommand(vm),
_timerProc(timerProc) {
}
void RivenTimerCommand::execute() {
(*_timerProc)();
}
void RivenTimerCommand::dump(byte tabs) {
printTabs(tabs);
debugN("doTimer();\n");
}
} // End of namespace Mohawk

View File

@ -23,6 +23,8 @@
#ifndef RIVEN_SCRIPTS_H
#define RIVEN_SCRIPTS_H
#include "mohawk/riven_stack.h"
#include "common/str-array.h"
#include "common/ptr.h"
#include "common/textconsole.h"
@ -91,6 +93,7 @@ enum RivenCommandType {
class MohawkEngine_Riven;
class RivenCommand;
class RivenScript;
class RivenScriptManager;
struct MLSTRecord;
typedef Common::SharedPtr<RivenScript> RivenScriptPtr;
@ -362,6 +365,18 @@ private:
bool _byStackId; // Otherwise by stack name id
};
class RivenTimerCommand : public RivenCommand {
public:
RivenTimerCommand(MohawkEngine_Riven *vm, const Common::SharedPtr<RivenStack::TimerProc> &timerProc);
// RivenCommand API
virtual void dump(byte tabs) override;
virtual void execute() override;
private:
Common::SharedPtr<RivenStack::TimerProc> _timerProc;
};
} // End of namespace Mohawk
#undef DECLARE_OPCODE

View File

@ -40,6 +40,8 @@ RivenStack::RivenStack(MohawkEngine_Riven *vm, uint16 id) :
_id(id),
_mouseIsDown(false),
_keyPressed(Common::KEYCODE_INVALID) {
removeTimer();
loadResourceNames();
loadCardIdMap();
setCurrentStackVariable();
@ -282,6 +284,8 @@ void RivenStack::onFrame() {
return;
}
checkTimer();
_vm->_gfx->updateEffects();
RivenScriptPtr script(new RivenScript());
@ -315,6 +319,33 @@ Common::Point RivenStack::getMouseDragStartPosition() const {
return _mouseDragStartPosition;
}
void RivenStack::installTimer(TimerProc *proc, uint32 time) {
removeTimer();
_timerProc = Common::SharedPtr<TimerProc>(proc);
_timerTime = time + _vm->getTotalPlayTime();
}
void RivenStack::checkTimer() {
if (!_timerProc) {
return;
}
// NOTE: If the specified timer function is called, it is its job to remove the timer!
// Timers are queued as script commands so that they don't run when the doFrame method
// is called from an inner game loop.
if (_vm->getTotalPlayTime() >= _timerTime) {
RivenScriptPtr script = _vm->_scriptMan->createScriptWithCommand(
new RivenTimerCommand(_vm, _timerProc));
_vm->_scriptMan->runScript(script, true);
}
}
void RivenStack::removeTimer() {
_timerProc.reset();
_timerTime = 0;
}
RivenNameList::RivenNameList() {
}

View File

@ -81,6 +81,8 @@ public:
RivenStack(MohawkEngine_Riven *vm, uint16 id);
virtual ~RivenStack();
typedef Common::Functor0<void> TimerProc;
/** Get the id of the stack */
uint16 getId() const;
@ -112,6 +114,9 @@ public:
/** Install a timer for the current card if one is defined */
virtual void installCardTimer();
/** Clear any currently installed timer */
void removeTimer();
/** Handle a mouse down event */
void onMouseDown(const Common::Point &mouse);
@ -162,6 +167,9 @@ protected:
/** Register an external command for use by the scripts */
void registerCommand(const Common::String &name, ExternalCommand *command);
/** Register a proc for planned execution */
void installTimer(TimerProc *proc, uint32 time);
private:
typedef Common::HashMap<Common::String, Common::SharedPtr<ExternalCommand>, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CommandsMap;
@ -170,9 +178,13 @@ private:
#method, new Common::Functor2Mem<uint16, uint16 *, void, cls>(this, &cls::method) \
)
#define TIMER(cls, method) \
new Common::Functor0Mem<void, cls>(this, &cls::method)
void loadResourceNames();
void loadCardIdMap();
void setCurrentStackVariable();
void checkTimer();
uint16 _id;
@ -192,6 +204,10 @@ private:
bool _mouseIsDown;
Common::Point _mousePosition;
Common::Point _mouseDragStartPosition;
// Timer
Common::SharedPtr<TimerProc> _timerProc;
uint32 _timerTime;
};
namespace RivenStacks {

View File

@ -282,7 +282,7 @@ void BSpit::xbupdateboiler(uint16 argc, uint16 *argv) {
void BSpit::ytramTrapTimer() {
// Remove this timer
_vm->removeTimer();
removeTimer();
// Check if we've caught a Ytram
checkYtramCatch(true);
@ -296,7 +296,7 @@ void BSpit::xbsettrap(uint16 argc, uint16 *argv) {
_vm->_vars["bytramtime"] = timeUntilCatch + _vm->getTotalPlayTime();
// And set the timer too
_vm->installTimer(TIMER(BSpit, ytramTrapTimer), timeUntilCatch);
installTimer(TIMER(BSpit, ytramTrapTimer), timeUntilCatch);
}
void BSpit::checkYtramCatch(bool playSound) {
@ -307,7 +307,7 @@ void BSpit::checkYtramCatch(bool playSound) {
// If the trap still has not gone off, reinstall our timer
// This is in case you set the trap, walked away, and returned
if (_vm->getTotalPlayTime() < ytramTime) {
_vm->installTimer(TIMER(BSpit, ytramTrapTimer), ytramTime - _vm->getTotalPlayTime());
installTimer(TIMER(BSpit, ytramTrapTimer), ytramTime - _vm->getTotalPlayTime());
return;
}

View File

@ -425,7 +425,7 @@ void GSpit::catherineViewerIdleTimer() {
video->play();
// Reset the timer
_vm->installTimer(TIMER(GSpit, catherineViewerIdleTimer), video->getDuration() + _vm->_rnd->getRandomNumber(60) * 1000);
installTimer(TIMER(GSpit, catherineViewerIdleTimer), video->getDuration() + _vm->_rnd->getRandomNumber(60) * 1000);
}
void GSpit::xglview_prisonon(uint16 argc, uint16 *argv) {
@ -473,7 +473,7 @@ void GSpit::xglview_prisonon(uint16 argc, uint16 *argv) {
}
// Create the timer for the next video
_vm->installTimer(TIMER(GSpit, catherineViewerIdleTimer), timeUntilNextMovie);
installTimer(TIMER(GSpit, catherineViewerIdleTimer), timeUntilNextMovie);
}
void GSpit::xglview_prisonoff(uint16 argc, uint16 *argv) {
@ -483,7 +483,7 @@ void GSpit::xglview_prisonoff(uint16 argc, uint16 *argv) {
_vm->_vars["glview"] = 0;
// Remove the timer we set in xglview_prisonon()
_vm->removeTimer();
removeTimer();
// Play the 'turn off' movie after stopping any videos still playing
_vm->_video->closeVideos();

View File

@ -570,7 +570,7 @@ void JSpit::sunnersPlayVideo(RivenVideo *video, uint32 destCardGlobalId, bool su
void JSpit::sunnersTopStairsTimer() {
// If the sunners are gone, we have no video to play
if (_vm->_vars["jsunners"] != 0) {
_vm->removeTimer();
removeTimer();
return;
}
@ -595,13 +595,13 @@ void JSpit::sunnersTopStairsTimer() {
sunnerTime = timerTime + _vm->getTotalPlayTime();
}
_vm->installTimer(TIMER(JSpit, sunnersTopStairsTimer), timerTime);
installTimer(TIMER(JSpit, sunnersTopStairsTimer), timerTime);
}
void JSpit::sunnersMidStairsTimer() {
// If the sunners are gone, we have no video to play
if (_vm->_vars["jsunners"] != 0) {
_vm->removeTimer();
removeTimer();
return;
}
@ -634,13 +634,13 @@ void JSpit::sunnersMidStairsTimer() {
sunnerTime = timerTime + _vm->getTotalPlayTime();
}
_vm->installTimer(TIMER(JSpit, sunnersMidStairsTimer), timerTime);
installTimer(TIMER(JSpit, sunnersMidStairsTimer), timerTime);
}
void JSpit::sunnersLowerStairsTimer() {
// If the sunners are gone, we have no video to play
if (_vm->_vars["jsunners"] != 0) {
_vm->removeTimer();
removeTimer();
return;
}
@ -665,13 +665,13 @@ void JSpit::sunnersLowerStairsTimer() {
sunnerTime = timerTime + _vm->getTotalPlayTime();
}
_vm->installTimer(TIMER(JSpit, sunnersLowerStairsTimer), timerTime);
installTimer(TIMER(JSpit, sunnersLowerStairsTimer), timerTime);
}
void JSpit::sunnersBeachTimer() {
// If the sunners are gone, we have no video to play
if (_vm->_vars["jsunners"] != 0) {
_vm->removeTimer();
removeTimer();
return;
}
@ -700,7 +700,7 @@ void JSpit::sunnersBeachTimer() {
sunnerTime = timerTime + _vm->getTotalPlayTime();
}
_vm->installTimer(TIMER(JSpit, sunnersBeachTimer), timerTime);
installTimer(TIMER(JSpit, sunnersBeachTimer), timerTime);
}
void JSpit::xjschool280_resetleft(uint16 argc, uint16 *argv) {
@ -786,16 +786,16 @@ void JSpit::xjatboundary(uint16 argc, uint16 *argv) {
void JSpit::installCardTimer() {
switch (getCurrentCardGlobalId()) {
case 0x77d6: // Sunners, top of stairs
_vm->installTimer(TIMER(JSpit, sunnersTopStairsTimer), 500);
installTimer(TIMER(JSpit, sunnersTopStairsTimer), 500);
break;
case 0x79bd: // Sunners, middle of stairs
_vm->installTimer(TIMER(JSpit, sunnersMidStairsTimer), 500);
installTimer(TIMER(JSpit, sunnersMidStairsTimer), 500);
break;
case 0x7beb: // Sunners, bottom of stairs
_vm->installTimer(TIMER(JSpit, sunnersLowerStairsTimer), 500);
installTimer(TIMER(JSpit, sunnersLowerStairsTimer), 500);
break;
case 0xb6ca: // Sunners, shoreline
_vm->installTimer(TIMER(JSpit, sunnersBeachTimer), 500);
installTimer(TIMER(JSpit, sunnersBeachTimer), 500);
break;
default:
RivenStack::installCardTimer();

View File

@ -80,7 +80,7 @@ void PSpit::catherineIdleTimer() {
_vm->_vars["pcathtime"] = timeUntilNextMovie + _vm->getTotalPlayTime();
_vm->installTimer(TIMER(PSpit, catherineIdleTimer), timeUntilNextMovie);
installTimer(TIMER(PSpit, catherineIdleTimer), timeUntilNextMovie);
}
void PSpit::xpisland990_elevcombo(uint16 argc, uint16 *argv) {
@ -131,7 +131,7 @@ void PSpit::installCardTimer() {
if (getCurrentCardGlobalId() == 0x3a85) {
// Top of elevator on prison island
// Handle Catherine hardcoded videos
_vm->installTimer(TIMER(PSpit, catherineIdleTimer), _vm->_rnd->getRandomNumberRng(1, 33) * 1000);
installTimer(TIMER(PSpit, catherineIdleTimer), _vm->_rnd->getRandomNumberRng(1, 33) * 1000);
} else {
RivenStack::installCardTimer();
}

View File

@ -76,7 +76,7 @@ void RSpit::rebelPrisonWindowTimer() {
_vm->_vars["rvillagetime"] = timeUntilNextVideo + _vm->getTotalPlayTime();
// Reinstall this timer with the new time
_vm->installTimer(TIMER(RSpit, rebelPrisonWindowTimer), timeUntilNextVideo);
installTimer(TIMER(RSpit, rebelPrisonWindowTimer), timeUntilNextVideo);
}
void RSpit::xrwindowsetup(uint16 argc, uint16 *argv) {
@ -86,7 +86,7 @@ void RSpit::xrwindowsetup(uint16 argc, uint16 *argv) {
// If we have time leftover from a previous run, set up the timer again
if (_vm->getTotalPlayTime() < villageTime) {
_vm->installTimer(TIMER(RSpit, rebelPrisonWindowTimer), villageTime - _vm->getTotalPlayTime());
installTimer(TIMER(RSpit, rebelPrisonWindowTimer), villageTime - _vm->getTotalPlayTime());
return;
}
@ -109,7 +109,7 @@ void RSpit::xrwindowsetup(uint16 argc, uint16 *argv) {
// the timer to reinstall itself...
// Install our timer and we're on our way
_vm->installTimer(TIMER(RSpit, rebelPrisonWindowTimer), timeUntilNextVideo);
installTimer(TIMER(RSpit, rebelPrisonWindowTimer), timeUntilNextVideo);
}