#ifndef CREATURELIB_SCRIPTAGGREGATOR_HPP #define CREATURELIB_SCRIPTAGGREGATOR_HPP #include #include #include "../../Library/Exceptions/NotReachableException.hpp" #include "Script.hpp" #include "ScriptSet.hpp" #include "ScriptWrapper.hpp" namespace CreatureLib::Battling { class ScriptAggregator { std::vector _scripts; size_t _index = 0; bool _isSetSet = false; const std::vector* _setScripts; size_t _setIndex; public: ScriptAggregator(std::vector scripts) : _scripts(std::move(scripts)){}; bool HasNext() { return _index < _scripts.size() || (_isSetSet && _setIndex < _setScripts->size()); } Script* GetNext() { // We can probably do this in a cleaner version once C++ 20 drops with Coroutine support. if (_isSetSet) { if (_setIndex >= _setScripts->size()) { _isSetSet = false; return GetNext(); } auto s = _setScripts->at(_setIndex); _setIndex++; if (_setIndex >= _setScripts->size()) { _isSetSet = false; } return s; } if (_index >= _scripts.size()) return nullptr; auto next = _scripts[_index]; _index++; if (!next.IsSet()) { auto scriptPtr = next.GetScript(); if (scriptPtr == nullptr) return GetNext(); return *scriptPtr; } else { auto set = next.GetScriptSet(); if (set->Count() == 0) return GetNext(); _setScripts = set->GetIterator(); _isSetSet = true; _setIndex = 0; return GetNext(); } throw NotReachableException(); } }; } #endif // CREATURELIB_SCRIPTAGGREGATOR_HPP