1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-04-03 10:20:10 +00:00

Add engine handler for skill levelup, to dehardcode the book/trainer case.

This commit is contained in:
Mads Buvik Sandvei 2024-01-15 21:48:19 +01:00
parent 2cfa819ccc
commit 9f15f3b431
10 changed files with 38 additions and 14 deletions

@ -62,8 +62,9 @@ namespace MWBase
virtual void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0; 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 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 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 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, 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) std::string_view start, std::string_view stop, float startpoint, uint32_t loops, bool loopfallback)
= 0; = 0;

@ -5,6 +5,7 @@
#include <MyGUI_TextIterator.h> #include <MyGUI_TextIterator.h>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/luamanager.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -174,10 +175,7 @@ namespace MWGui
} }
// increase skill // increase skill
MWWorld::LiveCellRef<ESM::NPC>* playerRef = player.get<ESM::NPC>(); MWBase::Environment::get().getLuaManager()->skillLevelUp(player, skill->mId, "trainer");
const ESM::Class* class_ = store.get<ESM::Class>().find(playerRef->mBase->mClass);
pcStats.increaseSkill(skill->mId, *class_, true);
// remove gold // remove gold
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price); player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price);

@ -104,6 +104,15 @@ namespace MWLua
scripts->onSkillUse(event.mSkill, event.useType, event.scale); 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: private:
MWWorld::Ptr getPtr(ESM::RefNum id) const MWWorld::Ptr getPtr(ESM::RefNum id) const
{ {

@ -70,8 +70,14 @@ namespace MWLua
int useType; int useType;
float scale; float scale;
}; };
struct OnSkillLevelUp
{
ESM::RefNum mActor;
std::string mSkill;
std::string mSource;
};
using Event = std::variant<OnActive, OnInactive, OnConsume, OnActivate, OnUseItem, OnNewExterior, OnTeleported, using Event = std::variant<OnActive, OnInactive, OnConsume, OnActivate, OnUseItem, OnNewExterior, OnTeleported,
OnAnimationTextKey, OnSkillUse>; OnAnimationTextKey, OnSkillUse, OnSkillLevelUp>;
void clear() { mQueue.clear(); } void clear() { mQueue.clear(); }
void addToQueue(Event e) { mQueue.push_back(std::move(e)); } void addToQueue(Event e) { mQueue.push_back(std::move(e)); }

@ -176,7 +176,7 @@ namespace MWLua
{ {
this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData)); this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData));
registerEngineHandlers({ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers, registerEngineHandlers({ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers,
&mOnTeleportedHandlers, &mOnAnimationTextKeyHandlers, &mOnPlayAnimationHandlers, &mOnSkillUse }); &mOnTeleportedHandlers, &mOnAnimationTextKeyHandlers, &mOnPlayAnimationHandlers, &mOnSkillUse, &mOnSkillLevelUp });
} }
void LocalScripts::setActive(bool active) void LocalScripts::setActive(bool active)

@ -83,6 +83,10 @@ namespace MWLua
{ {
callEngineHandlers(mOnSkillUse, skillId, useType, scale); callEngineHandlers(mOnSkillUse, skillId, useType, scale);
} }
void onSkillLevelUp(std::string_view skillId, std::string_view source)
{
callEngineHandlers(mOnSkillLevelUp, skillId, source);
}
void applyStatsCache(); void applyStatsCache();
@ -98,6 +102,7 @@ namespace MWLua
EngineHandlerList mOnAnimationTextKeyHandlers{ "_onAnimationTextKey" }; EngineHandlerList mOnAnimationTextKeyHandlers{ "_onAnimationTextKey" };
EngineHandlerList mOnPlayAnimationHandlers{ "_onPlayAnimation" }; EngineHandlerList mOnPlayAnimationHandlers{ "_onPlayAnimation" };
EngineHandlerList mOnSkillUse{ "_onSkillUse" }; EngineHandlerList mOnSkillUse{ "_onSkillUse" };
EngineHandlerList mOnSkillLevelUp{ "_onSkillLevelUp" };
}; };
} }

@ -411,6 +411,11 @@ namespace MWLua
mEngineEvents.addToQueue(EngineEvents::OnSkillUse{ getId(actor), skillId.serializeText(), useType, scale }); 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) void LuaManager::objectAddedToScene(const MWWorld::Ptr& ptr)
{ {
mObjectLists.objectAddedToScene(ptr); // assigns generated RefNum if it is not set yet. mObjectLists.objectAddedToScene(ptr); // assigns generated RefNum if it is not set yet.

@ -85,6 +85,7 @@ namespace MWLua
std::string_view start, std::string_view stop, float startpoint, uint32_t loops, std::string_view start, std::string_view stop, float startpoint, uint32_t loops,
bool loopfallback) override; bool loopfallback) override;
void skillUse(const MWWorld::Ptr& actor, ESM::RefId skillId, int useType, float scale) 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 void exteriorCreated(MWWorld::CellStore& cell) override
{ {
mEngineEvents.addToQueue(EngineEvents::OnNewExterior{ cell }); mEngineEvents.addToQueue(EngineEvents::OnNewExterior{ cell });

@ -5,6 +5,7 @@
#include <components/esm3/loadskil.hpp> #include <components/esm3/loadskil.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/luamanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"
@ -49,12 +50,7 @@ namespace MWWorld
ESM::RefId skill = ESM::Skill::indexToRefId(ref->mBase->mData.mSkillId); ESM::RefId skill = ESM::Skill::indexToRefId(ref->mBase->mData.mSkillId);
if (!skill.empty() && !npcStats.hasBeenUsed(ref->mBase->mId)) if (!skill.empty() && !npcStats.hasBeenUsed(ref->mBase->mId))
{ {
MWWorld::LiveCellRef<ESM::NPC>* playerRef = actor.get<ESM::NPC>(); MWBase::Environment::get().getLuaManager()->skillLevelUp(actor, skill, "book");
const ESM::Class* class_
= MWBase::Environment::get().getESMStore()->get<ESM::Class>().find(playerRef->mBase->mClass);
npcStats.increaseSkill(skill, *class_, true, true);
npcStats.flagAsUsed(ref->mBase->mId); npcStats.flagAsUsed(ref->mBase->mId);
} }

@ -265,9 +265,12 @@ return {
}, },
}, },
engineHandlers = { engineHandlers = {
-- Use the interface in these handlers so any overrides will receive the calls.
_onSkillUse = function (skillid, useType, scale) _onSkillUse = function (skillid, useType, scale)
-- Use the interface here so any overrides of skillUsed will receive the call.
I.SkillProgression.skillUsed(skillid, useType, scale) I.SkillProgression.skillUsed(skillid, useType, scale)
end, end,
_onSkillLevelUp = function (skillid, source)
I.SkillProgression.skillLevelUp(skillid, source)
end,
}, },
} }