From b1a6441c2329612eb30ba052b815797ae8b52b86 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Wed, 21 Apr 2021 04:11:11 +0200 Subject: [PATCH] Add LocalScripts::LocalEngineEvent. Add `OnConsume` engine handler. --- apps/openmw/mwbase/luamanager.hpp | 11 +++++-- apps/openmw/mwclass/npc.cpp | 2 ++ apps/openmw/mwlua/eventqueue.cpp | 8 ++--- apps/openmw/mwlua/eventqueue.hpp | 10 +++--- apps/openmw/mwlua/localscripts.cpp | 30 ++++++++++++------ apps/openmw/mwlua/localscripts.hpp | 13 ++++++-- apps/openmw/mwlua/luamanagerimp.cpp | 49 ++++++++++++++++++----------- apps/openmw/mwlua/luamanagerimp.hpp | 10 ++++-- 8 files changed, 90 insertions(+), 43 deletions(-) diff --git a/apps/openmw/mwbase/luamanager.hpp b/apps/openmw/mwbase/luamanager.hpp index 52d3102a45..24c1780984 100644 --- a/apps/openmw/mwbase/luamanager.hpp +++ b/apps/openmw/mwbase/luamanager.hpp @@ -29,11 +29,16 @@ namespace MWBase virtual ~LuaManager() = default; virtual void newGameStarted() = 0; - virtual void objectAddedToScene(const MWWorld::Ptr& ptr) = 0; - virtual void objectRemovedFromScene(const MWWorld::Ptr& ptr) = 0; + virtual void keyPressed(const SDL_KeyboardEvent &arg) = 0; + virtual void registerObject(const MWWorld::Ptr& ptr) = 0; virtual void deregisterObject(const MWWorld::Ptr& ptr) = 0; - virtual void keyPressed(const SDL_KeyboardEvent &arg) = 0; + virtual void objectAddedToScene(const MWWorld::Ptr& ptr) = 0; + virtual void objectRemovedFromScene(const MWWorld::Ptr& ptr) = 0; + virtual void appliedToObject(const MWWorld::Ptr& toPtr, std::string_view recordId, const MWWorld::Ptr& fromPtr) = 0; + // TODO: notify LuaManager about other events + // virtual void objectOnHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, + // const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful) = 0; struct ActorControls { bool disableAI; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 6131f86269..5bf81caf9d 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -17,6 +17,7 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/dialoguemanager.hpp" #include "../mwbase/soundmanager.hpp" +#include "../mwbase/luamanager.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/npcstats.hpp" @@ -1095,6 +1096,7 @@ namespace MWClass bool Npc::apply (const MWWorld::Ptr& ptr, const std::string& id, const MWWorld::Ptr& actor) const { + MWBase::Environment::get().getLuaManager()->appliedToObject(ptr, id, actor); MWMechanics::CastSpell cast(ptr, ptr); return cast.cast(id); } diff --git a/apps/openmw/mwlua/eventqueue.cpp b/apps/openmw/mwlua/eventqueue.cpp index 5e63fee57a..1c136551c4 100644 --- a/apps/openmw/mwlua/eventqueue.cpp +++ b/apps/openmw/mwlua/eventqueue.cpp @@ -14,10 +14,10 @@ namespace MWLua template void saveEvent(ESM::ESMWriter& esm, const ObjectId& dest, const Event& event) { - esm.writeHNString("LUAE", event.eventName); + esm.writeHNString("LUAE", event.mEventName); dest.save(esm, true); - if (!event.eventData.empty()) - saveLuaBinaryData(esm, event.eventData); + if (!event.mEventData.empty()) + saveLuaBinaryData(esm, event.mEventData); } void loadEvents(sol::state& lua, ESM::ESMReader& esm, GlobalEventQueue& globalEvents, LocalEventQueue& localEvents, @@ -57,7 +57,7 @@ namespace MWLua for (const GlobalEvent& e : globalEvents) saveEvent(esm, globalId, e); for (const LocalEvent& e : localEvents) - saveEvent(esm, e.dest, e); + saveEvent(esm, e.mDest, e); } } diff --git a/apps/openmw/mwlua/eventqueue.hpp b/apps/openmw/mwlua/eventqueue.hpp index b692d7162d..0e5f2dfcb4 100644 --- a/apps/openmw/mwlua/eventqueue.hpp +++ b/apps/openmw/mwlua/eventqueue.hpp @@ -23,14 +23,14 @@ namespace MWLua { struct GlobalEvent { - std::string eventName; - std::string eventData; + std::string mEventName; + std::string mEventData; }; struct LocalEvent { - ObjectId dest; - std::string eventName; - std::string eventData; + ObjectId mDest; + std::string mEventName; + std::string mEventData; }; using GlobalEventQueue = std::vector; using LocalEventQueue = std::vector; diff --git a/apps/openmw/mwlua/localscripts.cpp b/apps/openmw/mwlua/localscripts.cpp index 5b5347af03..e4c50334d4 100644 --- a/apps/openmw/mwlua/localscripts.cpp +++ b/apps/openmw/mwlua/localscripts.cpp @@ -90,18 +90,30 @@ namespace MWLua mData.mControls.controlledFromLua = false; mData.mControls.disableAI = false; this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData)); - registerEngineHandlers({&mOnActiveHandlers, &mOnInactiveHandlers}); + registerEngineHandlers({&mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers}); } - void LocalScripts::becomeActive() + void LocalScripts::receiveEngineEvent(const EngineEvent& event, ObjectRegistry*) { - mData.mIsActive = true; - callEngineHandlers(mOnActiveHandlers); - } - void LocalScripts::becomeInactive() - { - mData.mIsActive = false; - callEngineHandlers(mOnInactiveHandlers); + std::visit([this](auto&& arg) + { + using EventT = std::decay_t; + if constexpr (std::is_same_v) + { + mData.mIsActive = true; + callEngineHandlers(mOnActiveHandlers); + } + else if constexpr (std::is_same_v) + { + mData.mIsActive = false; + callEngineHandlers(mOnInactiveHandlers); + } + else + { + static_assert(std::is_same_v); + callEngineHandlers(mOnConsumeHandlers, arg.mRecordId); + } + }, event); } } diff --git a/apps/openmw/mwlua/localscripts.hpp b/apps/openmw/mwlua/localscripts.hpp index 40bff371a1..49612be441 100644 --- a/apps/openmw/mwlua/localscripts.hpp +++ b/apps/openmw/mwlua/localscripts.hpp @@ -31,14 +31,23 @@ namespace MWLua bool mIsActive; }; - void becomeActive(); - void becomeInactive(); + struct OnActive {}; + struct OnInactive {}; + struct OnConsume + { + std::string mRecordId; + }; + using EngineEvent = std::variant; + + void receiveEngineEvent(const EngineEvent&, ObjectRegistry*); + protected: LocalScripts(LuaUtil::LuaState* lua, const LObject& obj); SelfObject mData; private: EngineHandlerList mOnActiveHandlers{"onActive"}; EngineHandlerList mOnInactiveHandlers{"onInactive"}; + EngineHandlerList mOnConsumeHandlers{"onConsume"}; }; } diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index f695e1245b..604dde8495 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -100,6 +100,8 @@ namespace MWLua void LuaManager::update(bool paused, float dt) { + ObjectRegistry* objectRegistry = mWorldView.getObjectRegistry(); + if (!mPlayer.isEmpty()) { MWWorld::Ptr newPlayerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -108,7 +110,7 @@ namespace MWLua if (!mPlayer.isInCell() || !newPlayerPtr.isInCell() || mPlayer.getCell() != newPlayerPtr.getCell()) { mPlayer = newPlayerPtr; - mWorldView.getObjectRegistry()->registerPtr(mPlayer); + objectRegistry->registerPtr(mPlayer); } } mWorldView.update(); @@ -136,15 +138,15 @@ namespace MWLua // Receive events for (GlobalEvent& e : globalEvents) - mGlobalScripts.receiveEvent(e.eventName, e.eventData); + mGlobalScripts.receiveEvent(e.mEventName, e.mEventData); for (LocalEvent& e : localEvents) { - LObject obj(e.dest, mWorldView.getObjectRegistry()); + LObject obj(e.mDest, objectRegistry); LocalScripts* scripts = obj.isValid() ? obj.ptr().getRefData().getLuaScripts() : nullptr; if (scripts) - scripts->receiveEvent(e.eventName, e.eventData); + scripts->receiveEvent(e.mEventName, e.mEventData); else - Log(Debug::Debug) << "Ignored event " << e.eventName << " to L" << idToString(e.dest) + Log(Debug::Debug) << "Ignored event " << e.mEventName << " to L" << idToString(e.mDest) << ". Object not found or has no attached scripts"; } @@ -156,12 +158,19 @@ namespace MWLua } mKeyPressEvents.clear(); - for (LocalScripts* localScripts : mObjectInactiveEvents) - localScripts->becomeInactive(); - for (LocalScripts* localScripts : mObjectActiveEvents) - localScripts->becomeActive(); - mObjectActiveEvents.clear(); - mObjectInactiveEvents.clear(); + for (const LocalEngineEvent& e : mLocalEngineEvents) + { + LObject obj(e.mDest, objectRegistry); + if (!obj.isValid()) + { + Log(Debug::Verbose) << "Can not call engine handlers: object" << idToString(e.mDest) << " is not found"; + continue; + } + LocalScripts* scripts = obj.ptr().getRefData().getLuaScripts(); + if (scripts) + scripts->receiveEngineEvent(e.mEvent, objectRegistry); + } + mLocalEngineEvents.clear(); for (LocalScripts* scripts : mActiveLocalScripts) scripts->update(dt); @@ -170,11 +179,11 @@ namespace MWLua if (mPlayerChanged) { mPlayerChanged = false; - mGlobalScripts.playerAdded(GObject(getId(mPlayer), mWorldView.getObjectRegistry())); + mGlobalScripts.playerAdded(GObject(getId(mPlayer), objectRegistry)); } for (ObjectId id : mActorAddedEvents) - mGlobalScripts.actorActive(GObject(id, mWorldView.getObjectRegistry())); + mGlobalScripts.actorActive(GObject(id, objectRegistry)); mActorAddedEvents.clear(); mGlobalScripts.update(dt); @@ -203,8 +212,7 @@ namespace MWLua mGlobalEvents.clear(); mKeyPressEvents.clear(); mActorAddedEvents.clear(); - mObjectActiveEvents.clear(); - mObjectInactiveEvents.clear(); + mLocalEngineEvents.clear(); mPlayerChanged = false; mPlayerScripts = nullptr; mWorldView.clear(); @@ -228,7 +236,7 @@ namespace MWLua if (!mPlayerScripts) throw std::logic_error("mPlayerScripts not initialized"); mActiveLocalScripts.insert(mPlayerScripts); - mObjectActiveEvents.push_back(mPlayerScripts); + mLocalEngineEvents.push_back({getId(ptr), LocalScripts::OnActive{}}); mPlayerChanged = true; } @@ -240,7 +248,7 @@ namespace MWLua if (localScripts) { mActiveLocalScripts.insert(localScripts); - mObjectActiveEvents.push_back(localScripts); + mLocalEngineEvents.push_back({getId(ptr), LocalScripts::OnActive{}}); } if (ptr.getClass().isActor() && ptr != mPlayer) @@ -255,7 +263,7 @@ namespace MWLua { mActiveLocalScripts.erase(localScripts); if (!mWorldView.getObjectRegistry()->getPtr(getId(ptr), true).isEmpty()) - mObjectInactiveEvents.push_back(localScripts); + mLocalEngineEvents.push_back({getId(ptr), LocalScripts::OnInactive{}}); } } @@ -274,6 +282,11 @@ namespace MWLua mKeyPressEvents.push_back(arg.keysym); } + void LuaManager::appliedToObject(const MWWorld::Ptr& toPtr, std::string_view recordId, const MWWorld::Ptr& fromPtr) + { + mLocalEngineEvents.push_back({getId(toPtr), LocalScripts::OnConsume{std::string(recordId)}}); + } + MWBase::LuaManager::ActorControls* LuaManager::getActorControls(const MWWorld::Ptr& ptr) const { LocalScripts* localScripts = ptr.getRefData().getLuaScripts(); diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index d3191e8428..5cfadebc40 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -43,6 +43,7 @@ namespace MWLua void registerObject(const MWWorld::Ptr& ptr) override; void deregisterObject(const MWWorld::Ptr& ptr) override; void keyPressed(const SDL_KeyboardEvent &arg) override; + void appliedToObject(const MWWorld::Ptr& toPtr, std::string_view recordId, const MWWorld::Ptr& fromPtr) override; MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override; @@ -96,8 +97,13 @@ namespace MWLua std::vector mKeyPressEvents; std::vector mActorAddedEvents; - std::vector mObjectActiveEvents; - std::vector mObjectInactiveEvents; + + struct LocalEngineEvent + { + ObjectId mDest; + LocalScripts::EngineEvent mEvent; + }; + std::vector mLocalEngineEvents; // Queued actions that should be done in main thread. Processed by applyQueuedChanges(). std::vector> mActionQueue;