mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 20:56:39 +00:00 
			
		
		
		
	Move std::variant<SelfObject*, LObject, GObject> from mwlua/stats.cpp to mwlua/objectvariant.hpp
				
					
				
			This commit is contained in:
		
							parent
							
								
									0b385d5db9
								
							
						
					
					
						commit
						2bfffb3063
					
				
					 6 changed files with 139 additions and 121 deletions
				
			
		|  | @ -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 | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ namespace sol | |||
|     { | ||||
|     }; | ||||
|     template <> | ||||
|     struct is_automagical<MWLua::LocalScripts::SelfObject> : std::false_type | ||||
|     struct is_automagical<MWLua::SelfObject> : std::false_type | ||||
|     { | ||||
|     }; | ||||
|     template <> | ||||
|  |  | |||
|  | @ -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<CachedStat, sol::object> 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<CachedStat, sol::object> mStatsCache; | ||||
|             bool mIsActive; | ||||
|         }; | ||||
| 
 | ||||
|         struct OnActive | ||||
|         { | ||||
|         }; | ||||
|  |  | |||
							
								
								
									
										55
									
								
								apps/openmw/mwlua/objectvariant.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								apps/openmw/mwlua/objectvariant.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| #ifndef MWLUA_OBJECTVARIANT_H | ||||
| #define MWLUA_OBJECTVARIANT_H | ||||
| 
 | ||||
| #include <variant> | ||||
| 
 | ||||
| #include "localscripts.hpp" | ||||
| #include "object.hpp" | ||||
| 
 | ||||
| namespace MWLua | ||||
| { | ||||
| 
 | ||||
|     class ObjectVariant | ||||
|     { | ||||
|     public: | ||||
|         explicit ObjectVariant(const sol::object& obj) | ||||
|         { | ||||
|             if (obj.is<SelfObject>()) | ||||
|                 mVariant.emplace<SelfObject*>(obj.as<SelfObject*>()); | ||||
|             else if (obj.is<LObject>()) | ||||
|                 mVariant.emplace<LObject>(obj.as<LObject>()); | ||||
|             else | ||||
|                 mVariant.emplace<GObject>(obj.as<GObject>()); | ||||
|         } | ||||
| 
 | ||||
|         bool isSelfObject() const { return std::holds_alternative<SelfObject*>(mVariant); } | ||||
|         bool isLObject() const { return std::holds_alternative<LObject>(mVariant); } | ||||
|         bool isGObject() const { return std::holds_alternative<GObject>(mVariant); } | ||||
| 
 | ||||
|         SelfObject* asSelfObject() const | ||||
|         { | ||||
|             if (!isSelfObject()) | ||||
|                 throw std::runtime_error("Allowed only in local scripts for 'openmw.self'."); | ||||
|             return std::get<SelfObject*>(mVariant); | ||||
|         } | ||||
| 
 | ||||
|         const MWWorld::Ptr& ptr() const | ||||
|         { | ||||
|             return std::visit( | ||||
|                 [](auto&& variant) -> const MWWorld::Ptr& { | ||||
|                     using T = std::decay_t<decltype(variant)>; | ||||
|                     if constexpr (std::is_same_v<T, SelfObject*>) | ||||
|                         return variant->ptr(); | ||||
|                     else | ||||
|                         return variant.ptr(); | ||||
|                 }, | ||||
|                 mVariant); | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
|         std::variant<SelfObject*, LObject, GObject> mVariant; | ||||
|     }; | ||||
| 
 | ||||
| } // namespace MWLua
 | ||||
| 
 | ||||
| #endif // MWLUA_OBJECTVARIANT_H
 | ||||
|  | @ -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 <class T> | ||||
|     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 <class T, class G> | ||||
|  | @ -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*, MWLua::LObject, MWLua::GObject>; | ||||
|     SelfObject* asSelfObject(const StatObject& obj) | ||||
|     { | ||||
|         if (!std::holds_alternative<SelfObject*>(obj)) | ||||
|             throw std::runtime_error("Changing stats allowed only in local scripts for 'openmw.self'."); | ||||
|         return std::get<SelfObject*>(obj); | ||||
|     } | ||||
| 
 | ||||
|     const MWLua::Object* getObject(const StatObject& obj) | ||||
|     { | ||||
|         return std::visit( | ||||
|             [](auto&& variant) -> const MWLua::Object* { | ||||
|                 using T = std::decay_t<decltype(variant)>; | ||||
|                 if constexpr (std::is_same_v<T, SelfObject*>) | ||||
|                     return variant; | ||||
|                 else if constexpr (std::is_same_v<T, MWLua::LObject>) | ||||
|                     return &variant; | ||||
|                 else if constexpr (std::is_same_v<T, MWLua::GObject>) | ||||
|                     return &variant; | ||||
|             }, | ||||
|             obj); | ||||
|     } | ||||
| 
 | ||||
|     template <class G> | ||||
|     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<decltype(variant)>; | ||||
|                 if constexpr (std::is_same_v<T, SelfObject*>) | ||||
|                 { | ||||
|                     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<T, MWLua::LObject>) | ||||
|                     return sol::make_object(context.mLua->sol(), getter(&variant)); | ||||
|                 else if constexpr (std::is_same_v<T, MWLua::GObject>) | ||||
|                     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<StatUpdateAction>(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<LevelStat> create(StatObject object, int index) | ||||
|         static std::optional<LevelStat> 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<DynamicStat> create(StatObject object, int index) | ||||
|         static std::optional<DynamicStat> 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<StatUpdateAction>(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<AttributeStat> create(StatObject object, int index) | ||||
|         static std::optional<AttributeStat> 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<StatUpdateAction>(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<SkillStat> create(StatObject object, int index) | ||||
|         static std::optional<SkillStat> 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<StatUpdateAction>(context.mLua, obj->id())); | ||||
|             obj->mStatsCache[SelfObject::CachedStat{ &SkillStat::setValue, mIndex, prop }] = value; | ||||
|  |  | |||
|  | @ -119,8 +119,6 @@ namespace MWLua | |||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     using SelfObject = LocalScripts::SelfObject; | ||||
| 
 | ||||
|     void addActorBindings(sol::table actor, const Context& context) | ||||
|     { | ||||
|         actor["STANCE"] | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue