From 2bfffb3063c6031bbec3b025b298bc9a3bc71d26 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Mon, 6 Mar 2023 02:31:58 +0100 Subject: [PATCH] Move `std::variant` from mwlua/stats.cpp to mwlua/objectvariant.hpp --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwlua/localscripts.cpp | 2 +- apps/openmw/mwlua/localscripts.hpp | 80 +++++++++---------- apps/openmw/mwlua/objectvariant.hpp | 55 +++++++++++++ apps/openmw/mwlua/stats.cpp | 119 ++++++++++------------------ apps/openmw/mwlua/types/actor.cpp | 2 - 6 files changed, 139 insertions(+), 121 deletions(-) create mode 100644 apps/openmw/mwlua/objectvariant.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 15a6b8713c..f9f4905421 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -59,7 +59,7 @@ add_openmw_dir (mwscript ) add_openmw_dir (mwlua - luamanagerimp object worldview userdataserializer eventqueue + luamanagerimp object worldview userdataserializer eventqueue objectvariant luabindings localscripts playerscripts objectbindings cellbindings camerabindings uibindings inputbindings nearbybindings postprocessingbindings stats debugbindings types/types types/door types/actor types/container types/weapon types/npc types/creature types/activator types/book types/lockpick types/probe types/apparatus types/potion types/ingredient types/misc types/repair types/armor types/light types/static types/clothing diff --git a/apps/openmw/mwlua/localscripts.cpp b/apps/openmw/mwlua/localscripts.cpp index e3e46d453f..1b9984fc66 100644 --- a/apps/openmw/mwlua/localscripts.cpp +++ b/apps/openmw/mwlua/localscripts.cpp @@ -33,7 +33,7 @@ namespace sol { }; template <> - struct is_automagical : std::false_type + struct is_automagical : std::false_type { }; template <> diff --git a/apps/openmw/mwlua/localscripts.hpp b/apps/openmw/mwlua/localscripts.hpp index 26c8668b5a..bad7300849 100644 --- a/apps/openmw/mwlua/localscripts.hpp +++ b/apps/openmw/mwlua/localscripts.hpp @@ -16,6 +16,46 @@ namespace MWLua { struct Context; + struct SelfObject : public LObject + { + class CachedStat + { + public: + using Setter = void (*)(int, std::string_view, const MWWorld::Ptr&, const sol::object&); + + private: + Setter mSetter; // Function that updates a stat's property + int mIndex; // Optional index to disambiguate the stat + std::string_view mProp; // Name of the stat's property + public: + CachedStat(Setter setter, int index, std::string_view prop) + : mSetter(setter) + , mIndex(index) + , mProp(std::move(prop)) + { + } + + void operator()(const MWWorld::Ptr& ptr, const sol::object& object) const + { + mSetter(mIndex, mProp, ptr, object); + } + + bool operator<(const CachedStat& other) const + { + return std::tie(mSetter, mIndex, mProp) < std::tie(other.mSetter, other.mIndex, other.mProp); + } + }; + + SelfObject(const LObject& obj) + : LObject(obj) + , mIsActive(false) + { + } + MWBase::LuaManager::ActorControls mControls; + std::map mStatsCache; + bool mIsActive; + }; + class LocalScripts : public LuaUtil::ScriptsContainer { public: @@ -25,46 +65,6 @@ namespace MWLua MWBase::LuaManager::ActorControls* getActorControls() { return &mData.mControls; } const MWWorld::Ptr& getPtr() const { return mData.ptr(); } - struct SelfObject : public LObject - { - class CachedStat - { - public: - using Setter = void (*)(int, std::string_view, const MWWorld::Ptr&, const sol::object&); - - private: - Setter mSetter; // Function that updates a stat's property - int mIndex; // Optional index to disambiguate the stat - std::string_view mProp; // Name of the stat's property - public: - CachedStat(Setter setter, int index, std::string_view prop) - : mSetter(setter) - , mIndex(index) - , mProp(std::move(prop)) - { - } - - void operator()(const MWWorld::Ptr& ptr, const sol::object& object) const - { - mSetter(mIndex, mProp, ptr, object); - } - - bool operator<(const CachedStat& other) const - { - return std::tie(mSetter, mIndex, mProp) < std::tie(other.mSetter, other.mIndex, other.mProp); - } - }; - - SelfObject(const LObject& obj) - : LObject(obj) - , mIsActive(false) - { - } - MWBase::LuaManager::ActorControls mControls; - std::map mStatsCache; - bool mIsActive; - }; - struct OnActive { }; diff --git a/apps/openmw/mwlua/objectvariant.hpp b/apps/openmw/mwlua/objectvariant.hpp new file mode 100644 index 0000000000..8be0a390ea --- /dev/null +++ b/apps/openmw/mwlua/objectvariant.hpp @@ -0,0 +1,55 @@ +#ifndef MWLUA_OBJECTVARIANT_H +#define MWLUA_OBJECTVARIANT_H + +#include + +#include "localscripts.hpp" +#include "object.hpp" + +namespace MWLua +{ + + class ObjectVariant + { + public: + explicit ObjectVariant(const sol::object& obj) + { + if (obj.is()) + mVariant.emplace(obj.as()); + else if (obj.is()) + mVariant.emplace(obj.as()); + else + mVariant.emplace(obj.as()); + } + + bool isSelfObject() const { return std::holds_alternative(mVariant); } + bool isLObject() const { return std::holds_alternative(mVariant); } + bool isGObject() const { return std::holds_alternative(mVariant); } + + SelfObject* asSelfObject() const + { + if (!isSelfObject()) + throw std::runtime_error("Allowed only in local scripts for 'openmw.self'."); + return std::get(mVariant); + } + + const MWWorld::Ptr& ptr() const + { + return std::visit( + [](auto&& variant) -> const MWWorld::Ptr& { + using T = std::decay_t; + if constexpr (std::is_same_v) + return variant->ptr(); + else + return variant.ptr(); + }, + mVariant); + } + + private: + std::variant mVariant; + }; + +} // namespace MWLua + +#endif // MWLUA_OBJECTVARIANT_H diff --git a/apps/openmw/mwlua/stats.cpp b/apps/openmw/mwlua/stats.cpp index 8740ae15ee..2def0c6ac6 100644 --- a/apps/openmw/mwlua/stats.cpp +++ b/apps/openmw/mwlua/stats.cpp @@ -18,14 +18,17 @@ #include "../mwworld/class.hpp" #include "../mwworld/esmstore.hpp" +#include "objectvariant.hpp" + namespace { + using SelfObject = MWLua::SelfObject; + using ObjectVariant = MWLua::ObjectVariant; + template auto addIndexedAccessor(int index) { - return sol::overload([index](MWLua::LocalScripts::SelfObject& o) { return T::create(&o, index); }, - [index](const MWLua::LObject& o) { return T::create(o, index); }, - [index](const MWLua::GObject& o) { return T::create(o, index); }); + return [index](const sol::object& o) { return T::create(ObjectVariant(o), index); }; } template @@ -35,50 +38,18 @@ namespace [=](const T& stat, const sol::object& value) { stat.cache(context, prop, value); }); } - using SelfObject = MWLua::LocalScripts::SelfObject; - using StatObject = std::variant; - SelfObject* asSelfObject(const StatObject& obj) - { - if (!std::holds_alternative(obj)) - throw std::runtime_error("Changing stats allowed only in local scripts for 'openmw.self'."); - return std::get(obj); - } - - const MWLua::Object* getObject(const StatObject& obj) - { - return std::visit( - [](auto&& variant) -> const MWLua::Object* { - using T = std::decay_t; - if constexpr (std::is_same_v) - return variant; - else if constexpr (std::is_same_v) - return &variant; - else if constexpr (std::is_same_v) - return &variant; - }, - obj); - } - template - sol::object getValue(const MWLua::Context& context, const StatObject& obj, SelfObject::CachedStat::Setter setter, + sol::object getValue(const MWLua::Context& context, const ObjectVariant& obj, SelfObject::CachedStat::Setter setter, int index, std::string_view prop, G getter) { - return std::visit( - [&](auto&& variant) { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - auto it = variant->mStatsCache.find({ setter, index, prop }); - if (it != variant->mStatsCache.end()) - return it->second; - return sol::make_object(context.mLua->sol(), getter(variant)); - } - else if constexpr (std::is_same_v) - return sol::make_object(context.mLua->sol(), getter(&variant)); - else if constexpr (std::is_same_v) - return sol::make_object(context.mLua->sol(), getter(&variant)); - }, - obj); + if (obj.isSelfObject()) + { + SelfObject* self = obj.asSelfObject(); + auto it = self->mStatsCache.find({ setter, index, prop }); + if (it != self->mStatsCache.end()) + return it->second; + } + return sol::make_object(context.mLua->sol(), getter(obj.ptr())); } } @@ -111,9 +82,9 @@ namespace MWLua class LevelStat { - StatObject mObject; + ObjectVariant mObject; - LevelStat(StatObject object) + LevelStat(ObjectVariant object) : mObject(std::move(object)) { } @@ -121,15 +92,13 @@ namespace MWLua public: sol::object getCurrent(const Context& context) const { - return getValue(context, mObject, &LevelStat::setValue, 0, "current", [](const MWLua::Object* obj) { - const auto& ptr = obj->ptr(); - return ptr.getClass().getCreatureStats(ptr).getLevel(); - }); + return getValue(context, mObject, &LevelStat::setValue, 0, "current", + [](const MWWorld::Ptr& ptr) { return ptr.getClass().getCreatureStats(ptr).getLevel(); }); } void setCurrent(const Context& context, const sol::object& value) const { - SelfObject* obj = asSelfObject(mObject); + SelfObject* obj = mObject.asSelfObject(); if (obj->mStatsCache.empty()) context.mLuaManager->addAction(std::make_unique(context.mLua, obj->id())); obj->mStatsCache[SelfObject::CachedStat{ &LevelStat::setValue, 0, "current" }] = value; @@ -137,15 +106,15 @@ namespace MWLua sol::object getProgress(const Context& context) const { - const auto& ptr = getObject(mObject)->ptr(); + const auto& ptr = mObject.ptr(); if (!ptr.getClass().isNpc()) return sol::nil; return sol::make_object(context.mLua->sol(), ptr.getClass().getNpcStats(ptr).getLevelProgress()); } - static std::optional create(StatObject object, int index) + static std::optional create(ObjectVariant object, int index) { - if (!getObject(object)->ptr().getClass().isActor()) + if (!object.ptr().getClass().isActor()) return {}; return LevelStat{ std::move(object) }; } @@ -160,10 +129,10 @@ namespace MWLua class DynamicStat { - StatObject mObject; + ObjectVariant mObject; int mIndex; - DynamicStat(StatObject object, int index) + DynamicStat(ObjectVariant object, int index) : mObject(std::move(object)) , mIndex(index) { @@ -174,22 +143,21 @@ namespace MWLua sol::object get(const Context& context, std::string_view prop, G getter) const { return getValue( - context, mObject, &DynamicStat::setValue, mIndex, prop, [this, getter](const MWLua::Object* obj) { - const auto& ptr = obj->ptr(); + context, mObject, &DynamicStat::setValue, mIndex, prop, [this, getter](const MWWorld::Ptr& ptr) { return (ptr.getClass().getCreatureStats(ptr).getDynamic(mIndex).*getter)(); }); } - static std::optional create(StatObject object, int index) + static std::optional create(ObjectVariant object, int index) { - if (!getObject(object)->ptr().getClass().isActor()) + if (!object.ptr().getClass().isActor()) return {}; return DynamicStat{ std::move(object), index }; } void cache(const Context& context, std::string_view prop, const sol::object& value) const { - SelfObject* obj = asSelfObject(mObject); + SelfObject* obj = mObject.asSelfObject(); if (obj->mStatsCache.empty()) context.mLuaManager->addAction(std::make_unique(context.mLua, obj->id())); obj->mStatsCache[SelfObject::CachedStat{ &DynamicStat::setValue, mIndex, prop }] = value; @@ -212,10 +180,10 @@ namespace MWLua class AttributeStat { - StatObject mObject; + ObjectVariant mObject; int mIndex; - AttributeStat(StatObject object, int index) + AttributeStat(ObjectVariant object, int index) : mObject(std::move(object)) , mIndex(index) { @@ -226,8 +194,7 @@ namespace MWLua sol::object get(const Context& context, std::string_view prop, G getter) const { return getValue( - context, mObject, &AttributeStat::setValue, mIndex, prop, [this, getter](const MWLua::Object* obj) { - const auto& ptr = obj->ptr(); + context, mObject, &AttributeStat::setValue, mIndex, prop, [this, getter](const MWWorld::Ptr& ptr) { return (ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex).*getter)(); }); } @@ -240,16 +207,16 @@ namespace MWLua return std::max(0.f, base - damage + modifier); // Should match AttributeValue::getModified } - static std::optional create(StatObject object, int index) + static std::optional create(ObjectVariant object, int index) { - if (!getObject(object)->ptr().getClass().isActor()) + if (!object.ptr().getClass().isActor()) return {}; return AttributeStat{ std::move(object), index }; } void cache(const Context& context, std::string_view prop, const sol::object& value) const { - SelfObject* obj = asSelfObject(mObject); + SelfObject* obj = mObject.asSelfObject(); if (obj->mStatsCache.empty()) context.mLuaManager->addAction(std::make_unique(context.mLua, obj->id())); obj->mStatsCache[SelfObject::CachedStat{ &AttributeStat::setValue, mIndex, prop }] = value; @@ -275,10 +242,10 @@ namespace MWLua class SkillStat { - StatObject mObject; + ObjectVariant mObject; int mIndex; - SkillStat(StatObject object, int index) + SkillStat(ObjectVariant object, int index) : mObject(std::move(object)) , mIndex(index) { @@ -304,8 +271,7 @@ namespace MWLua sol::object get(const Context& context, std::string_view prop, G getter) const { return getValue( - context, mObject, &SkillStat::setValue, mIndex, prop, [this, getter](const MWLua::Object* obj) { - const auto& ptr = obj->ptr(); + context, mObject, &SkillStat::setValue, mIndex, prop, [this, getter](const MWWorld::Ptr& ptr) { return (ptr.getClass().getNpcStats(ptr).getSkill(mIndex).*getter)(); }); } @@ -321,22 +287,21 @@ namespace MWLua sol::object getProgress(const Context& context) const { return getValue( - context, mObject, &SkillStat::setValue, mIndex, "progress", [this](const MWLua::Object* obj) { - const auto& ptr = obj->ptr(); + context, mObject, &SkillStat::setValue, mIndex, "progress", [this](const MWWorld::Ptr& ptr) { return getProgress(ptr, mIndex, ptr.getClass().getNpcStats(ptr).getSkill(mIndex)); }); } - static std::optional create(StatObject object, int index) + static std::optional create(ObjectVariant object, int index) { - if (!getObject(object)->ptr().getClass().isNpc()) + if (!object.ptr().getClass().isNpc()) return {}; return SkillStat{ std::move(object), index }; } void cache(const Context& context, std::string_view prop, const sol::object& value) const { - SelfObject* obj = asSelfObject(mObject); + SelfObject* obj = mObject.asSelfObject(); if (obj->mStatsCache.empty()) context.mLuaManager->addAction(std::make_unique(context.mLua, obj->id())); obj->mStatsCache[SelfObject::CachedStat{ &SkillStat::setValue, mIndex, prop }] = value; diff --git a/apps/openmw/mwlua/types/actor.cpp b/apps/openmw/mwlua/types/actor.cpp index 97d797d8d5..15e29544ee 100644 --- a/apps/openmw/mwlua/types/actor.cpp +++ b/apps/openmw/mwlua/types/actor.cpp @@ -119,8 +119,6 @@ namespace MWLua }; } - using SelfObject = LocalScripts::SelfObject; - void addActorBindings(sol::table actor, const Context& context) { actor["STANCE"]