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 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;

@ -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);
}

@ -14,10 +14,10 @@ namespace MWLua
template <typename 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);
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);
}
}

@ -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<GlobalEvent>;
using LocalEventQueue = std::vector<LocalEvent>;

@ -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<decltype(arg)>;
if constexpr (std::is_same_v<EventT, OnActive>)
{
mData.mIsActive = true;
callEngineHandlers(mOnActiveHandlers);
}
else if constexpr (std::is_same_v<EventT, OnInactive>)
{
mData.mIsActive = false;
callEngineHandlers(mOnInactiveHandlers);
}
else
{
static_assert(std::is_same_v<EventT, OnConsume>);
callEngineHandlers(mOnConsumeHandlers, arg.mRecordId);
}
}, event);
}
}

@ -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<OnActive, OnInactive, OnConsume>;
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"};
};
}

@ -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();

@ -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<SDL_Keysym> mKeyPressEvents;
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().
std::vector<std::unique_ptr<Action>> mActionQueue;

Loading…
Cancel
Save