mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-18 13:12:50 +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
@ -218,6 +218,7 @@ Programmers
|
||||
tlmullis
|
||||
tri4ng1e
|
||||
Thoronador
|
||||
Tobias Tribble (zackogenic)
|
||||
Tom Lowe (Vulpen)
|
||||
Tom Mason (wheybags)
|
||||
Torben Leif Carrington (TorbenC)
|
||||
@ -234,7 +235,6 @@ Programmers
|
||||
Yuri Krupenin
|
||||
zelurker
|
||||
Noah Gooder
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
@ -36,6 +36,7 @@ namespace MWBase
|
||||
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;
|
||||
virtual void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 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;
|
||||
|
@ -6,10 +6,13 @@
|
||||
#include <components/lua/luastate.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include <apps/openmw/mwbase/luamanager.hpp>
|
||||
|
||||
#include <apps/openmw/mwworld/action.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
|
||||
{
|
||||
@ -145,4 +148,24 @@ namespace MWLua
|
||||
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;
|
||||
};
|
||||
|
||||
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
|
||||
|
@ -88,7 +88,7 @@ namespace MWLua
|
||||
: LuaUtil::ScriptsContainer(lua, "L" + idToString(obj.id()), autoStartMode), mData(obj)
|
||||
{
|
||||
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)
|
||||
@ -106,6 +106,10 @@ namespace MWLua
|
||||
mData.mIsActive = false;
|
||||
callEngineHandlers(mOnInactiveHandlers);
|
||||
}
|
||||
else if constexpr (std::is_same_v<EventT, OnActivated>)
|
||||
{
|
||||
callEngineHandlers(mOnActivatedHandlers, arg.mActivatingActor);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::is_same_v<EventT, OnConsume>);
|
||||
|
@ -33,11 +33,15 @@ namespace MWLua
|
||||
|
||||
struct OnActive {};
|
||||
struct OnInactive {};
|
||||
struct OnActivated
|
||||
{
|
||||
LObject mActivatingActor;
|
||||
};
|
||||
struct OnConsume
|
||||
{
|
||||
std::string mRecordId;
|
||||
};
|
||||
using EngineEvent = std::variant<OnActive, OnInactive, OnConsume>;
|
||||
using EngineEvent = std::variant<OnActive, OnInactive, OnConsume, OnActivated>;
|
||||
|
||||
void receiveEngineEvent(const EngineEvent&);
|
||||
|
||||
@ -48,6 +52,7 @@ namespace MWLua
|
||||
EngineHandlerList mOnActiveHandlers{"onActive"};
|
||||
EngineHandlerList mOnInactiveHandlers{"onInactive"};
|
||||
EngineHandlerList mOnConsumeHandlers{"onConsume"};
|
||||
EngineHandlerList mOnActivatedHandlers{"onActivated"};
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -352,6 +352,11 @@ namespace MWLua
|
||||
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
|
||||
{
|
||||
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
|
||||
|
@ -49,6 +49,7 @@ namespace MWLua
|
||||
void deregisterObject(const MWWorld::Ptr& ptr) override;
|
||||
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 objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) override;
|
||||
|
||||
MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override;
|
||||
|
||||
|
@ -137,6 +137,14 @@ namespace MWLua
|
||||
const MWWorld::Class& cls = o.ptr().getClass();
|
||||
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>)
|
||||
{ // Only for global scripts
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "../mwbase/scriptmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/luamanager.hpp"
|
||||
|
||||
#include "../mwworld/action.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
@ -417,6 +418,7 @@ namespace MWScript
|
||||
|
||||
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));
|
||||
action->execute (actor);
|
||||
if (action->getTarget() != MWWorld::Ptr() && action->getTarget() != ptr)
|
||||
|
@ -3827,7 +3827,8 @@ namespace MWWorld
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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 |
|
||||
| | | 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. |
|
||||
+----------------------------------+----------------------------------------------------------------------+
|
||||
| **Only for local scripts attached to a player** |
|
||||
|
@ -217,6 +217,14 @@
|
||||
-- @param #string eventName
|
||||
-- @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.
|
||||
-- @function [parent=#GameObject] isEquipped
|
||||
|
Loading…
x
Reference in New Issue
Block a user