Expose AI stats to Lua

animationblending
Evil Eye 9 months ago
parent 6f8123998c
commit d08e47bc40

@ -217,6 +217,7 @@
Feature #7792: Support Timescale Clouds
Feature #7795: Support MaxNumberRipples INI setting
Feature #7805: Lua Menu context
Feature #7860: Lua: Expose NPC AI settings (fight, alarm, flee)
Task #5896: Do not use deprecated MyGUI properties
Task #6085: Replace boost::filesystem with std::filesystem
Task #6149: Dehardcode Lua API_REVISION

@ -31,7 +31,7 @@ namespace
using Index = const SelfObject::CachedStat::Index&;
template <class T>
auto addIndexedAccessor(Index index)
auto addIndexedAccessor(auto index)
{
return [index](const sol::object& o) { return T::create(ObjectVariant(o), index); };
}
@ -425,6 +425,62 @@ namespace MWLua
stats.setSkill(id, stat);
}
};
class AIStat
{
ObjectVariant mObject;
MWMechanics::AiSetting mIndex;
AIStat(ObjectVariant object, MWMechanics::AiSetting 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, &AIStat::setValue, static_cast<int>(mIndex), prop,
[this, getter](const MWWorld::Ptr& ptr) {
return (ptr.getClass().getCreatureStats(ptr).getAiSetting(mIndex).*getter)();
});
}
int getModified(const Context& context) const
{
auto base = LuaUtil::cast<int>(get(context, "base", &MWMechanics::Stat<int>::getBase));
auto modifier = LuaUtil::cast<int>(get(context, "modifier", &MWMechanics::Stat<int>::getModifier));
return std::max(0, base + modifier);
}
static std::optional<AIStat> create(ObjectVariant object, MWMechanics::AiSetting index)
{
if (!object.ptr().getClass().isActor())
return {};
return AIStat{ std::move(object), index };
}
void cache(const Context& context, std::string_view prop, const sol::object& value) const
{
SelfObject* obj = mObject.asSelfObject();
addStatUpdateAction(context.mLuaManager, *obj);
obj->mStatsCache[SelfObject::CachedStat{ &AIStat::setValue, static_cast<int>(mIndex), prop }] = value;
}
static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
{
auto index = static_cast<MWMechanics::AiSetting>(std::get<int>(i));
auto& stats = ptr.getClass().getCreatureStats(ptr);
auto stat = stats.getAiSetting(index);
int intValue = LuaUtil::cast<int>(value);
if (prop == "base")
stat.setBase(intValue);
else if (prop == "modifier")
stat.setModifier(intValue);
stats.setAiSetting(index, stat);
}
};
}
namespace sol
@ -465,6 +521,10 @@ namespace sol
struct is_automagical<ESM::MagicSchool> : std::false_type
{
};
template <>
struct is_automagical<MWLua::AIStat> : std::false_type
{
};
}
namespace MWLua
@ -529,6 +589,17 @@ namespace MWLua
stats["attributes"] = LuaUtil::makeReadOnly(attributes);
for (const ESM::Attribute& attribute : MWBase::Environment::get().getESMStore()->get<ESM::Attribute>())
attributes[ESM::RefId(attribute.mId).serializeText()] = addIndexedAccessor<AttributeStat>(attribute.mId);
auto aiStatT = context.mLua->sol().new_usertype<AIStat>("AIStat");
addProp(context, aiStatT, "base", &MWMechanics::Stat<int>::getBase);
addProp(context, aiStatT, "modifier", &MWMechanics::Stat<int>::getModifier);
aiStatT["modified"] = sol::readonly_property([=](const AIStat& stat) { return stat.getModified(context); });
sol::table ai(context.mLua->sol(), sol::create);
stats["ai"] = LuaUtil::makeReadOnly(ai);
ai["alarm"] = addIndexedAccessor<AIStat>(MWMechanics::AiSetting::Alarm);
ai["fight"] = addIndexedAccessor<AIStat>(MWMechanics::AiSetting::Fight);
ai["flee"] = addIndexedAccessor<AIStat>(MWMechanics::AiSetting::Flee);
ai["hello"] = addIndexedAccessor<AIStat>(MWMechanics::AiSetting::Hello);
}
void addNpcStatsBindings(sol::table& npc, const Context& context)

@ -445,6 +445,12 @@
-- @field #number modifier The skill's modifier.
-- @field #number progress [0-1] The NPC's skill progress.
---
-- @type AIStat
-- @field #number base The stat's base value.
-- @field #number modifier The stat's modifier.
-- @field #number modified The actor's current ai value (read-only.)
---
-- @type DynamicStats
@ -466,6 +472,33 @@
-- @param openmw.core#GameObject actor
-- @return #DynamicStat
---
-- @type AIStats
---
-- Alarm (returns @{#AIStat})
-- @function [parent=#AIStats] alarm
-- @param openmw.core#GameObject actor
-- @return #AIStat
---
-- Fight (returns @{#AIStat})
-- @function [parent=#AIStats] fight
-- @param openmw.core#GameObject actor
-- @return #AIStat
---
-- Flee (returns @{#AIStat})
-- @function [parent=#AIStats] flee
-- @param openmw.core#GameObject actor
-- @return #AIStat
---
-- Hello (returns @{#AIStat})
-- @function [parent=#AIStats] hello
-- @param openmw.core#GameObject actor
-- @return #AIStat
---
-- @type AttributeStats
@ -686,6 +719,7 @@
-- @type ActorStats
-- @field #DynamicStats dynamic
-- @field #AttributeStats attributes
-- @field #AIStats ai
---
-- Level (returns @{#LevelStat})

Loading…
Cancel
Save