Add LocalScripts::LocalEngineEvent. Add `OnConsume` engine handler.

dont-compose-content
Petr Mikheev 4 years ago
parent 1268597676
commit b1a6441c23

@ -29,11 +29,16 @@ namespace MWBase
virtual ~LuaManager() = default; virtual ~LuaManager() = default;
virtual void newGameStarted() = 0; virtual void newGameStarted() = 0;
virtual void objectAddedToScene(const MWWorld::Ptr& ptr) = 0; virtual void keyPressed(const SDL_KeyboardEvent &arg) = 0;
virtual void objectRemovedFromScene(const MWWorld::Ptr& ptr) = 0;
virtual void registerObject(const MWWorld::Ptr& ptr) = 0; virtual void registerObject(const MWWorld::Ptr& ptr) = 0;
virtual void deregisterObject(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 { struct ActorControls {
bool disableAI; bool disableAI;

@ -17,6 +17,7 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/dialoguemanager.hpp" #include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwbase/luamanager.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
@ -1095,6 +1096,7 @@ namespace MWClass
bool Npc::apply (const MWWorld::Ptr& ptr, const std::string& id, bool Npc::apply (const MWWorld::Ptr& ptr, const std::string& id,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
MWBase::Environment::get().getLuaManager()->appliedToObject(ptr, id, actor);
MWMechanics::CastSpell cast(ptr, ptr); MWMechanics::CastSpell cast(ptr, ptr);
return cast.cast(id); return cast.cast(id);
} }

@ -14,10 +14,10 @@ namespace MWLua
template <typename Event> template <typename Event>
void saveEvent(ESM::ESMWriter& esm, const ObjectId& dest, const Event& event) 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); dest.save(esm, true);
if (!event.eventData.empty()) if (!event.mEventData.empty())
saveLuaBinaryData(esm, event.eventData); saveLuaBinaryData(esm, event.mEventData);
} }
void loadEvents(sol::state& lua, ESM::ESMReader& esm, GlobalEventQueue& globalEvents, LocalEventQueue& localEvents, void loadEvents(sol::state& lua, ESM::ESMReader& esm, GlobalEventQueue& globalEvents, LocalEventQueue& localEvents,
@ -57,7 +57,7 @@ namespace MWLua
for (const GlobalEvent& e : globalEvents) for (const GlobalEvent& e : globalEvents)
saveEvent(esm, globalId, e); saveEvent(esm, globalId, e);
for (const LocalEvent& e : localEvents) for (const LocalEvent& e : localEvents)
saveEvent(esm, e.dest, e); saveEvent(esm, e.mDest, e);
} }
} }

@ -23,14 +23,14 @@ namespace MWLua
{ {
struct GlobalEvent struct GlobalEvent
{ {
std::string eventName; std::string mEventName;
std::string eventData; std::string mEventData;
}; };
struct LocalEvent struct LocalEvent
{ {
ObjectId dest; ObjectId mDest;
std::string eventName; std::string mEventName;
std::string eventData; std::string mEventData;
}; };
using GlobalEventQueue = std::vector<GlobalEvent>; using GlobalEventQueue = std::vector<GlobalEvent>;
using LocalEventQueue = std::vector<LocalEvent>; using LocalEventQueue = std::vector<LocalEvent>;

@ -90,18 +90,30 @@ namespace MWLua
mData.mControls.controlledFromLua = false; mData.mControls.controlledFromLua = false;
mData.mControls.disableAI = false; mData.mControls.disableAI = false;
this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData)); 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*)
{
std::visit([this](auto&& arg)
{
using EventT = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<EventT, OnActive>)
{ {
mData.mIsActive = true; mData.mIsActive = true;
callEngineHandlers(mOnActiveHandlers); callEngineHandlers(mOnActiveHandlers);
} }
void LocalScripts::becomeInactive() else if constexpr (std::is_same_v<EventT, OnInactive>)
{ {
mData.mIsActive = false; mData.mIsActive = false;
callEngineHandlers(mOnInactiveHandlers); callEngineHandlers(mOnInactiveHandlers);
} }
else
{
static_assert(std::is_same_v<EventT, OnConsume>);
callEngineHandlers(mOnConsumeHandlers, arg.mRecordId);
}
}, event);
}
} }

