mirror of
https://github.com/OpenMW/openmw.git
synced 2025-04-11 12:36:45 +00:00
Merge branch 'lua_activate' into 'master'
Lua command `object:activateBy(actor)` and handler `onActivate` See merge request OpenMW/openmw!1618
This commit is contained in:
commit
406e950052
13 changed files with 86 additions and 8 deletions
|
@ -218,6 +218,7 @@ Programmers
|
||||||
tlmullis
|
tlmullis
|
||||||
tri4ng1e
|
tri4ng1e
|
||||||
Thoronador
|
Thoronador
|
||||||
|
Tobias Tribble (zackogenic)
|
||||||
Tom Lowe (Vulpen)
|
Tom Lowe (Vulpen)
|
||||||
Tom Mason (wheybags)
|
Tom Mason (wheybags)
|
||||||
Torben Leif Carrington (TorbenC)
|
Torben Leif Carrington (TorbenC)
|
||||||
|
@ -234,7 +235,6 @@ Programmers
|
||||||
Yuri Krupenin
|
Yuri Krupenin
|
||||||
zelurker
|
zelurker
|
||||||
Noah Gooder
|
Noah Gooder
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
|
|
@ -36,6 +36,7 @@ namespace MWBase
|
||||||
virtual void objectAddedToScene(const MWWorld::Ptr& ptr) = 0;
|
virtual void objectAddedToScene(const MWWorld::Ptr& ptr) = 0;
|
||||||
virtual void objectRemovedFromScene(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;
|
virtual void appliedToObject(const MWWorld::Ptr& toPtr, std::string_view recordId, const MWWorld::Ptr& fromPtr) = 0;
|
||||||
|
virtual void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0;
|
||||||
// TODO: notify LuaManager about other events
|
// TODO: notify LuaManager about other events
|
||||||
// virtual void objectOnHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object,
|
// 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;
|
// const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful) = 0;
|
||||||
|
|
|
@ -6,10 +6,13 @@
|
||||||
#include <components/lua/luastate.hpp>
|
#include <components/lua/luastate.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include <apps/openmw/mwbase/luamanager.hpp>
|
||||||
#include "../mwworld/class.hpp"
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include <apps/openmw/mwworld/action.hpp>
|
||||||
#include "../mwworld/player.hpp"
|
#include <apps/openmw/mwworld/cellstore.hpp>
|
||||||
|
#include <apps/openmw/mwworld/class.hpp>
|
||||||
|
#include <apps/openmw/mwworld/inventorystore.hpp>
|
||||||
|
#include <apps/openmw/mwworld/player.hpp>
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
|
@ -145,4 +148,24 @@ namespace MWLua
|
||||||
tryEquipToSlot(anySlot, item);
|
tryEquipToSlot(anySlot, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ActivateAction::apply(WorldView& worldView) const
|
||||||
|
{
|
||||||
|
MWWorld::Ptr object = worldView.getObjectRegistry()->getPtr(mObject, true);
|
||||||
|
if (object.isEmpty())
|
||||||
|
throw std::runtime_error(std::string("Object not found: " + idToString(mObject)));
|
||||||
|
MWWorld::Ptr actor = worldView.getObjectRegistry()->getPtr(mActor, true);
|
||||||
|
if (actor.isEmpty())
|
||||||
|
throw std::runtime_error(std::string("Actor not found: " + idToString(mActor)));
|
||||||
|
|
||||||
|
MWBase::Environment::get().getLuaManager()->objectActivated(object, actor);
|
||||||
|
std::shared_ptr<MWWorld::Action> action = object.getClass().activate(object, actor);
|
||||||
|
action->execute(actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ActivateAction::toString() const
|
||||||
|
{
|
||||||
|
return std::string("ActivateAction object=") + idToString(mObject) +
|
||||||
|
std::string(" actor=") + idToString(mActor);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,20 @@ namespace MWLua
|
||||||
Equipment mEquipment;
|
Equipment mEquipment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ActivateAction final : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActivateAction(LuaUtil::LuaState* state, ObjectId object, ObjectId actor)
|
||||||
|
: Action(state), mObject(object), mActor(actor) {}
|
||||||
|
|
||||||
|
void apply(WorldView&) const override;
|
||||||
|
std::string toString() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ObjectId mObject;
|
||||||
|
ObjectId mActor;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MWLUA_ACTIONS_H
|
#endif // MWLUA_ACTIONS_H
|
||||||
|
|
|
@ -88,7 +88,7 @@ namespace MWLua
|
||||||
: LuaUtil::ScriptsContainer(lua, "L" + idToString(obj.id()), autoStartMode), mData(obj)
|
: LuaUtil::ScriptsContainer(lua, "L" + idToString(obj.id()), autoStartMode), mData(obj)
|
||||||
{
|
{
|
||||||
this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData));
|
this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData));
|
||||||
registerEngineHandlers({&mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers});
|
registerEngineHandlers({&mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalScripts::receiveEngineEvent(const EngineEvent& event)
|
void LocalScripts::receiveEngineEvent(const EngineEvent& event)
|
||||||
|
@ -106,6 +106,10 @@ namespace MWLua
|
||||||
mData.mIsActive = false;
|
mData.mIsActive = false;
|
||||||
callEngineHandlers(mOnInactiveHandlers);
|
callEngineHandlers(mOnInactiveHandlers);
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_same_v<EventT, OnActivated>)
|
||||||
|
{
|
||||||
|
callEngineHandlers(mOnActivatedHandlers, arg.mActivatingActor);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static_assert(std::is_same_v<EventT, OnConsume>);
|
static_assert(std::is_same_v<EventT, OnConsume>);
|
||||||
|
|
|
@ -33,11 +33,15 @@ namespace MWLua
|
||||||
|
|
||||||
struct OnActive {};
|
struct OnActive {};
|
||||||
struct OnInactive {};
|
struct OnInactive {};
|
||||||
|
struct OnActivated
|
||||||
|
{
|
||||||
|
LObject mActivatingActor;
|
||||||
|
};
|
||||||
struct OnConsume
|
struct OnConsume
|
||||||
{
|
{
|
||||||
std::string mRecordId;
|
std::string mRecordId;
|
||||||
};
|
};
|
||||||
using EngineEvent = std::variant<OnActive, OnInactive, OnConsume>;
|
using EngineEvent = std::variant<OnActive, OnInactive, OnConsume, OnActivated>;
|
||||||
|
|
||||||
void receiveEngineEvent(const EngineEvent&);
|
void receiveEngineEvent(const EngineEvent&);
|
||||||
|
|
||||||
|
@ -48,6 +52,7 @@ namespace MWLua
|
||||||
EngineHandlerList mOnActiveHandlers{"onActive"};
|
EngineHandlerList mOnActiveHandlers{"onActive"};
|
||||||
EngineHandlerList mOnInactiveHandlers{"onInactive"};
|
EngineHandlerList mOnInactiveHandlers{"onInactive"};
|
||||||
EngineHandlerList mOnConsumeHandlers{"onConsume"};
|
EngineHandlerList mOnConsumeHandlers{"onConsume"};
|
||||||
|
EngineHandlerList mOnActivatedHandlers{"onActivated"};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,6 +352,11 @@ namespace MWLua
|
||||||
mLocalEngineEvents.push_back({getId(toPtr), LocalScripts::OnConsume{std::string(recordId)}});
|
mLocalEngineEvents.push_back({getId(toPtr), LocalScripts::OnConsume{std::string(recordId)}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaManager::objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor)
|
||||||
|
{
|
||||||
|
mLocalEngineEvents.push_back({getId(object), LocalScripts::OnActivated{LObject(getId(actor), mWorldView.getObjectRegistry())}});
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
@ -49,6 +49,7 @@ namespace MWLua
|
||||||
void deregisterObject(const MWWorld::Ptr& ptr) override;
|
void deregisterObject(const MWWorld::Ptr& ptr) override;
|
||||||
void inputEvent(const InputEvent& event) override { mInputEvents.push_back(event); }
|
void inputEvent(const InputEvent& event) override { mInputEvents.push_back(event); }
|
||||||
void appliedToObject(const MWWorld::Ptr& toPtr, std::string_view recordId, const MWWorld::Ptr& fromPtr) override;
|
void appliedToObject(const MWWorld::Ptr& toPtr, std::string_view recordId, const MWWorld::Ptr& fromPtr) override;
|
||||||
|
void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) override;
|
||||||
|
|
||||||
MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override;
|
MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override;
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,14 @@ namespace MWLua
|
||||||
const MWWorld::Class& cls = o.ptr().getClass();
|
const MWWorld::Class& cls = o.ptr().getClass();
|
||||||
return cls.getWalkSpeed(o.ptr());
|
return cls.getWalkSpeed(o.ptr());
|
||||||
};
|
};
|
||||||
|
objectT["activateBy"] = [context](const ObjectT& o, const ObjectT& actor)
|
||||||
|
{
|
||||||
|
uint32_t esmRecordType = actor.ptr().getType();
|
||||||
|
if (esmRecordType != ESM::REC_CREA && esmRecordType != ESM::REC_NPC_)
|
||||||
|
throw std::runtime_error("The argument of `activateBy` must be an actor who activates the object. Got: " +
|
||||||
|
ptrToString(actor.ptr()));
|
||||||
|
context.mLuaManager->addAction(std::make_unique<ActivateAction>(context.mLua, o.id(), actor.id()));
|
||||||
|
};
|
||||||
|
|
||||||
if constexpr (std::is_same_v<ObjectT, GObject>)
|
if constexpr (std::is_same_v<ObjectT, GObject>)
|
||||||
{ // Only for global scripts
|
{ // Only for global scripts
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "../mwbase/scriptmanager.hpp"
|
#include "../mwbase/scriptmanager.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/inputmanager.hpp"
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
#include "../mwbase/luamanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/action.hpp"
|
#include "../mwworld/action.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -417,6 +418,7 @@ namespace MWScript
|
||||||
|
|
||||||
void InterpreterContext::executeActivation(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor)
|
void InterpreterContext::executeActivation(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
|
MWBase::Environment::get().getLuaManager()->objectActivated(ptr, actor);
|
||||||
std::shared_ptr<MWWorld::Action> action = (ptr.getClass().activate(ptr, actor));
|
std::shared_ptr<MWWorld::Action> action = (ptr.getClass().activate(ptr, actor));
|
||||||
action->execute (actor);
|
action->execute (actor);
|
||||||
if (action->getTarget() != MWWorld::Ptr() && action->getTarget() != ptr)
|
if (action->getTarget() != MWWorld::Ptr() && action->getTarget() != ptr)
|
||||||
|
|
|
@ -3827,7 +3827,8 @@ namespace MWWorld
|
||||||
|
|
||||||
if (object.getRefData().activate())
|
if (object.getRefData().activate())
|
||||||
{
|
{
|
||||||
std::shared_ptr<MWWorld::Action> action = (object.getClass().activate(object, actor));
|
MWBase::Environment::get().getLuaManager()->objectActivated(object, actor);
|
||||||
|
std::shared_ptr<MWWorld::Action> action = object.getClass().activate(object, actor);
|
||||||
action->execute (actor);
|
action->execute (actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,12 @@ Engine handler is a function defined by a script, that can be called by the engi
|
||||||
| | | can not access anything nearby, but it is possible to send |
|
| | | can not access anything nearby, but it is possible to send |
|
||||||
| | | an event to global scripts. |
|
| | | an event to global scripts. |
|
||||||
+----------------------------------+----------------------------------------------------------------------+
|
+----------------------------------+----------------------------------------------------------------------+
|
||||||
|
| onActivated(actor) | | Called on an object when an actor activates it. Note that picking |
|
||||||
|
| | | up an item is also an activation and works this way: (1) a copy of |
|
||||||
|
| | | the item is placed to the actor's inventory, (2) count of |
|
||||||
|
| | | the original item is set to zero, (3) and only then onActivated is |
|
||||||
|
| | | called on the original item, so self.count is already zero. |
|
||||||
|
+----------------------------------+----------------------------------------------------------------------+
|
||||||
| onConsume(recordId) | | Called if `recordId` (e.g. a potion) is consumed. |
|
| onConsume(recordId) | | Called if `recordId` (e.g. a potion) is consumed. |
|
||||||
+----------------------------------+----------------------------------------------------------------------+
|
+----------------------------------+----------------------------------------------------------------------+
|
||||||
| **Only for local scripts attached to a player** |
|
| **Only for local scripts attached to a player** |
|
||||||
|
|
|
@ -217,6 +217,14 @@
|
||||||
-- @param #string eventName
|
-- @param #string eventName
|
||||||
-- @param eventData
|
-- @param eventData
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Activate the object.
|
||||||
|
-- @function [parent=#GameObject] activateBy
|
||||||
|
-- @param self
|
||||||
|
-- @param #GameObject actor The actor who activates the object
|
||||||
|
-- @usage local self = require('openmw.self')
|
||||||
|
-- object:activateBy(self)
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Returns `true` if the item is equipped on the object.
|
-- Returns `true` if the item is equipped on the object.
|
||||||
-- @function [parent=#GameObject] isEquipped
|
-- @function [parent=#GameObject] isEquipped
|
||||||
|
|
Loading…
Reference in a new issue