diff --git a/engines/stark/resources/anim.cpp b/engines/stark/resources/anim.cpp index a6a9c3bbef5..113efc66b6f 100644 --- a/engines/stark/resources/anim.cpp +++ b/engines/stark/resources/anim.cpp @@ -58,6 +58,10 @@ void Anim::readData(XRCReadStream *stream) { _numFrames = stream->readUint32LE(); } +void Anim::selectFrame(uint32 frameIndex) { + //TODO +} + void Anim::reference(Item *item) { _refCount++; } diff --git a/engines/stark/resources/anim.h b/engines/stark/resources/anim.h index d5eece2e25d..94423422254 100644 --- a/engines/stark/resources/anim.h +++ b/engines/stark/resources/anim.h @@ -52,6 +52,8 @@ public: // Resource API void readData(XRCReadStream *stream) override; + void selectFrame(uint32 frameIndex); + // Refcounting, used to know if the anim script needs to run virtual void reference(Item *item); virtual void dereference(Item *item); diff --git a/engines/stark/resources/animscript.cpp b/engines/stark/resources/animscript.cpp index 990fddd3fcf..bb086da6368 100644 --- a/engines/stark/resources/animscript.cpp +++ b/engines/stark/resources/animscript.cpp @@ -20,9 +20,13 @@ * */ -#include "common/debug.h" - #include "engines/stark/resources/animscript.h" + +#include "common/debug.h" +#include "common/random.h" + +#include "engines/stark/resources/anim.h" +#include "engines/stark/stark.h" #include "engines/stark/xrcreader.h" namespace Stark { @@ -31,11 +35,81 @@ AnimScript::~AnimScript() { } AnimScript::AnimScript(Resource *parent, byte subType, uint16 index, const Common::String &name) : - Resource(parent, subType, index, name) { + Resource(parent, subType, index, name), + _anim(nullptr), + _msecsToNextUpdate(0), + _nextItemIndex(-1) { _type = TYPE; } -void AnimScript::printData() { +void AnimScript::onAllLoaded() { + Resource::onAllLoaded(); + + _anim = Resource::cast(_parent); + _items = listChildren(); + + if (!_items.empty()) { + // Setup the next item to the first + _nextItemIndex = 0; + } +} + +void AnimScript::onGameLoop(uint msecs) { + Resource::onGameLoop(msecs); + + if (!_anim || !_anim->isReferenced() || _nextItemIndex == -1) { + // The script is disabled, do nothing + return; + } + + Common::RandomSource *randomSource = StarkServices::instance().randomSource; + + while (_msecsToNextUpdate <= (int32)msecs) { + AnimScriptItem *item = _items[_nextItemIndex]; + _msecsToNextUpdate += item->getDuration(); + + switch (item->getOpcode()) { + case AnimScriptItem::kDisplayFrame: + _anim->selectFrame(item->getOperand()); + goToNextItem(); + break; + case AnimScriptItem::kPlayAnimSound: + // TODO + goToNextItem(); + break; + case AnimScriptItem::kGoToItem: + _nextItemIndex = item->getOperand(); + break; + case AnimScriptItem::kDisplayRandomFrame: { + uint32 startFrame = item->getOperand() >> 16; + uint32 endFrame = item->getOperand() & 0xFFFF; + + uint32 frame = randomSource->getRandomNumberRng(startFrame, endFrame); + _anim->selectFrame(frame); + goToNextItem(); + break; + } + case AnimScriptItem::kSleepRandomDuration: { + uint duration = randomSource->getRandomNumber(item->getOperand()); + _msecsToNextUpdate += duration; + goToNextItem(); + break; + } + case AnimScriptItem::kPlayStockSound: + // TODO + goToNextItem(); + break; + default: + error("Unknown anim script type %d", item->getOpcode()); + } + } + + _msecsToNextUpdate -= msecs; +} + +void AnimScript::goToNextItem() { + _nextItemIndex += 1; + _nextItemIndex %= _items.size(); } AnimScriptItem::~AnimScriptItem() { diff --git a/engines/stark/resources/animscript.h b/engines/stark/resources/animscript.h index 88bee8c5dc9..f0a56780c25 100644 --- a/engines/stark/resources/animscript.h +++ b/engines/stark/resources/animscript.h @@ -29,6 +29,8 @@ namespace Stark { +class Anim; +class AnimScriptItem; class XRCReadStream; class AnimScript : public Resource { @@ -38,25 +40,49 @@ public: AnimScript(Resource *parent, byte subType, uint16 index, const Common::String &name); virtual ~AnimScript(); + // Resource API + void onAllLoaded() override; + void onGameLoop(uint msecs) override; + protected: - void printData() override; + void goToNextItem(); + + Anim *_anim; + Common::Array _items; + + int32 _nextItemIndex; + int32 _msecsToNextUpdate; }; class AnimScriptItem : public Resource { public: static const ResourceType::Type TYPE = ResourceType::kAnimScriptItem; + enum Opcodes { + kDisplayFrame = 0, + kPlayAnimSound = 1, + kGoToItem = 2, + kDisplayRandomFrame = 3, + kSleepRandomDuration = 4, + kPlayStockSound = 5 + }; + AnimScriptItem(Resource *parent, byte subType, uint16 index, const Common::String &name); virtual ~AnimScriptItem(); + // Resource API void readData(XRCReadStream *stream) override; + uint32 getOpcode() const { return _opcode; } + uint32 getOperand() const { return _operand; } + uint32 getDuration() const { return _duration; } + +protected: + void printData() override; + uint32 _opcode; uint32 _operand; uint32 _duration; - -protected: - void printData() override; }; } // End of namespace Stark diff --git a/engines/stark/stark.cpp b/engines/stark/stark.cpp index e676c81ecad..46cc48db006 100644 --- a/engines/stark/stark.cpp +++ b/engines/stark/stark.cpp @@ -33,6 +33,7 @@ #include "common/config-manager.h" #include "common/events.h" +#include "common/random.h" #include "common/savefile.h" #include "common/system.h" #include "audio/mixer.h" @@ -52,7 +53,8 @@ StarkEngine::StarkEngine(OSystem *syst, const ADGameDescription *gameDesc) : _global(nullptr), _archiveLoader(nullptr), _stateProvider(nullptr), - _resourceProvider(nullptr) { + _resourceProvider(nullptr), + _randomSource(nullptr) { _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, 127); _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); @@ -66,6 +68,7 @@ StarkEngine::StarkEngine(OSystem *syst, const ADGameDescription *gameDesc) : } StarkEngine::~StarkEngine() { + delete _randomSource; delete _scene; delete _console; delete _gfx; @@ -88,12 +91,14 @@ Common::Error StarkEngine::run() { _stateProvider = new StateProvider(); _global = new Global(); _resourceProvider = new ResourceProvider(_archiveLoader, _stateProvider, _global); + _randomSource = new Common::RandomSource("stark"); // Setup the public services StarkServices &services = StarkServices::instance(); services.archiveLoader = _archiveLoader; services.resourceProvider = _resourceProvider; services.global = _global; + services.randomSource = _randomSource; // Load global resources _resourceProvider->initGlobal(); diff --git a/engines/stark/stark.h b/engines/stark/stark.h index 038af9019fa..c42de4bee76 100644 --- a/engines/stark/stark.h +++ b/engines/stark/stark.h @@ -26,6 +26,10 @@ #include "engines/advancedDetector.h" #include "engines/engine.h" +namespace Common { +class RandomSource; +} + namespace Stark { /* @@ -56,11 +60,13 @@ public: global = nullptr; archiveLoader = nullptr; resourceProvider = nullptr; + randomSource = nullptr; } Global *global; ArchiveLoader *archiveLoader; ResourceProvider *resourceProvider; + Common::RandomSource *randomSource; }; class StarkEngine : public Engine { @@ -89,6 +95,7 @@ private: ArchiveLoader *_archiveLoader; StateProvider *_stateProvider; ResourceProvider *_resourceProvider; + Common::RandomSource *_randomSource; const ADGameDescription *_gameDescription;