@ -31,14 +31,23 @@ namespace MWLua
bool mIsActive; bool mIsActive;
}; };
void becomeActive(); struct OnActive {};
void becomeInactive(); struct OnInactive {};
struct OnConsume
{
std::string mRecordId;
};
using EngineEvent = std::variant<OnActive, OnInactive, OnConsume>;
void receiveEngineEvent(const EngineEvent&, ObjectRegistry*);
protected: protected:
LocalScripts(LuaUtil::LuaState* lua, const LObject& obj); LocalScripts(LuaUtil::LuaState* lua, const LObject& obj);
SelfObject mData; SelfObject mData;
private: private:
EngineHandlerList mOnActiveHandlers{"onActive"}; EngineHandlerList mOnActiveHandlers{"onActive"};
EngineHandlerList mOnInactiveHandlers{"onInactive"}; EngineHandlerList mOnInactiveHandlers{"onInactive"};
EngineHandlerList mOnConsumeHandlers{"onConsume"};
}; };
} }

@ -100,6 +100,8 @@ namespace MWLua
void LuaManager::update(bool paused, float dt) void LuaManager::update(bool paused, float dt)
{ {
ObjectRegistry* objectRegistry = mWorldView.getObjectRegistry();
if (!mPlayer.isEmpty()) if (!mPlayer.isEmpty())
{ {
MWWorld::Ptr newPlayerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr newPlayerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr();
@ -108,7 +110,7 @@ namespace MWLua
if (!mPlayer.isInCell() || !newPlayerPtr.isInCell() || mPlayer.getCell() != newPlayerPtr.getCell()) if (!mPlayer.isInCell() || !newPlayerPtr.isInCell() || mPlayer.getCell() != newPlayerPtr.getCell())
{ {
mPlayer = newPlayerPtr; mPlayer = newPlayerPtr;
mWorldView.getObjectRegistry()->registerPtr(mPlayer); objectRegistry->registerPtr(mPlayer);
} }
} }
mWorldView.update(); mWorldView.update();
@ -136,15 +138,15 @@ namespace MWLua
// Receive events // Receive events
for (GlobalEvent& e : globalEvents) for (GlobalEvent& e : globalEvents)
mGlobalScripts.receiveEvent(e.eventName, e.eventData); mGlobalScripts.receiveEvent(e.mEventName, e.mEventData);
for (LocalEvent& e : localEvents) for (LocalEvent& e : localEvents)
{ {
LObject obj(e.dest, mWorldView.getObjectRegistry()); LObject obj(e.mDest, objectRegistry);
LocalScripts* scripts = obj.isValid() ? obj.ptr().getRefData().getLuaScripts() : nullptr; LocalScripts* scripts = obj.isValid() ? obj.ptr().getRefData().getLuaScripts() : nullptr;
if (scripts) if (scripts)
scripts->receiveEvent(e.eventName, e.eventData); scripts->receiveEvent(e.mEventName, e.mEventData);
else 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"; << ". Object not found or has no attached scripts";
} }
@ -156,12 +158,19 @@ namespace MWLua
} }
mKeyPressEvents.clear(); mKeyPressEvents.clear();
for (LocalScripts* localScripts : mObjectInactiveEvents) for (const LocalEngineEvent& e : mLocalEngineEvents)
localScripts->becomeInactive(); {
for (LocalScripts* localScripts : mObjectActiveEvents) LObject obj(e.mDest, objectRegistry);
localScripts->becomeActive(); if (!obj.isValid())
mObjectActiveEvents.clear(); {
mObjectInactiveEvents.clear(); 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) for (LocalScripts* scripts : mActiveLocalScripts)
scripts->update(dt); scripts->update(dt);
@ -170,11 +179,11 @@ namespace MWLua
if (mPlayerChanged) if (mPlayerChanged)
{ {
mPlayerChanged = false; mPlayerChanged = false;
mGlobalScripts.playerAdded(GObject(getId(mPlayer), mWorldView.getObjectRegistry())); mGlobalScripts.playerAdded(GObject(getId(mPlayer), objectRegistry));
} }
for (ObjectId id : mActorAddedEvents) for (ObjectId id : mActorAddedEvents)
mGlobalScripts.actorActive(GObject(id, mWorldView.getObjectRegistry())); mGlobalScripts.actorActive(GObject(id, objectRegistry));
mActorAddedEvents.clear(); mActorAddedEvents.clear();
mGlobalScripts.update(dt); mGlobalScripts.update(dt);
@ -203,8 +212,7 @@ namespace MWLua
mGlobalEvents.clear(); mGlobalEvents.clear();
mKeyPressEvents.clear(); mKeyPressEvents.clear();
mActorAddedEvents.clear(); mActorAddedEvents.clear();
mObjectActiveEvents.clear(); mLocalEngineEvents.clear();
mObjectInactiveEvents.clear();
mPlayerChanged = false; mPlayerChanged = false;
mPlayerScripts = nullptr; mPlayerScripts = nullptr;
mWorldView.clear(); mWorldView.clear();
@ -228,7 +236,7 @@ namespace MWLua
if (!mPlayerScripts) if (!mPlayerScripts)
throw std::logic_error("mPlayerScripts not initialized"); throw std::logic_error("mPlayerScripts not initialized");
mActiveLocalScripts.insert(mPlayerScripts); mActiveLocalScripts.insert(mPlayerScripts);
mObjectActiveEvents.push_back(mPlayerScripts); mLocalEngineEvents.push_back({getId(ptr), LocalScripts::OnActive{}});
mPlayerChanged = true; mPlayerChanged = true;
} }
@ -240,7 +248,7 @@ namespace MWLua
if (localScripts) if (localScripts)
{ {
mActiveLocalScripts.insert(localScripts); mActiveLocalScripts.insert(localScripts);
mObjectActiveEvents.push_back(localScripts); mLocalEngineEvents.push_back({getId(ptr), LocalScripts::OnActive{}});
} }
if (ptr.getClass().isActor() && ptr != mPlayer) if (ptr.getClass().isActor() && ptr != mPlayer)
@ -255,7 +263,7 @@ namespace MWLua
{ {
mActiveLocalScripts.erase(localScripts); mActiveLocalScripts.erase(localScripts);
if (!mWorldView.getObjectRegistry()->getPtr(getId(ptr), true).isEmpty()) 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); 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 MWBase::LuaManager::ActorControls* LuaManager::getActorControls(const MWWorld::Ptr& ptr) const
{ {
LocalScripts* localScripts = ptr.getRefData().getLuaScripts(); LocalScripts* localScripts = ptr.getRefData().getLuaScripts();

@ -43,6 +43,7 @@ namespace MWLua
void registerObject(const MWWorld::Ptr& ptr) override; void registerObject(const MWWorld::Ptr& ptr) override;
void deregisterObject(const MWWorld::Ptr& ptr) override; void deregisterObject(const MWWorld::Ptr& ptr) override;
void keyPressed(const SDL_KeyboardEvent &arg) 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; MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override;
@ -96,8 +97,13 @@ namespace MWLua
std::vector<SDL_Keysym> mKeyPressEvents; std::vector<SDL_Keysym> mKeyPressEvents;
std::vector<ObjectId> mActorAddedEvents; std::vector<ObjectId> mActorAddedEvents;
std::vector<LocalScripts*> mObjectActiveEvents;
std::vector<LocalScripts*> mObjectInactiveEvents; struct LocalEngineEvent
{
ObjectId mDest;
LocalScripts::EngineEvent mEvent;
};
std::vector<LocalEngineEvent> mLocalEngineEvents;
// Queued actions that should be done in main thread. Processed by applyQueuedChanges(). // Queued actions that should be done in main thread. Processed by applyQueuedChanges().
std::vector<std::unique_ptr<Action>> mActionQueue; std::vector<std::unique_ptr<Action>> mActionQueue;

Loading…
Cancel
Save