From 9f15f3b431e057232ada7fb39748a4a4e37a6d2e Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei <madssandvei@zoho.com> Date: Mon, 15 Jan 2024 21:48:19 +0100 Subject: [PATCH] Add engine handler for skill levelup, to dehardcode the book/trainer case. --- apps/openmw/mwbase/luamanager.hpp | 3 ++- apps/openmw/mwgui/trainingwindow.cpp | 6 ++---- apps/openmw/mwlua/engineevents.cpp | 9 +++++++++ apps/openmw/mwlua/engineevents.hpp | 8 +++++++- apps/openmw/mwlua/localscripts.cpp | 2 +- apps/openmw/mwlua/localscripts.hpp | 5 +++++ apps/openmw/mwlua/luamanagerimp.cpp | 5 +++++ apps/openmw/mwlua/luamanagerimp.hpp | 1 + apps/openmw/mwworld/actionread.cpp | 8 ++------ files/data/scripts/omw/skillhandlers.lua | 5 ++++- 10 files changed, 38 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwbase/luamanager.hpp b/apps/openmw/mwbase/luamanager.hpp index 115416cd8c..7f7ee85127 100644 --- a/apps/openmw/mwbase/luamanager.hpp +++ b/apps/openmw/mwbase/luamanager.hpp @@ -62,8 +62,9 @@ namespace MWBase virtual void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0; virtual void useItem(const MWWorld::Ptr& object, const MWWorld::Ptr& actor, bool force) = 0; virtual void animationTextKey(const MWWorld::Ptr& actor, const std::string& key) = 0; - virtual void skillUse(const MWWorld::Ptr& actor, ESM::RefId skillId, int useType, float scale) = 0; virtual void playAnimation(const MWWorld::Ptr& object, const std::string& groupname, + virtual void skillLevelUp(const MWWorld::Ptr& actor, ESM::RefId skillId, std::string_view source) = 0; + virtual void skillUse(const MWWorld::Ptr& actor, ESM::RefId skillId, int useType, float scale) = 0; const MWRender::AnimPriority& priority, int blendMask, bool autodisable, float speedmult, std::string_view start, std::string_view stop, float startpoint, uint32_t loops, bool loopfallback) = 0; diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index 5395f6db1c..fa4fd266b5 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -5,6 +5,7 @@ #include <MyGUI_TextIterator.h> #include "../mwbase/environment.hpp" +#include "../mwbase/luamanager.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" @@ -174,10 +175,7 @@ namespace MWGui } // increase skill - MWWorld::LiveCellRef<ESM::NPC>* playerRef = player.get<ESM::NPC>(); - - const ESM::Class* class_ = store.get<ESM::Class>().find(playerRef->mBase->mClass); - pcStats.increaseSkill(skill->mId, *class_, true); + MWBase::Environment::get().getLuaManager()->skillLevelUp(player, skill->mId, "trainer"); // remove gold player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price); diff --git a/apps/openmw/mwlua/engineevents.cpp b/apps/openmw/mwlua/engineevents.cpp index 7cc2b3db48..f9b9d461cc 100644 --- a/apps/openmw/mwlua/engineevents.cpp +++ b/apps/openmw/mwlua/engineevents.cpp @@ -104,6 +104,15 @@ namespace MWLua scripts->onSkillUse(event.mSkill, event.useType, event.scale); } + void operator()(const OnSkillLevelUp& event) const + { + MWWorld::Ptr actor = getPtr(event.mActor); + if (actor.isEmpty()) + return; + if (auto* scripts = getLocalScripts(actor)) + scripts->onSkillLevelUp(event.mSkill, event.mSource); + } + private: MWWorld::Ptr getPtr(ESM::RefNum id) const { diff --git a/apps/openmw/mwlua/engineevents.hpp b/apps/openmw/mwlua/engineevents.hpp index b9f4c25b39..862c09ef2a 100644 --- a/apps/openmw/mwlua/engineevents.hpp +++ b/apps/openmw/mwlua/engineevents.hpp @@ -70,8 +70,14 @@ namespace MWLua int useType; float scale; }; + struct OnSkillLevelUp + { + ESM::RefNum mActor; + std::string mSkill; + std::string mSource; + }; using Event = std::variant<OnActive, OnInactive, OnConsume, OnActivate, OnUseItem, OnNewExterior, OnTeleported, - OnAnimationTextKey, OnSkillUse>; + OnAnimationTextKey, OnSkillUse, OnSkillLevelUp>; void clear() { mQueue.clear(); } void addToQueue(Event e) { mQueue.push_back(std::move(e)); } diff --git a/apps/openmw/mwlua/localscripts.cpp b/apps/openmw/mwlua/localscripts.cpp index 0c0af5b902..8bd0d7c047 100644 --- a/apps/openmw/mwlua/localscripts.cpp +++ b/apps/openmw/mwlua/localscripts.cpp @@ -176,7 +176,7 @@ namespace MWLua { this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData)); registerEngineHandlers({ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers, - &mOnTeleportedHandlers, &mOnAnimationTextKeyHandlers, &mOnPlayAnimationHandlers, &mOnSkillUse }); + &mOnTeleportedHandlers, &mOnAnimationTextKeyHandlers, &mOnPlayAnimationHandlers, &mOnSkillUse, &mOnSkillLevelUp }); } void LocalScripts::setActive(bool active) diff --git a/apps/openmw/mwlua/localscripts.hpp b/apps/openmw/mwlua/localscripts.hpp index f5f740b1c6..2ec78860d1 100644 --- a/apps/openmw/mwlua/localscripts.hpp +++ b/apps/openmw/mwlua/localscripts.hpp @@ -83,6 +83,10 @@ namespace MWLua { callEngineHandlers(mOnSkillUse, skillId, useType, scale); } + void onSkillLevelUp(std::string_view skillId, std::string_view source) + { + callEngineHandlers(mOnSkillLevelUp, skillId, source); + } void applyStatsCache(); @@ -98,6 +102,7 @@ namespace MWLua EngineHandlerList mOnAnimationTextKeyHandlers{ "_onAnimationTextKey" }; EngineHandlerList mOnPlayAnimationHandlers{ "_onPlayAnimation" }; EngineHandlerList mOnSkillUse{ "_onSkillUse" }; + EngineHandlerList mOnSkillLevelUp{ "_onSkillLevelUp" }; }; } diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index 0974856d25..5a743f41e3 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -411,6 +411,11 @@ namespace MWLua mEngineEvents.addToQueue(EngineEvents::OnSkillUse{ getId(actor), skillId.serializeText(), useType, scale }); } + void LuaManager::skillLevelUp(const MWWorld::Ptr& actor, ESM::RefId skillId, std::string_view source) + { + mEngineEvents.addToQueue(EngineEvents::OnSkillLevelUp{ getId(actor), skillId.serializeText(), std::string(source) }); + } + void LuaManager::objectAddedToScene(const MWWorld::Ptr& ptr) { mObjectLists.objectAddedToScene(ptr); // assigns generated RefNum if it is not set yet. diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index 2e29ff272a..685fbbde4c 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -85,6 +85,7 @@ namespace MWLua std::string_view start, std::string_view stop, float startpoint, uint32_t loops, bool loopfallback) override; void skillUse(const MWWorld::Ptr& actor, ESM::RefId skillId, int useType, float scale) override; + void skillLevelUp(const MWWorld::Ptr& actor, ESM::RefId skillId, std::string_view source) override; void exteriorCreated(MWWorld::CellStore& cell) override { mEngineEvents.addToQueue(EngineEvents::OnNewExterior{ cell }); diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index 3f48920dc0..477c92d2dd 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -5,6 +5,7 @@ #include <components/esm3/loadskil.hpp> #include "../mwbase/environment.hpp" +#include "../mwbase/luamanager.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwmechanics/actorutil.hpp" @@ -49,12 +50,7 @@ namespace MWWorld ESM::RefId skill = ESM::Skill::indexToRefId(ref->mBase->mData.mSkillId); if (!skill.empty() && !npcStats.hasBeenUsed(ref->mBase->mId)) { - MWWorld::LiveCellRef<ESM::NPC>* playerRef = actor.get<ESM::NPC>(); - - const ESM::Class* class_ - = MWBase::Environment::get().getESMStore()->get<ESM::Class>().find(playerRef->mBase->mClass); - - npcStats.increaseSkill(skill, *class_, true, true); + MWBase::Environment::get().getLuaManager()->skillLevelUp(actor, skill, "book"); npcStats.flagAsUsed(ref->mBase->mId); } diff --git a/files/data/scripts/omw/skillhandlers.lua b/files/data/scripts/omw/skillhandlers.lua index 975a8b984e..1f3b856344 100644 --- a/files/data/scripts/omw/skillhandlers.lua +++ b/files/data/scripts/omw/skillhandlers.lua @@ -265,9 +265,12 @@ return { }, }, engineHandlers = { + -- Use the interface in these handlers so any overrides will receive the calls. _onSkillUse = function (skillid, useType, scale) - -- Use the interface here so any overrides of skillUsed will receive the call. I.SkillProgression.skillUsed(skillid, useType, scale) end, + _onSkillLevelUp = function (skillid, source) + I.SkillProgression.skillLevelUp(skillid, source) + end, }, }