diff --git a/apps/openmw/mwbase/luamanager.hpp b/apps/openmw/mwbase/luamanager.hpp index 06a68efe4a..e4b16ff725 100644 --- a/apps/openmw/mwbase/luamanager.hpp +++ b/apps/openmw/mwbase/luamanager.hpp @@ -53,6 +53,7 @@ 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 exteriorCreated(MWWorld::CellStore& cell) = 0; + virtual void actorDied(const MWWorld::Ptr& actor) = 0; virtual void questUpdated(const ESM::RefId& questId, int stage) = 0; // `arg` is either forwarded from MWGui::pushGuiMode or empty diff --git a/apps/openmw/mwlua/engineevents.cpp b/apps/openmw/mwlua/engineevents.cpp index 0fbb13f1cf..7250acc857 100644 --- a/apps/openmw/mwlua/engineevents.cpp +++ b/apps/openmw/mwlua/engineevents.cpp @@ -86,6 +86,16 @@ namespace MWLua void operator()(const OnNewExterior& event) const { mGlobalScripts.onNewExterior(GCell{ &event.mCell }); } + void operator()(const OnDeath& event) const + { + MWWorld::Ptr actor = getPtr(event.mActor); + if (!actor.isEmpty()) + { + if (auto* scripts = getLocalScripts(actor)) + scripts->onDeath(); + } + } + private: MWWorld::Ptr getPtr(ESM::RefNum id) const { diff --git a/apps/openmw/mwlua/engineevents.hpp b/apps/openmw/mwlua/engineevents.hpp index 7c706edcd0..04a5ab4ebd 100644 --- a/apps/openmw/mwlua/engineevents.hpp +++ b/apps/openmw/mwlua/engineevents.hpp @@ -51,7 +51,12 @@ namespace MWLua { MWWorld::CellStore& mCell; }; - using Event = std::variant; + struct OnDeath + { + ESM::RefNum mActor; + }; + using Event = std::variant; 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 8cf383e985..8dc8358aa8 100644 --- a/apps/openmw/mwlua/localscripts.cpp +++ b/apps/openmw/mwlua/localscripts.cpp @@ -170,7 +170,7 @@ namespace MWLua { this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData)); registerEngineHandlers({ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers, - &mOnTeleportedHandlers }); + &mOnTeleportedHandlers, &mOnDeathHandlers }); } void LocalScripts::setActive(bool active) diff --git a/apps/openmw/mwlua/localscripts.hpp b/apps/openmw/mwlua/localscripts.hpp index b87b628a89..05b34cbb96 100644 --- a/apps/openmw/mwlua/localscripts.hpp +++ b/apps/openmw/mwlua/localscripts.hpp @@ -71,6 +71,7 @@ namespace MWLua void onConsume(const LObject& consumable) { callEngineHandlers(mOnConsumeHandlers, consumable); } void onActivated(const LObject& actor) { callEngineHandlers(mOnActivatedHandlers, actor); } void onTeleported() { callEngineHandlers(mOnTeleportedHandlers); } + void onDeath() { callEngineHandlers(mOnDeathHandlers); } void applyStatsCache(); @@ -83,6 +84,7 @@ namespace MWLua EngineHandlerList mOnConsumeHandlers{ "onConsume" }; EngineHandlerList mOnActivatedHandlers{ "onActivated" }; EngineHandlerList mOnTeleportedHandlers{ "onTeleported" }; + EngineHandlerList mOnDeathHandlers{ "onDeath" }; }; } diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index 404820cc6b..ed0b4e9257 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -82,6 +82,10 @@ namespace MWLua { mEngineEvents.addToQueue(EngineEvents::OnNewExterior{ cell }); } + void actorDied(const MWWorld::Ptr& actor) override + { + mEngineEvents.addToQueue(EngineEvents::OnDeath{ getId(actor) }); + } void objectTeleported(const MWWorld::Ptr& ptr) override; void questUpdated(const ESM::RefId& questId, int stage) override; void uiModeChanged(const MWWorld::Ptr& arg) override; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 3e7b075e62..73bd331de2 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1730,6 +1730,8 @@ namespace MWMechanics actor.getClass().getCreatureStats(actor).notifyDied(); ++mDeathCount[actor.getCellRef().getRefId()]; + + MWBase::Environment::get().getLuaManager()->actorDied(actor); } void Actors::resurrect(const MWWorld::Ptr& ptr) const diff --git a/docs/source/reference/lua-scripting/engine_handlers.rst b/docs/source/reference/lua-scripting/engine_handlers.rst index 1ffa1820f3..b6e90a6bda 100644 --- a/docs/source/reference/lua-scripting/engine_handlers.rst +++ b/docs/source/reference/lua-scripting/engine_handlers.rst @@ -79,6 +79,8 @@ Engine handler is a function defined by a script, that can be called by the engi - | Called on an actor when they consume an item (e.g. a potion). | Similarly to onActivated, the item has already been removed | from the actor's inventory, and the count was set to zero. + * - onDeath() + - Called when the actor dies. Note that actors that start out dead are ignored. **Only for local scripts attached to a player**