mirror of
https://github.com/OpenMW/openmw.git
synced 2025-07-03 08:11:35 +00:00
Add LocalScripts::LocalEngineEvent. Add OnConsume
engine handler.
This commit is contained in:
parent
1268597676
commit
b1a6441c23
8 changed files with 90 additions and 43 deletions
|
@ -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…
Reference in a new issue