From f6fb05d1caec0f1a53997af1853089dca50d06ee Mon Sep 17 00:00:00 2001 From: Zackhasacat Date: Tue, 25 Apr 2023 21:20:43 +0000 Subject: [PATCH] Add functionality for lua to view and modify ownership data for GameObjects --- apps/openmw/mwlua/objectbindings.cpp | 58 ++++++++++++++++++++++++++++ files/lua_api/openmw/core.lua | 3 ++ files/lua_api/openmw/self.lua | 11 +++++- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwlua/objectbindings.cpp b/apps/openmw/mwlua/objectbindings.cpp index 68db67f0b7..e99648f1ed 100644 --- a/apps/openmw/mwlua/objectbindings.cpp +++ b/apps/openmw/mwlua/objectbindings.cpp @@ -1,5 +1,7 @@ #include "luabindings.hpp" +#include +#include #include #include "../mwworld/cellstore.hpp" @@ -142,6 +144,62 @@ namespace MWLua context.mLuaEvents->addLocalEvent( { dest.id(), std::move(eventName), LuaUtil::serialize(eventData, context.mSerializer) }); }; + auto getOwnerRecordId = [](const ObjectT& o) -> sol::optional { + ESM::RefId owner = o.ptr().getCellRef().getOwner(); + if (owner.empty()) + return sol::nullopt; + else + return owner.serializeText(); + }; + auto setOwnerRecordId = [](const ObjectT& obj, sol::optional ownerId) { + if (std::is_same_v && !dynamic_cast(&obj)) + throw std::runtime_error("Local scripts can set an owner only on self"); + const MWWorld::Ptr& ptr = obj.ptr(); + + if (!ownerId) + { + ptr.getCellRef().setOwner(ESM::RefId()); + return; + } + ESM::RefId owner = ESM::RefId::deserializeText(*ownerId); + const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore(); + if (!store.get().search(owner)) + throw std::runtime_error("Invalid owner record id"); + ptr.getCellRef().setOwner(owner); + }; + objectT["ownerRecordId"] = sol::property(getOwnerRecordId, setOwnerRecordId); + + auto getOwnerFactionId = [](const ObjectT& o) -> sol::optional { + ESM::RefId owner = o.ptr().getCellRef().getFaction(); + if (owner.empty()) + return sol::nullopt; + else + return owner.serializeText(); + }; + auto setOwnerFactionId = [](const ObjectT& object, sol::optional ownerId) { + ESM::RefId ownerFac; + if (std::is_same_v && !dynamic_cast(&object)) + throw std::runtime_error("Local scripts can set an owner faction only on self"); + if (!ownerId) + { + object.ptr().getCellRef().setFaction(ESM::RefId()); + return; + } + ownerFac = ESM::RefId::deserializeText(*ownerId); + const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore(); + if (!store.get().search(ownerFac)) + throw std::runtime_error("Invalid owner faction id"); + object.ptr().getCellRef().setFaction(ownerFac); + }; + objectT["ownerFactionId"] = sol::property(getOwnerFactionId, setOwnerFactionId); + + auto getOwnerFactionRank = [](const ObjectT& o) -> int { return o.ptr().getCellRef().getFactionRank(); }; + auto setOwnerFactionRank = [](const ObjectT& object, int factionRank) { + if (std::is_same_v && !dynamic_cast(&object)) + throw std::runtime_error("Local scripts can set an owner faction rank only on self"); + object.ptr().getCellRef().setFactionRank(factionRank); + }; + objectT["ownerFactionRank"] = sol::property(getOwnerFactionRank, setOwnerFactionRank); objectT["activateBy"] = [](const ObjectT& object, const ObjectT& actor) { const MWWorld::Ptr& objPtr = object.ptr(); diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index 5e2055215f..0312ba8706 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -111,6 +111,9 @@ -- @field #boolean enabled Whether the object is enabled or disabled. Global scripts can set the value. Items in containers or inventories can't be disabled. -- @field openmw.util#Vector3 position Object position. -- @field openmw.util#Vector3 rotation Object rotation (ZXY order). +-- @field #string ownerRecordId NPC who owns the object (nil if missing). Global and self scripts can set the value. +-- @field #string ownerFactionId Faction who owns the object (nil if missing). Global and self scripts can set the value. +-- @field #number ownerFactionRank Rank required to be allowed to pick up the object. Global and self scripts can set the value. -- @field #Cell cell The cell where the object currently is. During loading a game and for objects in an inventory or a container `cell` is nil. -- @field #any type Type of the object (one of the tables from the package @{openmw.types#types}). -- @field #number count Count (>1 means a stack of objects). diff --git a/files/lua_api/openmw/self.lua b/files/lua_api/openmw/self.lua index 48d4f5914b..70d35b5b71 100644 --- a/files/lua_api/openmw/self.lua +++ b/files/lua_api/openmw/self.lua @@ -22,6 +22,16 @@ -- The object the script is attached to (readonly) -- @field [parent=#self] openmw.core#GameObject object +--- NPC who owns the object or `nil` (mutable). +-- @field [parent=#self] #string ownerRecordId + +--- Faction who owns the object or `nil` (mutable). +-- @field [parent=#self] #string ownerFactionId + +--- Rank required to be allowed to pick up the object (mutable). +-- @field [parent=#self] #number ownerFactionRank + + --- -- Movement controls (only for actors) -- @field [parent=#self] #ActorControls controls @@ -55,4 +65,3 @@ -- @param #boolean v return nil -