From 6792cf02b24c151f868df1ef4e6c3a60c7e73887 Mon Sep 17 00:00:00 2001 From: uramer Date: Mon, 5 Feb 2024 18:46:01 +0100 Subject: [PATCH] Group owner bindings into a table --- apps/openmw/mwlua/object.hpp | 6 ++ apps/openmw/mwlua/objectbindings.cpp | 137 +++++++++++++++------------ files/lua_api/openmw/core.lua | 12 ++- 3 files changed, 90 insertions(+), 65 deletions(-) diff --git a/apps/openmw/mwlua/object.hpp b/apps/openmw/mwlua/object.hpp index b42b092302..d032515314 100644 --- a/apps/openmw/mwlua/object.hpp +++ b/apps/openmw/mwlua/object.hpp @@ -71,6 +71,12 @@ namespace MWLua { Obj mObj; }; + + template + struct Owner + { + Obj mObj; + }; } #endif // MWLUA_OBJECT_H diff --git a/apps/openmw/mwlua/objectbindings.cpp b/apps/openmw/mwlua/objectbindings.cpp index 2a30e31948..c594af2944 100644 --- a/apps/openmw/mwlua/objectbindings.cpp +++ b/apps/openmw/mwlua/objectbindings.cpp @@ -200,6 +200,80 @@ namespace MWLua return Misc::Convert::makeOsgQuat(pos.rot); } + template + void addOwnerbindings(sol::usertype& objectT, const std::string& prefix, const Context& context) + { + using OwnerT = Owner; + sol::usertype ownerT = context.mLua->sol().new_usertype(prefix + "Owner"); + + ownerT[sol::meta_function::to_string] = [](const OwnerT& o) { return "Owner[" + o.mObj.toString() + "]"; }; + + auto getOwnerRecordId = [](const OwnerT& o) -> sol::optional { + ESM::RefId owner = o.mObj.ptr().getCellRef().getOwner(); + if (owner.empty()) + return sol::nullopt; + else + return owner.serializeText(); + }; + auto setOwnerRecordId = [](const OwnerT& o, sol::optional ownerId) { + if (std::is_same_v && !dynamic_cast(&o.mObj)) + throw std::runtime_error("Local scripts can set an owner only on self"); + const MWWorld::Ptr& ptr = o.mObj.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); + }; + ownerT["recordId"] = sol::property(getOwnerRecordId, setOwnerRecordId); + + auto getOwnerFactionId = [](const OwnerT& o) -> sol::optional { + ESM::RefId owner = o.mObj.ptr().getCellRef().getFaction(); + if (owner.empty()) + return sol::nullopt; + else + return owner.serializeText(); + }; + auto setOwnerFactionId = [](const OwnerT& o, sol::optional ownerId) { + ESM::RefId ownerFac; + if (std::is_same_v && !dynamic_cast(&o.mObj)) + throw std::runtime_error("Local scripts can set an owner faction only on self"); + if (!ownerId) + { + o.mObj.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"); + o.mObj.ptr().getCellRef().setFaction(ownerFac); + }; + ownerT["factionId"] = sol::property(getOwnerFactionId, setOwnerFactionId); + + auto getOwnerFactionRank = [](const OwnerT& o) -> sol::optional { + int rank = o.mObj.ptr().getCellRef().getFactionRank(); + if (rank < 0) + return sol::nullopt; + else + return rank; + }; + auto setOwnerFactionRank = [](const OwnerT& o, sol::optional factionRank) { + if (std::is_same_v && !dynamic_cast(&o.mObj)) + throw std::runtime_error("Local scripts can set an owner faction rank only on self"); + o.mObj.ptr().getCellRef().setFactionRank(factionRank.value_or(-1)); + }; + ownerT["factionRank"] = sol::property(getOwnerFactionRank, setOwnerFactionRank); + + objectT["owner"] = sol::readonly_property([](const ObjectT& object) { return OwnerT{ object }; }); + } + template void addBasicBindings(sol::usertype& objectT, const Context& context) { @@ -266,68 +340,6 @@ 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) -> sol::optional { - int rank = o.ptr().getCellRef().getFactionRank(); - if (rank < 0) - return sol::nullopt; - else - return rank; - }; - auto setOwnerFactionRank = [](const ObjectT& object, sol::optional 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.value_or(-1)); - }; - objectT["ownerFactionRank"] = sol::property(getOwnerFactionRank, setOwnerFactionRank); objectT["activateBy"] = [](const ObjectT& object, const ObjectT& actor) { const MWWorld::Ptr& objPtr = object.ptr(); @@ -672,6 +684,7 @@ namespace MWLua = context.mLua->sol().new_usertype(prefix + "Object", sol::base_classes, sol::bases()); addBasicBindings(objectT, context); addInventoryBindings(objectT, prefix, context); + addOwnerbindings(objectT, prefix, context); registerObjectList(prefix, context); } diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index 33f21a6cce..ca2da8bb23 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -164,9 +164,7 @@ -- @field openmw.util#Transform rotation Object rotation. -- @field openmw.util#Vector3 startingPosition The object original position -- @field openmw.util#Transform startingRotation The object original rotation --- @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 (`nil` if any rank is allowed). Global and self scripts can set the value. +-- @field #ObjectOwner owner Ownership information -- @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 #GameObject parentContainer Container or actor that contains (or has in inventory) this object. It is nil if the object is in a cell. -- @field #any type Type of the object (one of the tables from the package @{openmw.types#types}). @@ -174,6 +172,14 @@ -- @field #string recordId Returns record ID of the object in lowercase. -- @field #string globalVariable Global Variable associated with this object(read only). + +--- +-- Object owner information +-- @type ObjectOwner +-- @field #string recordId NPC who owns the object (nil if missing). Global and self scripts can set the value. +-- @field #string factionId Faction who owns the object (nil if missing). Global and self scripts can set the value. +-- @field #number factionRank Rank required to be allowed to pick up the object (`nil` if any rank is allowed). Global and self scripts can set the value. + --- -- Does the object still exist and is available. -- Returns true if the object exists and loaded, and false otherwise. If false, then every