1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-19 19:10:12 +00:00

Move std::variant<SelfObject*, LObject, GObject> from mwlua/stats.cpp to mwlua/objectvariant.hpp

This commit is contained in:
Petr Mikheev 2023-03-06 02:31:58 +01:00
parent 0b385d5db9
commit 2bfffb3063
6 changed files with 139 additions and 121 deletions

View file

@ -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

View file

@ -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 <>

View file

@ -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
{
};

View 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

View file

@ -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;

View file

@ -119,8 +119,6 @@ namespace MWLua
};
}
using SelfObject = LocalScripts::SelfObject;
void addActorBindings(sol::table actor, const Context& context)
{
actor["STANCE"]