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