diff --git a/apps/openmw/mwlua/dialoguebindings.cpp b/apps/openmw/mwlua/dialoguebindings.cpp index e126bf0e82..20740870dc 100644 --- a/apps/openmw/mwlua/dialoguebindings.cpp +++ b/apps/openmw/mwlua/dialoguebindings.cpp @@ -1,10 +1,11 @@ #include "dialoguebindings.hpp" + +#include "context.hpp" + #include "apps/openmw/mwbase/environment.hpp" #include "apps/openmw/mwworld/esmstore.hpp" #include "apps/openmw/mwworld/store.hpp" -#include "context.hpp" -#include "object.hpp" -#include + #include #include #include @@ -12,122 +13,44 @@ namespace { - template + std::vector makeIndex(const MWWorld::Store& store, ESM::Dialogue::Type type) + { + std::vector result; + for (const ESM::Dialogue& v : store) + if (v.mType == type) + result.push_back(&v); + return result; + } + + template class FilteredDialogueStore { const MWWorld::Store& mDialogueStore; - - const ESM::Dialogue* foundDialogueFilteredOut(const ESM::Dialogue* possibleResult) const - { - if (possibleResult && possibleResult->mType == filter) - { - return possibleResult; - } - return nullptr; - } + std::vector mIndex; public: - FilteredDialogueStore() - : mDialogueStore{ MWBase::Environment::get().getESMStore()->get() } + explicit FilteredDialogueStore(const MWWorld::Store& store) + : mDialogueStore(store) + , mIndex{ makeIndex(store, type) } { } - class FilteredDialogueIterator - { - using DecoratedIterator = MWWorld::Store::iterator; - DecoratedIterator mIter; - DecoratedIterator mEndIter; - - public: - using iterator_category = DecoratedIterator::iterator_category; - using value_type = DecoratedIterator::value_type; - using difference_type = DecoratedIterator::difference_type; - using pointer = DecoratedIterator::pointer; - using reference = DecoratedIterator::reference; - - FilteredDialogueIterator(const DecoratedIterator& pointingIterator, const DecoratedIterator& end) - : mIter{ pointingIterator } - , mEndIter{ end } - { - } - - FilteredDialogueIterator& operator++() - { - if (mIter == mEndIter) - { - return *this; - } - - do - { - ++mIter; - } while (mIter != mEndIter && mIter->mType != filter); - return *this; - } - - FilteredDialogueIterator operator++(int) - { - FilteredDialogueIterator iter = *this; - ++(*this); - return iter; - } - - FilteredDialogueIterator& operator+=(difference_type advance) - { - while (advance > 0 && mIter != mEndIter) - { - ++(*this); - --advance; - } - return *this; - } - - bool operator==(const FilteredDialogueIterator& x) const { return mIter == x.mIter; } - - bool operator!=(const FilteredDialogueIterator& x) const { return !(*this == x); } - - const value_type& operator*() const { return *mIter; } - - const value_type* operator->() const { return &(*mIter); } - }; - - using iterator = FilteredDialogueIterator; - const ESM::Dialogue* search(const ESM::RefId& id) const { - return foundDialogueFilteredOut(mDialogueStore.search(id)); + const ESM::Dialogue* dialogue = mDialogueStore.search(id); + if (dialogue != nullptr && dialogue->mType == type) + return dialogue; + return nullptr; } - const ESM::Dialogue* at(size_t index) const + const ESM::Dialogue* at(std::size_t index) const { - auto result = begin(); - result += index; - - if (result == end()) - { + if (index >= mIndex.size()) return nullptr; - } - - return &(*result); - } - - size_t getSize() const - { - return std::count_if( - mDialogueStore.begin(), mDialogueStore.end(), [](const auto& d) { return d.mType == filter; }); - } - - iterator begin() const - { - iterator result{ mDialogueStore.begin(), mDialogueStore.end() }; - while (result != end() && result->mType != filter) - { - ++result; - } - return result; + return mIndex[index]; } - iterator end() const { return iterator{ mDialogueStore.end(), mDialogueStore.end() }; } + std::size_t getSize() const { return mIndex.size(); } }; template @@ -156,7 +79,7 @@ namespace storeBindingsClass[sol::meta_function::ipairs] = lua["ipairsForArray"].template get(); storeBindingsClass[sol::meta_function::pairs] = lua["ipairsForArray"].template get(); - table["records"] = StoreT{}; + table["records"] = StoreT{ MWBase::Environment::get().getESMStore()->get() }; } struct DialogueInfos diff --git a/apps/openmw/mwlua/dialoguebindings.hpp b/apps/openmw/mwlua/dialoguebindings.hpp index 6909418e96..a4ee242427 100644 --- a/apps/openmw/mwlua/dialoguebindings.hpp +++ b/apps/openmw/mwlua/dialoguebindings.hpp @@ -6,7 +6,8 @@ namespace MWLua { struct Context; - sol::table initCoreDialogueBindings(const Context&); + + sol::table initCoreDialogueBindings(const Context& context); } #endif // MWLUA_DIALOGUEBINDINGS_H diff --git a/scripts/data/morrowind_tests/builtin.omwscripts b/scripts/data/morrowind_tests/builtin.omwscripts deleted file mode 100644 index 8b7db327c5..0000000000 --- a/scripts/data/morrowind_tests/builtin.omwscripts +++ /dev/null @@ -1 +0,0 @@ -# It is an empty file that overrides builtin.omwscripts and disables builtin scripts diff --git a/scripts/data/morrowind_tests/global.lua b/scripts/data/morrowind_tests/global.lua new file mode 100644 index 0000000000..cdc10c0059 --- /dev/null +++ b/scripts/data/morrowind_tests/global.lua @@ -0,0 +1,34 @@ +local testing = require('testing_util') +local util = require('openmw.util') +local world = require('openmw.world') +local core = require('openmw.core') +local types = require('openmw.types') + +if not core.contentFiles.has('Morrowind.esm') then + error('This test requires Morrowind.esm') +end + +function makeTests(modules) + local tests = {} + + for _, moduleName in ipairs(modules) do + local module = require(moduleName) + for _, v in ipairs(module) do + table.insert(tests, {string.format('[%s] %s', moduleName, v[1]), v[2]}) + end + end + + return tests +end + +local testModules = { + 'global_issues', + 'global_dialogues', +} + +return { + engineHandlers = { + onUpdate = testing.testRunner(makeTests(testModules)), + }, + eventHandlers = testing.eventHandlers, +} diff --git a/scripts/data/morrowind_tests/global_dialogues.lua b/scripts/data/morrowind_tests/global_dialogues.lua new file mode 100644 index 0000000000..397eb8461c --- /dev/null +++ b/scripts/data/morrowind_tests/global_dialogues.lua @@ -0,0 +1,47 @@ +local testing = require('testing_util') +local core = require('openmw.core') + +function iterateOverRecords(records) + local firstRecordId = nil + local lastRecordId = nil + local count = 0 + for _, v in ipairs(records) do + firstRecordId = firstRecordId or v.id + lastRecordId = v.id + count = count + 1 + end + return firstRecordId, lastRecordId, count +end + +return { + {'Should support iteration over journal dialogues', function() + local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.journal.records) + testing.expectEqual(firstRecordId, '11111 test journal') + testing.expectEqual(lastRecordId, 'va_vamprich') + testing.expectEqual(count, 632) + end}, + {'Should support iteration over topic dialogues', function() + local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.topic.records) + testing.expectEqual(firstRecordId, '1000-drake pledge') + testing.expectEqual(lastRecordId, 'zenithar') + testing.expectEqual(count, 1698) + end}, + {'Should support iteration over greeting dialogues', function() + local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.greeting.records) + testing.expectEqual(firstRecordId, 'greeting 0') + testing.expectEqual(lastRecordId, 'greeting 9') + testing.expectEqual(count, 10) + end}, + {'Should support iteration over persuasion dialogues', function() + local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.persuasion.records) + testing.expectEqual(firstRecordId, 'admire fail') + testing.expectEqual(lastRecordId, 'taunt success') + testing.expectEqual(count, 10) + end}, + {'Should support iteration over voice dialogues', function() + local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.voice.records) + testing.expectEqual(firstRecordId, 'alarm') + testing.expectEqual(lastRecordId, 'thief') + testing.expectEqual(count, 8) + end}, +} diff --git a/scripts/data/morrowind_tests/test.lua b/scripts/data/morrowind_tests/global_issues.lua similarity index 89% rename from scripts/data/morrowind_tests/test.lua rename to scripts/data/morrowind_tests/global_issues.lua index 3515002f2d..2afad085b0 100644 --- a/scripts/data/morrowind_tests/test.lua +++ b/scripts/data/morrowind_tests/global_issues.lua @@ -4,11 +4,7 @@ local world = require('openmw.world') local core = require('openmw.core') local types = require('openmw.types') -if not core.contentFiles.has('Morrowind.esm') then - error('This test requires Morrowind.esm') -end - -local tests = { +return { {'Player should be able to walk up stairs in Ebonheart docks (#4247)', function() world.players[1]:teleport('', util.vector3(19867, -102180, -79), util.transform.rotateZ(math.rad(91))) coroutine.yield() @@ -42,10 +38,3 @@ local tests = { testing.expectThat(types.Container.inventory(barrel):find('ring_keley'), isFargothRing) end}, } - -return { - engineHandlers = { - onUpdate = testing.testRunner(tests), - }, - eventHandlers = testing.eventHandlers, -} diff --git a/scripts/data/morrowind_tests/test.omwscripts b/scripts/data/morrowind_tests/morrowind_tests.omwscripts similarity index 50% rename from scripts/data/morrowind_tests/test.omwscripts rename to scripts/data/morrowind_tests/morrowind_tests.omwscripts index 80507392f7..7455690608 100644 --- a/scripts/data/morrowind_tests/test.omwscripts +++ b/scripts/data/morrowind_tests/morrowind_tests.omwscripts @@ -1,2 +1,2 @@ -GLOBAL: test.lua +GLOBAL: global.lua PLAYER: player.lua diff --git a/scripts/data/morrowind_tests/openmw.cfg b/scripts/data/morrowind_tests/openmw.cfg index a8e18932ba..4693c186b4 100644 --- a/scripts/data/morrowind_tests/openmw.cfg +++ b/scripts/data/morrowind_tests/openmw.cfg @@ -7,5 +7,5 @@ data-local=test_workdir data=../integration_tests/testing_util data=. content=Morrowind.esm -content=test.omwscripts +content=morrowind_tests.omwscripts fallback-archive=Morrowind.bsa diff --git a/scripts/data/morrowind_tests/player.lua b/scripts/data/morrowind_tests/player.lua index c366d91ebd..7c2e36978e 100644 --- a/scripts/data/morrowind_tests/player.lua +++ b/scripts/data/morrowind_tests/player.lua @@ -78,7 +78,7 @@ testing.registerLocalTest('Guard in Imperial Prison Ship should find path (#7241 return { engineHandlers = { - onUpdate = testing.updateLocal, + onFrame = testing.updateLocal, }, eventHandlers = testing.eventHandlers }