From cd0e612cb703b6d8665c85da53dc091355334203 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 7 Sep 2023 21:30:08 +0200 Subject: [PATCH] Expose skill and attribute records to Lua and deprecate their enums --- apps/openmw/mwlua/luabindings.cpp | 2 + apps/openmw/mwlua/stats.cpp | 80 +++++++++++++++++++++++++++++++ apps/openmw/mwlua/stats.hpp | 1 + files/lua_api/openmw/core.lua | 58 +++++++++++++++++++++- files/lua_api/openmw/types.lua | 2 +- 5 files changed, 140 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwlua/luabindings.cpp b/apps/openmw/mwlua/luabindings.cpp index d844670eca..9aac877e4b 100644 --- a/apps/openmw/mwlua/luabindings.cpp +++ b/apps/openmw/mwlua/luabindings.cpp @@ -42,6 +42,7 @@ #include "objectbindings.hpp" #include "postprocessingbindings.hpp" #include "soundbindings.hpp" +#include "stats.hpp" #include "types/types.hpp" #include "uibindings.hpp" #include "vfsbindings.hpp" @@ -151,6 +152,7 @@ namespace MWLua }; addTimeBindings(api, context, false); api["magic"] = initCoreMagicBindings(context); + api["stats"] = initCoreStatsBindings(context); api["l10n"] = LuaUtil::initL10nLoader(lua->sol(), MWBase::Environment::get().getL10nManager()); const MWWorld::Store* gmstStore = &MWBase::Environment::get().getESMStore()->get(); diff --git a/apps/openmw/mwlua/stats.cpp b/apps/openmw/mwlua/stats.cpp index c202e9dc33..5c1e536dd6 100644 --- a/apps/openmw/mwlua/stats.cpp +++ b/apps/openmw/mwlua/stats.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include #include "context.hpp" #include "localscripts.hpp" @@ -20,6 +22,7 @@ #include "../mwworld/esmstore.hpp" #include "objectvariant.hpp" +#include "types/types.hpp" namespace { @@ -336,6 +339,18 @@ namespace sol struct is_automagical : std::false_type { }; + template <> + struct is_automagical : std::false_type + { + }; + template <> + struct is_automagical : std::false_type + { + }; + template <> + struct is_automagical : std::false_type + { + }; } namespace MWLua @@ -393,4 +408,69 @@ namespace MWLua for (const ESM::Skill& skill : MWBase::Environment::get().getESMStore()->get()) skills[ESM::RefId(skill.mId).serializeText()] = addIndexedAccessor(skill.mId); } + + sol::table initCoreStatsBindings(const Context& context) + { + sol::state_view& lua = context.mLua->sol(); + sol::table statsApi(lua, sol::create); + auto* vfs = MWBase::Environment::get().getResourceSystem()->getVFS(); + + sol::table attributes(lua, sol::create); + addRecordFunctionBinding(attributes, context); + statsApi["Attribute"] = LuaUtil::makeReadOnly(attributes); + statsApi["Attribute"][sol::metatable_key][sol::meta_function::to_string] = ESM::Attribute::getRecordType; + + auto attributeT = context.mLua->sol().new_usertype("Attribute"); + attributeT[sol::meta_function::to_string] + = [](const ESM::Attribute& rec) { return "ESM3_Attribute[" + rec.mId.toDebugString() + "]"; }; + attributeT["id"] = sol::readonly_property( + [](const ESM::Attribute& rec) -> std::string { return ESM::RefId{ rec.mId }.serializeText(); }); + attributeT["name"] + = sol::readonly_property([](const ESM::Attribute& rec) -> std::string_view { return rec.mName; }); + attributeT["description"] + = sol::readonly_property([](const ESM::Attribute& rec) -> std::string_view { return rec.mDescription; }); + attributeT["icon"] = sol::readonly_property([vfs](const ESM::Attribute& rec) -> std::string { + return Misc::ResourceHelpers::correctIconPath(rec.mIcon, vfs); + }); + + sol::table skills(lua, sol::create); + addRecordFunctionBinding(skills, context); + statsApi["Skill"] = LuaUtil::makeReadOnly(skills); + statsApi["Skill"][sol::metatable_key][sol::meta_function::to_string] = ESM::Skill::getRecordType; + + auto skillT = context.mLua->sol().new_usertype("Skill"); + skillT[sol::meta_function::to_string] + = [](const ESM::Skill& rec) { return "ESM3_Skill[" + rec.mId.toDebugString() + "]"; }; + skillT["id"] = sol::readonly_property( + [](const ESM::Skill& rec) -> std::string { return ESM::RefId{ rec.mId }.serializeText(); }); + skillT["name"] = sol::readonly_property([](const ESM::Skill& rec) -> std::string_view { return rec.mName; }); + skillT["description"] + = sol::readonly_property([](const ESM::Skill& rec) -> std::string_view { return rec.mDescription; }); + skillT["icon"] = sol::readonly_property([vfs](const ESM::Skill& rec) -> std::string { + return Misc::ResourceHelpers::correctIconPath(rec.mIcon, vfs); + }); + skillT["school"] = sol::readonly_property([](const ESM::Skill& rec) -> const ESM::MagicSchool* { + if (!rec.mSchool) + return nullptr; + return &*rec.mSchool; + }); + + auto schoolT = context.mLua->sol().new_usertype("MagicSchool"); + schoolT[sol::meta_function::to_string] + = [](const ESM::MagicSchool& rec) { return "ESM3_MagicSchool[" + rec.mName + "]"; }; + schoolT["name"] + = sol::readonly_property([](const ESM::MagicSchool& rec) -> std::string_view { return rec.mName; }); + schoolT["areaSound"] = sol::readonly_property( + [](const ESM::MagicSchool& rec) -> std::string { return rec.mAreaSound.serializeText(); }); + schoolT["boltSound"] = sol::readonly_property( + [](const ESM::MagicSchool& rec) -> std::string { return rec.mBoltSound.serializeText(); }); + schoolT["castSound"] = sol::readonly_property( + [](const ESM::MagicSchool& rec) -> std::string { return rec.mCastSound.serializeText(); }); + schoolT["failureSound"] = sol::readonly_property( + [](const ESM::MagicSchool& rec) -> std::string { return rec.mFailureSound.serializeText(); }); + schoolT["hitSound"] = sol::readonly_property( + [](const ESM::MagicSchool& rec) -> std::string { return rec.mHitSound.serializeText(); }); + + return LuaUtil::makeReadOnly(statsApi); + } } diff --git a/apps/openmw/mwlua/stats.hpp b/apps/openmw/mwlua/stats.hpp index 8c5824cc71..4ce2f6b5eb 100644 --- a/apps/openmw/mwlua/stats.hpp +++ b/apps/openmw/mwlua/stats.hpp @@ -9,6 +9,7 @@ namespace MWLua void addActorStatsBindings(sol::table& actor, const Context& context); void addNpcStatsBindings(sol::table& npc, const Context& context); + sol::table initCoreStatsBindings(const Context& context); } #endif diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index abe151eb73..3bd86de5be 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -429,9 +429,10 @@ -- @usage for _, item in ipairs(inventory:findAll('common_shirt_01')) do ... end ---- Possible @{#ATTRIBUTE} values +--- Possible @{#ATTRIBUTE} values (DEPRECATED use @{#Attribute}) -- @field [parent=#core] #ATTRIBUTE ATTRIBUTE +--- DEPRECATED, use @{#Attribute} --- `core.ATTRIBUTE` -- @type ATTRIBUTE -- @field #string Strength "strength" @@ -444,9 +445,10 @@ -- @field #string Luck "luck" ---- Possible @{#SKILL} values +--- Possible @{#SKILL} values (DEPRECATED use @{#Skill}) -- @field [parent=#core] #SKILL SKILL +--- DEPRECATED, use @{#Skill} --- `core.SKILL` -- @type SKILL -- @field #string Acrobatics "acrobatics" @@ -866,4 +868,56 @@ -- print(sound.fileName) -- end + +--- @{#Stats}: stats +-- @field [parent=#core] #Stats stats + + +--- @{#Attribute} functions +-- @field [parent=#Stats] #Attribute Attribute + +--- `core.stats.Attribute` +-- @type Attribute +-- @field #list<#AttributeRecord> records A read-only list of all @{#AttributeRecord}s in the world database. + +--- +-- Returns a read-only @{#AttributeRecord} +-- @function [parent=#Attribute] record +-- @param #string recordId +-- @return #AttributeRecord + +--- @{#Skill} functions +-- @field [parent=#Stats] #Skill Skill + +--- `core.stats.Skill` +-- @type Skill +-- @field #list<#SkillRecord> records A read-only list of all @{#SkillRecord}s in the world database. + +--- +-- Returns a read-only @{#SkillRecord} +-- @function [parent=#Skill] record +-- @param #string recordId +-- @return #SkillRecord + +-- @type AttributeRecord +-- @field #string id Record id +-- @field #string name Human-readable name +-- @field #string description Human-readable description +-- @field #string icon VFS path to the icon + +-- @type SkillRecord +-- @field #string id Record id +-- @field #string name Human-readable name +-- @field #string description Human-readable description +-- @field #string icon VFS path to the icon +-- @field #MagicSchoolData school Optional magic school + +-- @type MagicSchoolData +-- @field #string name Human-readable name +-- @field #string areaSound VFS path to the area sound +-- @field #string boltSound VFS path to the bolt sound +-- @field #string castSound VFS path to the cast sound +-- @field #string failureSound VFS path to the failure sound +-- @field #string hitSound VFS path to the hit sound + return nil diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index 557bbabd86..b491203052 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -919,7 +919,7 @@ -- @field #string speechcraft "speechcraft" -- @field #string unarmored "unarmored" ---- DEPRECATED, use @{openmw.core#SKILL} +--- DEPRECATED, use @{openmw.core#Skill} -- @field [parent=#Book] #BookSKILL SKILL ---