From 1b1e81b90e6191af4f047a9378b988fcfc653a76 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 20 Mar 2022 15:39:48 +0000 Subject: [PATCH] Lua bindings for ESM::Door and ESM::Weapon records --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwlua/types/door.cpp | 24 ++++++++++ apps/openmw/mwlua/types/types.cpp | 2 +- apps/openmw/mwlua/types/types.hpp | 3 +- apps/openmw/mwlua/types/weapon.cpp | 68 ++++++++++++++++++++++++++++ apps/openmw/mwworld/store.hpp | 7 +++ files/lua_api/openmw/types.lua | 71 ++++++++++++++++++++++++++++++ 7 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 apps/openmw/mwlua/types/weapon.cpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 9a83a5cdb7..b823674d31 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -60,7 +60,7 @@ 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/types types/door types/actor types/container types/weapon ) add_openmw_dir (mwsound diff --git a/apps/openmw/mwlua/types/door.cpp b/apps/openmw/mwlua/types/door.cpp index efcf638360..5c13e27f9e 100644 --- a/apps/openmw/mwlua/types/door.cpp +++ b/apps/openmw/mwlua/types/door.cpp @@ -1,7 +1,17 @@ #include "types.hpp" +#include + +#include + #include "../luabindings.hpp" +namespace sol +{ + template <> + struct is_automagical : std::false_type {}; +} + namespace MWLua { @@ -29,6 +39,20 @@ namespace MWLua else return sol::nil; }; + + const MWWorld::Store* store = &MWBase::Environment::get().getWorld()->getStore().get(); + door["record"] = sol::overload( + [](const Object& obj) -> const ESM::Door* { return obj.ptr().get()->mBase; }, + [store](const std::string& recordId) -> const ESM::Door* { return store->find(recordId); }); + sol::usertype record = context.mLua->sol().new_usertype("ESM3_Door"); + record[sol::meta_function::to_string] = sol::readonly_property( + [](const ESM::Door& rec) -> std::string { return "ESM3_Door[" + rec.mId + "]"; }); + record["id"] = sol::readonly_property([](const ESM::Door& rec) -> std::string { return rec.mId; }); + record["name"] = sol::readonly_property([](const ESM::Door& rec) -> std::string { return rec.mName; }); + record["model"] = sol::readonly_property([](const ESM::Door& rec) -> std::string { return rec.mModel; }); + record["mwscript"] = sol::readonly_property([](const ESM::Door& rec) -> std::string { return rec.mScript; }); + record["openSound"] = sol::readonly_property([](const ESM::Door& rec) -> std::string { return rec.mOpenSound; }); + record["closeSound"] = sol::readonly_property([](const ESM::Door& rec) -> std::string { return rec.mCloseSound; }); } } diff --git a/apps/openmw/mwlua/types/types.cpp b/apps/openmw/mwlua/types/types.cpp index 556c13963f..a175031058 100644 --- a/apps/openmw/mwlua/types/types.cpp +++ b/apps/openmw/mwlua/types/types.cpp @@ -166,7 +166,7 @@ namespace MWLua addType(ObjectTypeName::Light, {ESM::REC_LIGH}, ObjectTypeName::Item); addType(ObjectTypeName::MiscItem, {ESM::REC_MISC}, ObjectTypeName::Item); addType(ObjectTypeName::Potion, {ESM::REC_ALCH}, ObjectTypeName::Item); - addType(ObjectTypeName::Weapon, {ESM::REC_WEAP}, ObjectTypeName::Item); + addWeaponBindings(addType(ObjectTypeName::Weapon, {ESM::REC_WEAP}, ObjectTypeName::Item), context); addType(ObjectTypeName::Apparatus, {ESM::REC_APPA}, ObjectTypeName::Item); addType(ObjectTypeName::Lockpick, {ESM::REC_LOCK}, ObjectTypeName::Item); addType(ObjectTypeName::Probe, {ESM::REC_PROB}, ObjectTypeName::Item); diff --git a/apps/openmw/mwlua/types/types.hpp b/apps/openmw/mwlua/types/types.hpp index 966e32ccf2..af861c0bb4 100644 --- a/apps/openmw/mwlua/types/types.hpp +++ b/apps/openmw/mwlua/types/types.hpp @@ -24,9 +24,10 @@ namespace MWLua sol::table initTypesPackage(const Context& context); // used in initTypesPackage - void addContainerBindings(sol::table door, 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); + void addWeaponBindings(sol::table weapon, const Context& context); } #endif // MWLUA_TYPES_H diff --git a/apps/openmw/mwlua/types/weapon.cpp b/apps/openmw/mwlua/types/weapon.cpp new file mode 100644 index 0000000000..746536cc69 --- /dev/null +++ b/apps/openmw/mwlua/types/weapon.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 addWeaponBindings(sol::table weapon, const Context& context) + { + weapon["TYPE"] = LuaUtil::makeReadOnly(context.mLua->tableFromPairs({ + {"ShortBladeOneHand", ESM::Weapon::ShortBladeOneHand}, + {"LongBladeOneHand", ESM::Weapon::LongBladeOneHand}, + {"LongBladeTwoHand", ESM::Weapon::LongBladeTwoHand}, + {"BluntOneHand", ESM::Weapon::BluntOneHand}, + {"BluntTwoClose", ESM::Weapon::BluntTwoClose}, + {"BluntTwoWide", ESM::Weapon::BluntTwoWide}, + {"SpearTwoWide", ESM::Weapon::SpearTwoWide}, + {"AxeOneHand", ESM::Weapon::AxeOneHand}, + {"AxeTwoHand", ESM::Weapon::AxeTwoHand}, + {"MarksmanBow", ESM::Weapon::MarksmanBow}, + {"MarksmanCrossbow", ESM::Weapon::MarksmanCrossbow}, + {"MarksmanThrown", ESM::Weapon::MarksmanThrown}, + {"Arrow", ESM::Weapon::Arrow}, + {"Bolt", ESM::Weapon::Bolt}, + })); + + const MWWorld::Store* store = &MWBase::Environment::get().getWorld()->getStore().get(); + weapon["record"] = sol::overload( + [](const Object& obj) -> const ESM::Weapon* { return obj.ptr().get()->mBase; }, + [store](const std::string& recordId) -> const ESM::Weapon* { return store->find(recordId); }); + sol::usertype record = context.mLua->sol().new_usertype("ESM3_Weapon"); + record[sol::meta_function::to_string] = sol::readonly_property( + [](const ESM::Weapon& rec) -> std::string { return "ESM3_Weapon[" + rec.mId + "]"; }); + record["id"] = sol::readonly_property([](const ESM::Weapon& rec) -> std::string { return rec.mId; }); + record["name"] = sol::readonly_property([](const ESM::Weapon& rec) -> std::string { return rec.mName; }); + record["model"] = sol::readonly_property([](const ESM::Weapon& rec) -> std::string { return rec.mModel; }); + record["icon"] = sol::readonly_property([](const ESM::Weapon& rec) -> std::string { return rec.mIcon; }); + record["enchant"] = sol::readonly_property([](const ESM::Weapon& rec) -> std::string { return rec.mEnchant; }); + record["mwscript"] = sol::readonly_property([](const ESM::Weapon& rec) -> std::string { return rec.mScript; }); + record["isMagical"] = sol::readonly_property( + [](const ESM::Weapon& rec) -> bool { return rec.mData.mFlags & ESM::Weapon::Magical; }); + record["isSilver"] = sol::readonly_property( + [](const ESM::Weapon& rec) -> bool { return rec.mData.mFlags & ESM::Weapon::Silver; }); + record["weight"] = sol::readonly_property([](const ESM::Weapon& rec) -> float { return rec.mData.mWeight; }); + record["value"] = sol::readonly_property([](const ESM::Weapon& rec) -> int { return rec.mData.mValue; }); + record["type"] = sol::readonly_property([](const ESM::Weapon& rec) -> int { return rec.mData.mType; }); + 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["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]; }); + record["slashMaxDamage"] = sol::readonly_property([](const ESM::Weapon& rec) -> int { return rec.mData.mSlash[1]; }); + record["thrustMinDamage"] = sol::readonly_property([](const ESM::Weapon& rec) -> int { return rec.mData.mThrust[0]; }); + record["thrustMaxDamage"] = sol::readonly_property([](const ESM::Weapon& rec) -> int { return rec.mData.mThrust[1]; }); + } + +} diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 36860f291a..b352eaa311 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -77,6 +77,8 @@ namespace MWWorld void setUp(); const T *search(int index) const; + + // calls `search` and throws an exception if not found const T *find(int index) const; }; @@ -183,6 +185,7 @@ namespace MWWorld /** Returns a random record that starts with the named ID, or nullptr if not found. */ const T *searchRandom(const std::string &id) const; + // calls `search` and throws an exception if not found const T *find(const std::string &id) const; iterator begin() const; @@ -408,6 +411,8 @@ namespace MWWorld Store(); const ESM::Attribute *search(size_t index) const; + + // calls `search` and throws an exception if not found const ESM::Attribute *find(size_t index) const; void setUp(); @@ -428,6 +433,8 @@ namespace MWWorld Store(); const ESM::WeaponType *search(const int id) const; + + // calls `search` and throws an exception if not found const ESM::WeaponType *find(const int id) const; RecordId load(ESM::ESMReader &esm) override { return RecordId({}, false); } diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index 82dbded2e8..917a83ee8c 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -318,6 +318,58 @@ -- @param openmw.core#GameObject object -- @return #boolean +--- Weapon.TYPE +-- @type WeaponTYPE +-- @field #number ShortBladeOneHand +-- @field #number LongBladeOneHand +-- @field #number LongBladeTwoHand +-- @field #number BluntOneHand +-- @field #number BluntTwoClose +-- @field #number BluntTwoWide +-- @field #number SpearTwoWide +-- @field #number AxeOneHand +-- @field #number AxeTwoHand +-- @field #number MarksmanBow +-- @field #number MarksmanCrossbow +-- @field #number MarksmanThrown +-- @field #number Arrow +-- @field #number Bolt + +--- @{#WeaponTYPE} +-- @field [parent=#Weapon] #WeaponTYPE TYPE + +--- +-- Returns the read-only @{#WeaponRecord} of a weapon +-- @function [parent=#Weapon] record +-- @param #any objectOrRecordId +-- @return #WeaponRecord + +--- +-- @type WeaponRecord +-- @field #string id Record id +-- @field #string name Human-readable name +-- @field #string model VFS path to the model +-- @field #string mwscript MWScript on this door (can be empty) +-- @field #string icon +-- @field #string enchant +-- @field #boolean isMagical +-- @field #boolean isSilver +-- @field #number weight +-- @field #number value +-- @field #number type See @{#Weapon.TYPE} +-- @field #number health +-- @field #number speed +-- @field #number reach +-- @field #number enchant +-- @field #number chopMinDamage +-- @field #number chopMaxDamage +-- @field #number slashMinDamage +-- @field #number slashMaxDamage +-- @field #number thrustMinDamage +-- @field #number thrustMaxDamage + + + --- @{#Apparatus} functions -- @field [parent=#types] #Apparatus Apparatus @@ -404,6 +456,8 @@ -- @param openmw.core#GameObject object -- @return #boolean + + --- @{#Door} functions -- @field [parent=#types] #Door Door @@ -440,6 +494,23 @@ -- @param openmw.core#GameObject object -- @return openmw.core#Cell +--- +-- Returns the read-only @{#DoorRecord} of a door +-- @function [parent=#Door] record +-- @param #any objectOrRecordId +-- @return #DoorRecord + +--- +-- @type DoorRecord +-- @field #string id Record id +-- @field #string name Human-readable name +-- @field #string model VFS path to the model +-- @field #string mwscript MWScript on this door (can be empty) +-- @field #string openSound VFS path to the sound of opening +-- @field #string closeSound VFS path to the sound of closing + + + --- Functions for @{#Static} objects -- @field [parent=#types] #Static Static