From d08e47bc40b436e3c5114a1eb912cdf581fdcec9 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Fri, 29 Mar 2024 22:34:53 +0100 Subject: [PATCH 1/2] Expose AI stats to Lua --- CHANGELOG.md | 1 + apps/openmw/mwlua/stats.cpp | 73 +++++++++++++++++++++++++++++++++- files/lua_api/openmw/types.lua | 34 ++++++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f797a98dab..4211f47538 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/apps/openmw/mwlua/stats.cpp b/apps/openmw/mwlua/stats.cpp index ad0f585207..209a852697 100644 --- a/apps/openmw/mwlua/stats.cpp +++ b/apps/openmw/mwlua/stats.cpp @@ -31,7 +31,7 @@ namespace using Index = const SelfObject::CachedStat::Index&; template - 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 + sol::object get(const Context& context, std::string_view prop, G getter) const + { + return getValue(context, mObject, &AIStat::setValue, static_cast(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(get(context, "base", &MWMechanics::Stat::getBase)); + auto modifier = LuaUtil::cast(get(context, "modifier", &MWMechanics::Stat::getModifier)); + return std::max(0, base + modifier); + } + + static std::optional 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(mIndex), prop }] = value; + } + + static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value) + { + auto index = static_cast(std::get(i)); + auto& stats = ptr.getClass().getCreatureStats(ptr); + auto stat = stats.getAiSetting(index); + int intValue = LuaUtil::cast(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 : std::false_type { }; + template <> + struct is_automagical : 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()) attributes[ESM::RefId(attribute.mId).serializeText()] = addIndexedAccessor(attribute.mId); + + auto aiStatT = context.mLua->sol().new_usertype("AIStat"); + addProp(context, aiStatT, "base", &MWMechanics::Stat::getBase); + addProp(context, aiStatT, "modifier", &MWMechanics::Stat::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(MWMechanics::AiSetting::Alarm); + ai["fight"] = addIndexedAccessor(MWMechanics::AiSetting::Fight); + ai["flee"] = addIndexedAccessor(MWMechanics::AiSetting::Flee); + ai["hello"] = addIndexedAccessor(MWMechanics::AiSetting::Hello); } void addNpcStatsBindings(sol::table& npc, const Context& context) diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index e935fcbba3..149d9bd9fa 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -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}) From 4607722ce90310eccb206113ceacc4526f20a2d4 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 31 Mar 2024 11:37:02 +0200 Subject: [PATCH 2/2] Increment API version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5263d849e8..2bffdba34e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ message(STATUS "Configuring OpenMW...") set(OPENMW_VERSION_MAJOR 0) set(OPENMW_VERSION_MINOR 49) set(OPENMW_VERSION_RELEASE 0) -set(OPENMW_LUA_API_REVISION 58) +set(OPENMW_LUA_API_REVISION 59) set(OPENMW_POSTPROCESSING_API_REVISION 1) set(OPENMW_VERSION_COMMITHASH "")