mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-19 19:10:12 +00:00
Lua stats
This commit is contained in:
parent
1542a0392c
commit
93d195646c
13 changed files with 732 additions and 4 deletions
|
@ -59,8 +59,8 @@ add_openmw_dir (mwscript
|
|||
add_openmw_dir (mwlua
|
||||
luamanagerimp actions object worldview userdataserializer eventqueue
|
||||
luabindings localscripts playerscripts objectbindings cellbindings asyncbindings settingsbindings
|
||||
camerabindings uibindings inputbindings nearbybindings
|
||||
types/types types/door types/actor types/container types/weapon
|
||||
camerabindings uibindings inputbindings nearbybindings stats
|
||||
types/types types/door types/actor types/container types/weapon types/npc
|
||||
)
|
||||
|
||||
add_openmw_dir (mwsound
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "actions.hpp"
|
||||
|
||||
#include "localscripts.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
@ -168,4 +170,11 @@ namespace MWLua
|
|||
std::string(" actor=") + idToString(mActor);
|
||||
}
|
||||
|
||||
void StatUpdateAction::apply(WorldView& worldView) const
|
||||
{
|
||||
LObject obj(mId, worldView.getObjectRegistry());
|
||||
LocalScripts* scripts = obj.ptr().getRefData().getLuaScripts();
|
||||
if (scripts)
|
||||
scripts->applyStatsCache();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,16 @@ namespace MWLua
|
|||
ObjectId mActor;
|
||||
};
|
||||
|
||||
class StatUpdateAction final : public Action
|
||||
{
|
||||
ObjectId mId;
|
||||
public:
|
||||
StatUpdateAction(LuaUtil::LuaState* state, ObjectId id) : Action(state), mId(id) {}
|
||||
|
||||
void apply(WorldView& worldView) const override;
|
||||
|
||||
std::string toString() const override { return "StatUpdateAction"; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MWLUA_ACTIONS_H
|
||||
|
|
|
@ -182,4 +182,11 @@ namespace MWLua
|
|||
}, event);
|
||||
}
|
||||
|
||||
void LocalScripts::applyStatsCache()
|
||||
{
|
||||
const auto& ptr = mData.ptr();
|
||||
for (auto& [stat, value] : mData.mStatsCache)
|
||||
stat(ptr, value);
|
||||
mData.mStatsCache.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,31 @@ namespace MWLua
|
|||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -45,6 +68,7 @@ namespace MWLua
|
|||
|
||||
void receiveEngineEvent(const EngineEvent&);
|
||||
|
||||
void applyStatsCache();
|
||||
protected:
|
||||
SelfObject mData;
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace MWLua
|
|||
{
|
||||
auto* lua = context.mLua;
|
||||
sol::table api(lua->sol(), sol::create);
|
||||
api["API_REVISION"] = 18;
|
||||
api["API_REVISION"] = 19;
|
||||
api["quit"] = [lua]()
|
||||
{
|
||||
Log(Debug::Warning) << "Quit requested by a Lua script.\n" << lua->debugTraceback();
|
||||
|
|
369
apps/openmw/mwlua/stats.cpp
Normal file
369
apps/openmw/mwlua/stats.cpp
Normal file
|
@ -0,0 +1,369 @@
|
|||
#include "stats.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
|
||||
#include <components/lua/luastate.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "localscripts.hpp"
|
||||
#include "luamanagerimp.hpp"
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
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); }
|
||||
);
|
||||
}
|
||||
|
||||
template<class T, class G>
|
||||
void addProp(const MWLua::Context& context, sol::usertype<T>& type, std::string_view prop, G getter, bool readOnly = false)
|
||||
{
|
||||
if(readOnly)
|
||||
type[prop] = sol::property([=](const T& stat) { return stat.get(context, prop, getter); });
|
||||
else
|
||||
type[prop] = sol::property(
|
||||
[=](const T& stat) { return stat.get(context, prop, getter); },
|
||||
[=](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>;
|
||||
|
||||
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, 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);
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
class LevelStat
|
||||
{
|
||||
StatObject mObject;
|
||||
|
||||
LevelStat(StatObject object) : mObject(std::move(object)) {}
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
||||
void setCurrent(const Context& context, const sol::object& value) const
|
||||
{
|
||||
SelfObject* obj = std::get<SelfObject*>(mObject);
|
||||
if(obj->mStatsCache.empty())
|
||||
context.mLuaManager->addAction(std::make_unique<StatUpdateAction>(context.mLua, obj->id()));
|
||||
obj->mStatsCache[SelfObject::CachedStat{&LevelStat::setValue, 0, "current"}] = value;
|
||||
}
|
||||
|
||||
sol::object getProgress(const Context& context) const
|
||||
{
|
||||
const auto& ptr = getObject(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)
|
||||
{
|
||||
if(!getObject(object)->ptr().getClass().isActor())
|
||||
return {};
|
||||
return LevelStat{std::move(object)};
|
||||
}
|
||||
|
||||
static void setValue(int, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
|
||||
{
|
||||
auto& stats = ptr.getClass().getCreatureStats(ptr);
|
||||
if(prop == "current")
|
||||
stats.setLevel(value.as<int>());
|
||||
}
|
||||
};
|
||||
|
||||
class DynamicStat
|
||||
{
|
||||
StatObject mObject;
|
||||
int mIndex;
|
||||
|
||||
DynamicStat(StatObject object, int index) : mObject(std::move(object)), mIndex(index) {}
|
||||
public:
|
||||
template<class G>
|
||||
sol::object get(const Context& context, std::string_view prop, G getter) const
|
||||
{
|
||||
return getValue(context, mObject, &DynamicStat::setValue, mIndex, prop, [=](const MWLua::Object* obj)
|
||||
{
|
||||
const auto& ptr = obj->ptr();
|
||||
return (ptr.getClass().getCreatureStats(ptr).getDynamic(mIndex).*getter)();
|
||||
});
|
||||
}
|
||||
|
||||
static std::optional<DynamicStat> create(StatObject object, int index)
|
||||
{
|
||||
if(!getObject(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 = std::get<SelfObject*>(mObject);
|
||||
if(obj->mStatsCache.empty())
|
||||
context.mLuaManager->addAction(std::make_unique<StatUpdateAction>(context.mLua, obj->id()));
|
||||
obj->mStatsCache[SelfObject::CachedStat{&DynamicStat::setValue, mIndex, prop}] = value;
|
||||
}
|
||||
|
||||
static void setValue(int index, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
|
||||
{
|
||||
auto& stats = ptr.getClass().getCreatureStats(ptr);
|
||||
auto stat = stats.getDynamic(index);
|
||||
float floatValue = value.as<float>();
|
||||
if(prop == "base")
|
||||
stat.setBase(floatValue);
|
||||
else if(prop == "current")
|
||||
stat.setCurrent(floatValue, true, true);
|
||||
else if(prop == "modifier")
|
||||
stat.setModifier(floatValue);
|
||||
stats.setDynamic(index, stat);
|
||||
}
|
||||
};
|
||||
|
||||
class AttributeStat
|
||||
{
|
||||
StatObject mObject;
|
||||
int mIndex;
|
||||
|
||||
AttributeStat(StatObject object, int index) : mObject(std::move(object)), mIndex(index) {}
|
||||
public:
|
||||
template<class G>
|
||||
sol::object get(const Context& context, std::string_view prop, G getter) const
|
||||
{
|
||||
return getValue(context, mObject, &AttributeStat::setValue, mIndex, prop, [=](const MWLua::Object* obj)
|
||||
{
|
||||
const auto& ptr = obj->ptr();
|
||||
return (ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex).*getter)();
|
||||
});
|
||||
}
|
||||
|
||||
static std::optional<AttributeStat> create(StatObject object, int index)
|
||||
{
|
||||
if(!getObject(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 = std::get<SelfObject*>(mObject);
|
||||
if(obj->mStatsCache.empty())
|
||||
context.mLuaManager->addAction(std::make_unique<StatUpdateAction>(context.mLua, obj->id()));
|
||||
obj->mStatsCache[SelfObject::CachedStat{&AttributeStat::setValue, mIndex, prop}] = value;
|
||||
}
|
||||
|
||||
static void setValue(int index, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
|
||||
{
|
||||
auto& stats = ptr.getClass().getCreatureStats(ptr);
|
||||
auto stat = stats.getAttribute(index);
|
||||
float floatValue = value.as<float>();
|
||||
if(prop == "base")
|
||||
stat.setBase(floatValue);
|
||||
else if(prop == "damage")
|
||||
{
|
||||
stat.restore(stat.getDamage());
|
||||
stat.damage(floatValue);
|
||||
}
|
||||
else if(prop == "modifier")
|
||||
stat.setModifier(floatValue);
|
||||
stats.setAttribute(index, stat);
|
||||
}
|
||||
};
|
||||
|
||||
class SkillStat
|
||||
{
|
||||
StatObject mObject;
|
||||
int mIndex;
|
||||
|
||||
SkillStat(StatObject object, int index) : mObject(std::move(object)), mIndex(index) {}
|
||||
|
||||
static float getProgress(const MWWorld::Ptr& ptr, int index, const MWMechanics::SkillValue& stat)
|
||||
{
|
||||
float progress = stat.getProgress();
|
||||
if(progress != 0.f)
|
||||
progress /= getMaxProgress(ptr, index, stat);
|
||||
return progress;
|
||||
}
|
||||
|
||||
static float getMaxProgress(const MWWorld::Ptr& ptr, int index, const MWMechanics::SkillValue& stat) {
|
||||
const auto& store = MWBase::Environment::get().getWorld()->getStore();
|
||||
const auto cl = store.get<ESM::Class>().find(ptr.get<ESM::NPC>()->mBase->mClass);
|
||||
return ptr.getClass().getNpcStats(ptr).getSkillProgressRequirement(index, *cl);
|
||||
}
|
||||
public:
|
||||
template<class G>
|
||||
sol::object get(const Context& context, std::string_view prop, G getter) const
|
||||
{
|
||||
return getValue(context, mObject, &SkillStat::setValue, mIndex, prop, [=](const MWLua::Object* obj)
|
||||
{
|
||||
const auto& ptr = obj->ptr();
|
||||
return (ptr.getClass().getNpcStats(ptr).getSkill(mIndex).*getter)();
|
||||
});
|
||||
}
|
||||
|
||||
sol::object getProgress(const Context& context) const
|
||||
{
|
||||
return getValue(context, mObject, &SkillStat::setValue, mIndex, "progress", [=](const MWLua::Object* obj)
|
||||
{
|
||||
const auto& ptr = obj->ptr();
|
||||
return getProgress(ptr, mIndex, ptr.getClass().getNpcStats(ptr).getSkill(mIndex));
|
||||
});
|
||||
}
|
||||
|
||||
static std::optional<SkillStat> create(StatObject object, int index)
|
||||
{
|
||||
if(!getObject(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 = std::get<SelfObject*>(mObject);
|
||||
if(obj->mStatsCache.empty())
|
||||
context.mLuaManager->addAction(std::make_unique<StatUpdateAction>(context.mLua, obj->id()));
|
||||
obj->mStatsCache[SelfObject::CachedStat{&SkillStat::setValue, mIndex, prop}] = value;
|
||||
}
|
||||
|
||||
static void setValue(int index, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
|
||||
{
|
||||
auto& stats = ptr.getClass().getNpcStats(ptr);
|
||||
auto stat = stats.getSkill(index);
|
||||
float floatValue = value.as<float>();
|
||||
if(prop == "base")
|
||||
stat.setBase(floatValue);
|
||||
else if(prop == "damage")
|
||||
{
|
||||
stat.restore(stat.getDamage());
|
||||
stat.damage(floatValue);
|
||||
}
|
||||
else if(prop == "modifier")
|
||||
stat.setModifier(floatValue);
|
||||
else if(prop == "progress")
|
||||
stat.setProgress(floatValue * getMaxProgress(ptr, index, stat));
|
||||
stats.setSkill(index, stat);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace sol
|
||||
{
|
||||
template <>
|
||||
struct is_automagical<MWLua::LevelStat> : std::false_type {};
|
||||
template <>
|
||||
struct is_automagical<MWLua::DynamicStat> : std::false_type {};
|
||||
template <>
|
||||
struct is_automagical<MWLua::AttributeStat> : std::false_type {};
|
||||
template <>
|
||||
struct is_automagical<MWLua::SkillStat> : std::false_type {};
|
||||
}
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
void addActorStatsBindings(sol::table& actor, const Context& context)
|
||||
{
|
||||
sol::table stats(context.mLua->sol(), sol::create);
|
||||
actor["stats"] = LuaUtil::makeReadOnly(stats);
|
||||
|
||||
auto levelStatT = context.mLua->sol().new_usertype<LevelStat>("LevelStat");
|
||||
levelStatT["current"] = sol::property(
|
||||
[context](const LevelStat& stat) { return stat.getCurrent(context); },
|
||||
[context](const LevelStat& stat, const sol::object& value) { stat.setCurrent(context, value); });
|
||||
levelStatT["progress"] = sol::property([context](const LevelStat& stat) { return stat.getProgress(context); });
|
||||
stats["level"] = addIndexedAccessor<LevelStat>(0);
|
||||
|
||||
auto dynamicStatT = context.mLua->sol().new_usertype<DynamicStat>("DynamicStat");
|
||||
addProp(context, dynamicStatT, "base", &MWMechanics::DynamicStat<float>::getBase);
|
||||
addProp(context, dynamicStatT, "current", &MWMechanics::DynamicStat<float>::getCurrent);
|
||||
addProp(context, dynamicStatT, "modifier", &MWMechanics::DynamicStat<float>::getModifier);
|
||||
sol::table dynamic(context.mLua->sol(), sol::create);
|
||||
stats["dynamic"] = LuaUtil::makeReadOnly(dynamic);
|
||||
dynamic["health"] = addIndexedAccessor<DynamicStat>(0);
|
||||
dynamic["magicka"] = addIndexedAccessor<DynamicStat>(1);
|
||||
dynamic["fatigue"] = addIndexedAccessor<DynamicStat>(2);
|
||||
|
||||
auto attributeStatT = context.mLua->sol().new_usertype<AttributeStat>("AttributeStat");
|
||||
addProp(context, attributeStatT, "base", &MWMechanics::AttributeValue::getBase);
|
||||
addProp(context, attributeStatT, "damage", &MWMechanics::AttributeValue::getDamage);
|
||||
addProp(context, attributeStatT, "modified", &MWMechanics::AttributeValue::getModified, true);
|
||||
addProp(context, attributeStatT, "modifier", &MWMechanics::AttributeValue::getModifier);
|
||||
sol::table attributes(context.mLua->sol(), sol::create);
|
||||
stats["attributes"] = LuaUtil::makeReadOnly(attributes);
|
||||
for(int id = ESM::Attribute::Strength; id < ESM::Attribute::Length; ++id)
|
||||
attributes[Misc::StringUtils::lowerCase(ESM::Attribute::sAttributeNames[id])] = addIndexedAccessor<AttributeStat>(id);
|
||||
}
|
||||
|
||||
void addNpcStatsBindings(sol::table& npc, const Context& context)
|
||||
{
|
||||
sol::table npcStats(context.mLua->sol(), sol::create);
|
||||
sol::table baseMeta(context.mLua->sol(), sol::create);
|
||||
baseMeta[sol::meta_function::index] = LuaUtil::getMutableFromReadOnly(npc["baseType"]["stats"]);
|
||||
npcStats[sol::metatable_key] = baseMeta;
|
||||
npc["stats"] = LuaUtil::makeReadOnly(npcStats);
|
||||
|
||||
auto skillStatT = context.mLua->sol().new_usertype<SkillStat>("SkillStat");
|
||||
addProp(context, skillStatT, "base", &MWMechanics::SkillValue::getBase);
|
||||
addProp(context, skillStatT, "damage", &MWMechanics::SkillValue::getDamage);
|
||||
addProp(context, skillStatT, "modified", &MWMechanics::SkillValue::getModified, true);
|
||||
addProp(context, skillStatT, "modifier", &MWMechanics::SkillValue::getModifier);
|
||||
skillStatT["progress"] = sol::property(
|
||||
[context](const SkillStat& stat) { return stat.getProgress(context); },
|
||||
[context](const SkillStat& stat, const sol::object& value) { stat.cache(context, "progress", value); });
|
||||
sol::table skills(context.mLua->sol(), sol::create);
|
||||
npcStats["skills"] = LuaUtil::makeReadOnly(skills);
|
||||
for(int id = ESM::Skill::Block; id < ESM::Skill::Length; ++id)
|
||||
skills[Misc::StringUtils::lowerCase(ESM::Skill::sSkillNames[id])] = addIndexedAccessor<SkillStat>(id);
|
||||
}
|
||||
}
|
12
apps/openmw/mwlua/stats.hpp
Normal file
12
apps/openmw/mwlua/stats.hpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef MWLUA_STATS_H
|
||||
#define MWLUA_STATS_H
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
void addActorStatsBindings(sol::table& actor, const Context& context);
|
||||
void addNpcStatsBindings(sol::table& npc, const Context& context);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -10,6 +10,7 @@
|
|||
#include "../luabindings.hpp"
|
||||
#include "../localscripts.hpp"
|
||||
#include "../luamanagerimp.hpp"
|
||||
#include "../stats.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
@ -132,6 +133,8 @@ namespace MWLua
|
|||
}
|
||||
context.mLuaManager->addAction(std::make_unique<SetEquipmentAction>(context.mLua, obj.id(), std::move(eqp)));
|
||||
};
|
||||
|
||||
addActorStatsBindings(actor, context);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
11
apps/openmw/mwlua/types/npc.cpp
Normal file
11
apps/openmw/mwlua/types/npc.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "types.hpp"
|
||||
|
||||
#include "../stats.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
void addNpcBindings(sol::table npc, const Context& context)
|
||||
{
|
||||
addNpcStatsBindings(npc, context);
|
||||
}
|
||||
}
|
|
@ -156,7 +156,7 @@ namespace MWLua
|
|||
ESM::REC_APPA, ESM::REC_LOCK, ESM::REC_PROB, ESM::REC_REPA});
|
||||
|
||||
addType(ObjectTypeName::Creature, {ESM::REC_CREA}, ObjectTypeName::Actor);
|
||||
addType(ObjectTypeName::NPC, {ESM::REC_INTERNAL_PLAYER, ESM::REC_NPC_}, ObjectTypeName::Actor);
|
||||
addNpcBindings(addType(ObjectTypeName::NPC, {ESM::REC_INTERNAL_PLAYER, ESM::REC_NPC_}, ObjectTypeName::Actor), context);
|
||||
addType(ObjectTypeName::Player, {ESM::REC_INTERNAL_PLAYER}, ObjectTypeName::NPC);
|
||||
|
||||
addType(ObjectTypeName::Armor, {ESM::REC_ARMO}, ObjectTypeName::Item);
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace MWLua
|
|||
void addDoorBindings(sol::table door, const Context& context);
|
||||
void addActorBindings(sol::table actor, const Context& context);
|
||||
void addWeaponBindings(sol::table weapon, const Context& context);
|
||||
void addNpcBindings(sol::table npc, const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_TYPES_H
|
||||
|
|
|
@ -128,6 +128,287 @@
|
|||
-- local Actor = require('openmw.types').Actor
|
||||
-- Actor.setEquipment(self, {}) -- unequip all
|
||||
|
||||
---
|
||||
-- @type LevelStat
|
||||
-- @field #number current The actor's current level.
|
||||
-- @field #number progress The NPC's level progress (read-only.)
|
||||
|
||||
---
|
||||
-- @type DynamicStat
|
||||
-- @field #number base
|
||||
-- @field #number current
|
||||
-- @field #number modifier
|
||||
|
||||
---
|
||||
-- @type AttributeStat
|
||||
-- @field #number base The actor's base attribute value.
|
||||
-- @field #number damage The amount the attribute has been damaged.
|
||||
-- @field #number modified The actor's current attribute value (read-only.)
|
||||
-- @field #number modifier The attribute's modifier.
|
||||
|
||||
---
|
||||
-- @type SkillStat
|
||||
-- @field #number base The NPC's base skill value.
|
||||
-- @field #number damage The amount the skill has been damaged.
|
||||
-- @field #number modified The NPC's current skill value (read-only.)
|
||||
-- @field #number modifier The skill's modifier.
|
||||
-- @field #number progress [0-1] The NPC's skill progress.
|
||||
|
||||
---
|
||||
-- @type DynamicStats
|
||||
|
||||
---
|
||||
-- Health (returns @{#DynamicStat})
|
||||
-- @function [parent=#DynamicStats] health
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #DynamicStat
|
||||
|
||||
---
|
||||
-- Magicka (returns @{#DynamicStat})
|
||||
-- @function [parent=#DynamicStats] magicka
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #DynamicStat
|
||||
|
||||
---
|
||||
-- Fatigue (returns @{#DynamicStat})
|
||||
-- @function [parent=#DynamicStats] fatigue
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #DynamicStat
|
||||
|
||||
---
|
||||
-- @type AttributeStats
|
||||
|
||||
---
|
||||
-- Strength (returns @{#AttributeStat})
|
||||
-- @function [parent=#AttributeStats] strength
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #AttributeStat
|
||||
|
||||
---
|
||||
-- Intelligence (returns @{#AttributeStat})
|
||||
-- @function [parent=#AttributeStats] intelligence
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #AttributeStat
|
||||
|
||||
---
|
||||
-- Willpower (returns @{#AttributeStat})
|
||||
-- @function [parent=#AttributeStats] willpower
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #AttributeStat
|
||||
|
||||
---
|
||||
-- Agility (returns @{#AttributeStat})
|
||||
-- @function [parent=#AttributeStats] agility
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #AttributeStat
|
||||
|
||||
---
|
||||
-- Speed (returns @{#AttributeStat})
|
||||
-- @function [parent=#AttributeStats] speed
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #AttributeStat
|
||||
|
||||
---
|
||||
-- Endurance (returns @{#AttributeStat})
|
||||
-- @function [parent=#AttributeStats] endurance
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #AttributeStat
|
||||
|
||||
---
|
||||
-- Personality (returns @{#AttributeStat})
|
||||
-- @function [parent=#AttributeStats] personality
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #AttributeStat
|
||||
|
||||
---
|
||||
-- Luck (returns @{#AttributeStat})
|
||||
-- @function [parent=#AttributeStats] luck
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #AttributeStat
|
||||
|
||||
---
|
||||
-- @type SkillStats
|
||||
|
||||
---
|
||||
-- Block (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] block
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Armorer (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] armorer
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Medium Armor (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] mediumarmor
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Heavy Armor (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] heavyarmor
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Blunt Weapon (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] bluntweapon
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Long Blade (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] longblade
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Axe (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] axe
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Spear (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] spear
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Athletics (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] athletics
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Enchant (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] enchant
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Destruction (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] destruction
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Alteration (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] alteration
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Illusion (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] illusion
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Conjuration (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] conjuration
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Mysticism (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] mysticism
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Restoration (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] restoration
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Alchemy (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] alchemy
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Unarmored (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] unarmored
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Security (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] security
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Sneak (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] sneak
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Acrobatics (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] acrobatics
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Light Armor (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] lightarmor
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Short Blade (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] shortblade
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Marksman (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] marksman
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Mercantile (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] mercantile
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Speechcraft (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] speechcraft
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- Hand To Hand (returns @{#SkillStat})
|
||||
-- @function [parent=#SkillStats] handtohand
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #SkillStat
|
||||
|
||||
---
|
||||
-- @type ActorStats
|
||||
-- @field #DynamicStats dynamic
|
||||
-- @field #AttributeStats attributes
|
||||
|
||||
---
|
||||
-- Level (returns @{#LevelStat})
|
||||
-- @function [parent=#ActorStats] level
|
||||
-- @param openmw.core#GameObject actor
|
||||
-- @return #LevelStat
|
||||
|
||||
--- The actor's stats.
|
||||
-- @field [parent=#Actor] #ActorStats stats
|
||||
|
||||
---
|
||||
-- @type NpcStats
|
||||
-- @extends ActorStats
|
||||
-- @field #SkillStats skills
|
||||
|
||||
|
||||
--- @{#Item} functions (all pickable items that can be placed to an inventory or container)
|
||||
|
@ -167,6 +448,7 @@
|
|||
-- @type NPC
|
||||
-- @extends #Actor
|
||||
-- @field #Actor baseType @{#Actor}
|
||||
-- @field [parent=#NPC] #NpcStats stats
|
||||
|
||||
---
|
||||
-- Whether the object is an NPC or a Player.
|
||||
|
|
Loading…
Reference in a new issue