From cad68a5566c98177e589a1042cf728e5bdbe8c32 Mon Sep 17 00:00:00 2001 From: kuyondo Date: Thu, 19 May 2022 20:02:18 +0800 Subject: [PATCH 1/5] Add lua binding for books --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwlua/types/book.cpp | 68 +++++++++++++++++++++++++++++++ apps/openmw/mwlua/types/types.cpp | 1 + apps/openmw/mwlua/types/types.hpp | 1 + files/lua_api/openmw/types.lua | 54 ++++++++++++++++++++++++ 5 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 apps/openmw/mwlua/types/book.cpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index b4a8bdac80..9a19c3e1d6 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -62,7 +62,7 @@ add_openmw_dir (mwlua luamanagerimp object worldview userdataserializer eventqueue luabindings localscripts playerscripts objectbindings cellbindings asyncbindings settingsbindings camerabindings uibindings inputbindings nearbybindings postprocessingbindings stats debugbindings - types/types types/door types/actor types/container types/weapon types/npc types/creature types/activator + types/types types/door types/actor types/container types/weapon types/npc types/creature types/activator types/book ) add_openmw_dir (mwsound diff --git a/apps/openmw/mwlua/types/book.cpp b/apps/openmw/mwlua/types/book.cpp new file mode 100644 index 0000000000..a8c9563a43 --- /dev/null +++ b/apps/openmw/mwlua/types/book.cpp @@ -0,0 +1,68 @@ +#include "types.hpp" + +#include + +#include + +#include "../luabindings.hpp" + +namespace sol +{ + template <> + struct is_automagical : std::false_type {}; +} + +namespace MWLua +{ + void addBookBindings(sol::table book, const Context& context) + { + book["SKILL"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs({ + {"Acrobatics", ESM::Skill::Acrobatics}, + {"Alchemy", ESM::Skill::Alchemy}, + {"Alteration", ESM::Skill::Alteration}, + {"Armorer", ESM::Skill::Armorer}, + {"Athletics", ESM::Skill::Athletics}, + {"Axe", ESM::Skill::Axe}, + {"Block", ESM::Skill::Block}, + {"BluntWeapon", ESM::Skill::BluntWeapon}, + {"Conjuration", ESM::Skill::Conjuration}, + {"Destruction", ESM::Skill::Destruction}, + {"Enchant", ESM::Skill::Enchant}, + {"HandToHand", ESM::Skill::HandToHand}, + {"HeavyArmor", ESM::Skill::HeavyArmor}, + {"Illusion", ESM::Skill::Illusion}, + {"LightArmor", ESM::Skill::LightArmor}, + {"LongBlade", ESM::Skill::LongBlade}, + {"Marksman", ESM::Skill::Marksman}, + {"MediumArmor", ESM::Skill::MediumArmor}, + {"Mercantile", ESM::Skill::Mercantile}, + {"Mysticism", ESM::Skill::Mysticism}, + {"Restoration", ESM::Skill::Restoration}, + {"Security", ESM::Skill::Security}, + {"ShortBlade", ESM::Skill::ShortBlade}, + {"Sneak", ESM::Skill::Sneak}, + {"Spear", ESM::Skill::Spear}, + {"Speechcraft", ESM::Skill::Speechcraft}, + {"Unarmored", ESM::Skill::Unarmored}, + })); + + const MWWorld::Store* store = &MWBase::Environment::get().getWorld()->getStore().get(); + book["record"] = sol::overload( + [](const Object& obj) -> const ESM::Book* { return obj.ptr().get()->mBase; }, + [store](const std::string& recordId) -> const ESM::Book* { return store->find(recordId); }); + sol::usertype record = context.mLua->sol().new_usertype("ESM3_Book"); + record[sol::meta_function::to_string] = [](const ESM::Book& rec) { return "ESM3_Book[" + rec.mId + "]"; }; + record["id"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mId; }); + record["name"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mName; }); + record["model"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mModel; }); + record["mwscript"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mScript; }); + record["icon"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mIcon; }); + record["text"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mText; }); + record["enchant"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mEnchant; }); + record["isScroll"] = sol::readonly_property([](const ESM::Book& rec) -> bool { return rec.mData.mIsScroll; }); + record["skill"] = sol::readonly_property([](const ESM::Book& rec) -> int { return rec.mData.mSkillId; }); + record["value"] = sol::readonly_property([](const ESM::Book& rec) -> int { return rec.mData.mValue; }); + record["weight"] = sol::readonly_property([](const ESM::Book& rec) -> float { return rec.mData.mWeight; }); + record["enchantCapacity"] = sol::readonly_property([](const ESM::Book& rec) -> float { return rec.mData.mEnchant * 0.1f; }); + } +} diff --git a/apps/openmw/mwlua/types/types.cpp b/apps/openmw/mwlua/types/types.cpp index bc707059e8..be6dcb183c 100644 --- a/apps/openmw/mwlua/types/types.cpp +++ b/apps/openmw/mwlua/types/types.cpp @@ -173,6 +173,7 @@ namespace MWLua addType(ObjectTypeName::Repair, {ESM::REC_REPA}, ObjectTypeName::Item); addActivatorBindings(addType(ObjectTypeName::Activator, {ESM::REC_ACTI}), context); + addBookBindings(addType(ObjectTypeName::Book, {ESM::REC_BOOK}), context); addContainerBindings(addType(ObjectTypeName::Container, {ESM::REC_CONT}), context); addDoorBindings(addType(ObjectTypeName::Door, {ESM::REC_DOOR}), context); addType(ObjectTypeName::Static, {ESM::REC_STAT}); diff --git a/apps/openmw/mwlua/types/types.hpp b/apps/openmw/mwlua/types/types.hpp index 8373162995..f92644f443 100644 --- a/apps/openmw/mwlua/types/types.hpp +++ b/apps/openmw/mwlua/types/types.hpp @@ -25,6 +25,7 @@ namespace MWLua // used in initTypesPackage void addActivatorBindings(sol::table activator, const Context& context); + void addBookBindings(sol::table book, const Context& context); void addContainerBindings(sol::table container, const Context& context); void addDoorBindings(sol::table door, const Context& context); void addActorBindings(sol::table actor, const Context& context); diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index 257d926b50..6a58eea7bf 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -532,6 +532,60 @@ -- @param openmw.core#GameObject object -- @return #boolean +--- Book.SKILL +-- @type BookSKILL +-- @field #number Acrobatics +-- @field #number Alchemy +-- @field #number Alteration +-- @field #number Armorer +-- @field #number Athletics +-- @field #number Axe +-- @field #number Block +-- @field #number BluntWeapon +-- @field #number Conjuration +-- @field #number Destruction +-- @field #number Enchant +-- @field #number HandToHand +-- @field #number HeavyArmor +-- @field #number Illusion +-- @field #number LightArmor +-- @field #number LongBlade +-- @field #number Marksman +-- @field #number MediumArmor +-- @field #number Mercantile +-- @field #number Mysticism +-- @field #number Restoration +-- @field #number Security +-- @field #number ShortBlade +-- @field #number Sneak +-- @field #number Spear +-- @field #number Speechcraft +-- @field #number Unarmored + +--- @{#BookSKILL} +-- @field [parent=#Book] #BookSKILL SKILL + +--- +-- Returns the read-only @{#BookRecord} of a book +-- @function [parent=#Book] record +-- @param #any objectOrRecordId +-- @return #BookRecord + +--- +-- @type BookRecord +-- @field #string id The record ID of the book +-- @field #string name Name of the book +-- @field #string model VFS path to the model +-- @field #string mwscript MWScript on this book (can be empty) +-- @field #string icon VFS path to the icon +-- @field #string enchant The enchantment ID of this book (can be empty) +-- @field #string text The text content of the book +-- @field #number weight +-- @field #number value +-- @field #number skill See @{#Book.SKILL} +-- @field #boolean isScroll +-- @field #number enchantCapacity + --- @{#Clothing} functions From a26898d8eda75c670997d18569d3f76dc435b59b Mon Sep 17 00:00:00 2001 From: kuyondo Date: Thu, 19 May 2022 20:18:47 +0800 Subject: [PATCH 2/5] no addtype --- apps/openmw/mwlua/types/types.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwlua/types/types.cpp b/apps/openmw/mwlua/types/types.cpp index be6dcb183c..5330526edb 100644 --- a/apps/openmw/mwlua/types/types.cpp +++ b/apps/openmw/mwlua/types/types.cpp @@ -160,7 +160,6 @@ namespace MWLua addType(ObjectTypeName::Player, {ESM::REC_INTERNAL_PLAYER}, ObjectTypeName::NPC); addType(ObjectTypeName::Armor, {ESM::REC_ARMO}, ObjectTypeName::Item); - addType(ObjectTypeName::Book, {ESM::REC_BOOK}, ObjectTypeName::Item); addType(ObjectTypeName::Clothing, {ESM::REC_CLOT}, ObjectTypeName::Item); addType(ObjectTypeName::Ingredient, {ESM::REC_INGR}, ObjectTypeName::Item); addType(ObjectTypeName::Light, {ESM::REC_LIGH}, ObjectTypeName::Item); From 8a1a838ffa4e19076c4013c275e06642281e0504 Mon Sep 17 00:00:00 2001 From: kuyondo Date: Fri, 20 May 2022 00:39:19 +0800 Subject: [PATCH 3/5] update book.cpp and weapon.cpp --- apps/openmw/mwlua/types/book.cpp | 33 ++++-------------------------- apps/openmw/mwlua/types/weapon.cpp | 2 +- files/lua_api/openmw/types.lua | 4 ++-- 3 files changed, 7 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwlua/types/book.cpp b/apps/openmw/mwlua/types/book.cpp index a8c9563a43..597c1a07a0 100644 --- a/apps/openmw/mwlua/types/book.cpp +++ b/apps/openmw/mwlua/types/book.cpp @@ -16,35 +16,10 @@ namespace MWLua { void addBookBindings(sol::table book, const Context& context) { - book["SKILL"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs({ - {"Acrobatics", ESM::Skill::Acrobatics}, - {"Alchemy", ESM::Skill::Alchemy}, - {"Alteration", ESM::Skill::Alteration}, - {"Armorer", ESM::Skill::Armorer}, - {"Athletics", ESM::Skill::Athletics}, - {"Axe", ESM::Skill::Axe}, - {"Block", ESM::Skill::Block}, - {"BluntWeapon", ESM::Skill::BluntWeapon}, - {"Conjuration", ESM::Skill::Conjuration}, - {"Destruction", ESM::Skill::Destruction}, - {"Enchant", ESM::Skill::Enchant}, - {"HandToHand", ESM::Skill::HandToHand}, - {"HeavyArmor", ESM::Skill::HeavyArmor}, - {"Illusion", ESM::Skill::Illusion}, - {"LightArmor", ESM::Skill::LightArmor}, - {"LongBlade", ESM::Skill::LongBlade}, - {"Marksman", ESM::Skill::Marksman}, - {"MediumArmor", ESM::Skill::MediumArmor}, - {"Mercantile", ESM::Skill::Mercantile}, - {"Mysticism", ESM::Skill::Mysticism}, - {"Restoration", ESM::Skill::Restoration}, - {"Security", ESM::Skill::Security}, - {"ShortBlade", ESM::Skill::ShortBlade}, - {"Sneak", ESM::Skill::Sneak}, - {"Spear", ESM::Skill::Spear}, - {"Speechcraft", ESM::Skill::Speechcraft}, - {"Unarmored", ESM::Skill::Unarmored}, - })); + sol::table skill(context.mLua->sol(), sol::create); + book["SKILL"] = LuaUtil::makeStrictReadOnly(skill); + for (int id = ESM::Skill::Block; id < ESM::Skill::Length; ++id) + skill[(ESM::Skill::sSkillNames[id])] = id; const MWWorld::Store* store = &MWBase::Environment::get().getWorld()->getStore().get(); book["record"] = sol::overload( diff --git a/apps/openmw/mwlua/types/weapon.cpp b/apps/openmw/mwlua/types/weapon.cpp index 87ae984cf9..594e447f00 100644 --- a/apps/openmw/mwlua/types/weapon.cpp +++ b/apps/openmw/mwlua/types/weapon.cpp @@ -55,7 +55,7 @@ namespace MWLua record["health"] = sol::readonly_property([](const ESM::Weapon& rec) -> int { return rec.mData.mHealth; }); record["speed"] = sol::readonly_property([](const ESM::Weapon& rec) -> float { return rec.mData.mSpeed; }); record["reach"] = sol::readonly_property([](const ESM::Weapon& rec) -> float { return rec.mData.mReach; }); - record["enchant"] = sol::readonly_property([](const ESM::Weapon& rec) -> float { return rec.mData.mEnchant * 0.1f; }); + record["enchantCapacity"] = sol::readonly_property([](const ESM::Weapon& rec) -> float { return rec.mData.mEnchant * 0.1f; }); record["chopMinDamage"] = sol::readonly_property([](const ESM::Weapon& rec) -> int { return rec.mData.mChop[0]; }); record["chopMaxDamage"] = sol::readonly_property([](const ESM::Weapon& rec) -> int { return rec.mData.mChop[1]; }); record["slashMinDamage"] = sol::readonly_property([](const ESM::Weapon& rec) -> int { return rec.mData.mSlash[0]; }); diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index 6a58eea7bf..d7a917711b 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -582,7 +582,7 @@ -- @field #string text The text content of the book -- @field #number weight -- @field #number value --- @field #number skill See @{#Book.SKILL} +-- @field #number skill See @{#Book.SKILL} The skill that this book teaches -- @field #boolean isScroll -- @field #number enchantCapacity @@ -724,7 +724,7 @@ -- @field #number health -- @field #number speed -- @field #number reach --- @field #number enchant +-- @field #number enchantCapacity -- @field #number chopMinDamage -- @field #number chopMaxDamage -- @field #number slashMinDamage From 7dbccc914a146cee05ad5330864f35bd96c9b6c7 Mon Sep 17 00:00:00 2001 From: kuyondo Date: Fri, 20 May 2022 06:03:12 +0800 Subject: [PATCH 4/5] no skill returns nil --- apps/openmw/mwlua/types/book.cpp | 10 ++++-- files/lua_api/openmw/types.lua | 56 ++++++++++++++++---------------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/apps/openmw/mwlua/types/book.cpp b/apps/openmw/mwlua/types/book.cpp index 597c1a07a0..3fcdbec86d 100644 --- a/apps/openmw/mwlua/types/book.cpp +++ b/apps/openmw/mwlua/types/book.cpp @@ -19,7 +19,7 @@ namespace MWLua sol::table skill(context.mLua->sol(), sol::create); book["SKILL"] = LuaUtil::makeStrictReadOnly(skill); for (int id = ESM::Skill::Block; id < ESM::Skill::Length; ++id) - skill[(ESM::Skill::sSkillNames[id])] = id; + skill[Misc::StringUtils::lowerCase(ESM::Skill::sSkillNames[id])] = Misc::StringUtils::lowerCase(ESM::Skill::sSkillNames[id]); const MWWorld::Store* store = &MWBase::Environment::get().getWorld()->getStore().get(); book["record"] = sol::overload( @@ -35,9 +35,15 @@ namespace MWLua record["text"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mText; }); record["enchant"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mEnchant; }); record["isScroll"] = sol::readonly_property([](const ESM::Book& rec) -> bool { return rec.mData.mIsScroll; }); - record["skill"] = sol::readonly_property([](const ESM::Book& rec) -> int { return rec.mData.mSkillId; }); record["value"] = sol::readonly_property([](const ESM::Book& rec) -> int { return rec.mData.mValue; }); record["weight"] = sol::readonly_property([](const ESM::Book& rec) -> float { return rec.mData.mWeight; }); record["enchantCapacity"] = sol::readonly_property([](const ESM::Book& rec) -> float { return rec.mData.mEnchant * 0.1f; }); + record["skill"] = sol::readonly_property([](const ESM::Book& rec) -> sol::optional + { + if (rec.mData.mSkillId >= 0) + return Misc::StringUtils::lowerCase(ESM::Skill::sSkillNames[rec.mData.mSkillId]); + else + return sol::nullopt; + }); } } diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index d7a917711b..d9a4d36439 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -534,33 +534,33 @@ --- Book.SKILL -- @type BookSKILL --- @field #number Acrobatics --- @field #number Alchemy --- @field #number Alteration --- @field #number Armorer --- @field #number Athletics --- @field #number Axe --- @field #number Block --- @field #number BluntWeapon --- @field #number Conjuration --- @field #number Destruction --- @field #number Enchant --- @field #number HandToHand --- @field #number HeavyArmor --- @field #number Illusion --- @field #number LightArmor --- @field #number LongBlade --- @field #number Marksman --- @field #number MediumArmor --- @field #number Mercantile --- @field #number Mysticism --- @field #number Restoration --- @field #number Security --- @field #number ShortBlade --- @field #number Sneak --- @field #number Spear --- @field #number Speechcraft --- @field #number Unarmored +-- @field #string acrobatics "acrobatics" +-- @field #string alchemy "alchemy" +-- @field #string alteration "alteration" +-- @field #string armorer "armorer" +-- @field #string athletics "athletics" +-- @field #string axe "axe" +-- @field #string block "block" +-- @field #string bluntWeapon "bluntweapon" +-- @field #string conjuration "conjuration" +-- @field #string destruction "destruction" +-- @field #string enchant "enchant" +-- @field #string handToHand "handtohand" +-- @field #string heavyArmor "heavyarmor" +-- @field #string illusion "illusion" +-- @field #string lightArmor "lightarmor" +-- @field #string longBlade "longblade" +-- @field #string marksman "marksman" +-- @field #string mediumArmor "mediumarmor" +-- @field #string mercantile "mercantile" +-- @field #string mysticism "mysticism" +-- @field #string restoration "restoration" +-- @field #string security "security" +-- @field #string shortBlade "shortblade" +-- @field #string sneak "sneak" +-- @field #string spear "spear" +-- @field #string speechcraft "speechcraft" +-- @field #string unarmored "unarmored" --- @{#BookSKILL} -- @field [parent=#Book] #BookSKILL SKILL @@ -582,7 +582,7 @@ -- @field #string text The text content of the book -- @field #number weight -- @field #number value --- @field #number skill See @{#Book.SKILL} The skill that this book teaches +-- @field #string skill The skill that this book teaches. See @{#Book.SKILL} -- @field #boolean isScroll -- @field #number enchantCapacity From 5109777d3b4aabd7e58f3940ed7e43488caa2174 Mon Sep 17 00:00:00 2001 From: kuyondo Date: Fri, 20 May 2022 18:50:00 +0800 Subject: [PATCH 5/5] remove duplication --- apps/openmw/mwlua/types/book.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwlua/types/book.cpp b/apps/openmw/mwlua/types/book.cpp index 3fcdbec86d..9d34a2026e 100644 --- a/apps/openmw/mwlua/types/book.cpp +++ b/apps/openmw/mwlua/types/book.cpp @@ -19,7 +19,10 @@ namespace MWLua sol::table skill(context.mLua->sol(), sol::create); book["SKILL"] = LuaUtil::makeStrictReadOnly(skill); for (int id = ESM::Skill::Block; id < ESM::Skill::Length; ++id) - skill[Misc::StringUtils::lowerCase(ESM::Skill::sSkillNames[id])] = Misc::StringUtils::lowerCase(ESM::Skill::sSkillNames[id]); + { + std::string skillName = Misc::StringUtils::lowerCase(ESM::Skill::sSkillNames[id]); + skill[skillName] = skillName; + } const MWWorld::Store* store = &MWBase::Environment::get().getWorld()->getStore().get(); book["record"] = sol::overload(