mirror of https://github.com/OpenMW/openmw.git
take2
parent
ff16ee2d64
commit
83ebaf27cc
@ -0,0 +1,129 @@
|
||||
#include "itemdata.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
#include "luamanagerimp.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "objectvariant.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
using SelfObject = MWLua::SelfObject;
|
||||
using Index = const SelfObject::CachedStat::Index&;
|
||||
|
||||
constexpr std::array properties = { "condition", /*"enchantmentCharge", "soul", "owner", etc..*/ };
|
||||
|
||||
void invalidPropErr(std::string_view prop, const MWWorld::Ptr& ptr)
|
||||
{
|
||||
throw std::runtime_error(std::string(prop) + " does not exist for item "
|
||||
+ std::string(ptr.getClass().getName(ptr)) + "(" + std::string(ptr.getTypeDescription()) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
static void addStatUpdateAction(MWLua::LuaManager* manager, const SelfObject& obj)
|
||||
{
|
||||
if (!obj.mStatsCache.empty())
|
||||
return; // was already added before
|
||||
manager->addAction(
|
||||
[obj = Object(obj)] {
|
||||
LocalScripts* scripts = obj.ptr().getRefData().getLuaScripts();
|
||||
if (scripts)
|
||||
scripts->applyStatsCache();
|
||||
},
|
||||
"StatUpdateAction");
|
||||
}
|
||||
|
||||
class ItemData
|
||||
{
|
||||
ObjectVariant mObject;
|
||||
|
||||
public:
|
||||
ItemData(ObjectVariant object)
|
||||
: mObject(object)
|
||||
{
|
||||
}
|
||||
|
||||
sol::object get(const Context& context, std::string_view prop) const
|
||||
{
|
||||
if (mObject.isSelfObject())
|
||||
{
|
||||
SelfObject* self = mObject.asSelfObject();
|
||||
auto it = self->mStatsCache.find({ &ItemData::setValue, std::monostate{}, prop });
|
||||
if (it != self->mStatsCache.end())
|
||||
return it->second;
|
||||
}
|
||||
return sol::make_object(context.mLua->sol(), getValue(context, prop));
|
||||
}
|
||||
|
||||
void set(const Context& context, std::string_view prop, const sol::object& value) const
|
||||
{
|
||||
SelfObject* obj = mObject.asSelfObject();
|
||||
addStatUpdateAction(context.mLuaManager, *obj);
|
||||
obj->mStatsCache[SelfObject::CachedStat{ &ItemData::setValue, std::monostate{}, prop }] = value;
|
||||
}
|
||||
|
||||
sol::object getValue(const Context& context, std::string_view prop) const
|
||||
{
|
||||
if (prop == "condition")
|
||||
{
|
||||
MWWorld::Ptr o = mObject.ptr();
|
||||
if (o.getClass().isLight(o))
|
||||
return sol::make_object(context.mLua->sol(), o.getClass().getRemainingUsageTime(o));
|
||||
else if (o.getClass().hasItemHealth(o))
|
||||
return sol::make_object(context.mLua->sol(), o.getClass().getItemHealth(o));
|
||||
}
|
||||
|
||||
return sol::lua_nil;
|
||||
}
|
||||
|
||||
static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
|
||||
{
|
||||
if (prop == "condition")
|
||||
{
|
||||
double cond = value.as<double>();
|
||||
if (ptr.getClass().isLight(ptr))
|
||||
ptr.getClass().setRemainingUsageTime(ptr, cond);
|
||||
else if (ptr.getClass().hasItemHealth(ptr))
|
||||
ptr.getCellRef().setCharge(std::max(0, static_cast<int>(cond)));
|
||||
else /*ignore or error?*/
|
||||
invalidPropErr(prop, ptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace sol
|
||||
{
|
||||
template <>
|
||||
struct is_automagical<MWLua::ItemData> : std::false_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
void addItemDataBindings(sol::table& item, const Context& context)
|
||||
{
|
||||
item["itemData"] = [](const sol::object& object) -> sol::optional<ItemData> {
|
||||
ObjectVariant o(object);
|
||||
if (o.ptr().getClass().isItem(o.ptr()) || o.ptr().mRef->getType() == ESM::REC_LIGH)
|
||||
return ItemData(std::move(o));
|
||||
return {};
|
||||
};
|
||||
|
||||
sol::usertype<ItemData> itemData = context.mLua->sol().new_usertype<ItemData>("ItemData");
|
||||
itemData[sol::meta_function::new_index] = [](const ItemData& stat, const sol::variadic_args args) {
|
||||
throw std::runtime_error("Unknown ItemData property '" + args.get<std::string>() + "'");
|
||||
};
|
||||
|
||||
for (std::string_view prop : properties)
|
||||
{
|
||||
itemData[prop] = sol::property([context, prop](const ItemData& stat) { return stat.get(context, prop); },
|
||||
[context, prop](const ItemData& stat, const sol::object& value) { stat.set(context, prop, value); });
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#ifndef MWLUA_ITEMDATA_H
|
||||
#define MWLUA_ITEMDATA_H
|
||||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
void addItemDataBindings(sol::table& item, const Context& context);
|
||||
|
||||
}
|
||||
#endif // MWLUA_ITEMDATA_H
|
@ -1,31 +1,22 @@
|
||||
#include "itemstats.hpp"
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
namespace sol
|
||||
{
|
||||
template <>
|
||||
struct is_automagical<MWLua::ItemStat> : std::false_type
|
||||
{
|
||||
};
|
||||
}
|
||||
#include "../../mwworld/class.hpp"
|
||||
|
||||
#include "../itemdata.hpp"
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
||||
void addItemBindings(sol::table item, const Context& context)
|
||||
{
|
||||
sol::usertype<ItemStat> ItemStats = context.mLua->sol().new_usertype<ItemStat>("ItemStat");
|
||||
ItemStats[sol::meta_function::new_index] = [](const ItemStat& i, const sol::variadic_args args) {
|
||||
throw std::runtime_error("Unknown itemStat property '" + args.get<std::string>() + "'");
|
||||
};
|
||||
ItemStats["condition"] = sol::property([](const ItemStat& i) { return i.getCondition(); },
|
||||
[](const ItemStat& i, float cond) { i.setCondition(cond); });
|
||||
|
||||
item["getEnchantmentCharge"]
|
||||
= [](const Object& object) { return object.ptr().getCellRef().getEnchantmentCharge(); };
|
||||
item["setEnchantmentCharge"]
|
||||
= [](const GObject& object, float charge) { object.ptr().getCellRef().setEnchantmentCharge(charge); };
|
||||
item["isRestocking"]
|
||||
= [](const Object& object) -> bool { return object.ptr().getRefData().getCount(false) < 0; };
|
||||
item["itemStats"] = [](const sol::object& object) { return ItemStat(object); };
|
||||
|
||||
addItemDataBindings(item, context);
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
#include "itemstats.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
ItemStat::ItemStat(const sol::object& object)
|
||||
: mObject(ObjectVariant(object))
|
||||
{
|
||||
}
|
||||
sol::optional<double> ItemStat::getCondition() const
|
||||
{
|
||||
MWWorld::Ptr o = mObject.ptr();
|
||||
if (o.getClass().isLight(o))
|
||||
return o.getClass().getRemainingUsageTime(o);
|
||||
else if (o.getClass().hasItemHealth(o))
|
||||
return o.getClass().getItemHealth(o);
|
||||
else
|
||||
return sol::nullopt;
|
||||
}
|
||||
void ItemStat::setCondition(float cond) const
|
||||
{
|
||||
if (!mObject.isGObject())
|
||||
throw std::runtime_error("This property can only be set in global scripts");
|
||||
|
||||
MWWorld::Ptr o = mObject.ptr();
|
||||
if (o.getClass().isLight(o))
|
||||
return o.getClass().setRemainingUsageTime(o, cond);
|
||||
else if (o.getClass().hasItemHealth(o))
|
||||
o.getCellRef().setCharge(std::max(0, static_cast<int>(cond)));
|
||||
else
|
||||
throw std::runtime_error("'condition' property does not exist for " + std::string(o.getClass().getName(o))
|
||||
+ "(" + std::string(o.getTypeDescription()) + ")");
|
||||
};
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
#ifndef MWLUA_ITEMSTATS_H
|
||||
#define MWLUA_ITEMSTATS_H
|
||||
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
#include "../../mwworld/class.hpp"
|
||||
|
||||
#include "../objectvariant.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
class ItemStat
|
||||
{
|
||||
public:
|
||||
ItemStat(const sol::object& object);
|
||||
|
||||
sol::optional<double> getCondition() const;
|
||||
|
||||
void setCondition(float cond) const;
|
||||
|
||||
/*
|
||||
* set,get, enchantmentCharge, soul? etc..
|
||||
*/
|
||||
|
||||
ObjectVariant mObject;
|
||||
};
|
||||
}
|
||||
#endif // MWLUA_ITEMSTATS_H
|
Loading…
Reference in New Issue