From 45f25e3f1464e962b9098b59d2d4c257bf576d32 Mon Sep 17 00:00:00 2001 From: Zackhasacat Date: Tue, 29 Aug 2023 11:19:11 -0500 Subject: [PATCH] Add in initial support --- apps/openmw/mwlua/types/activator.cpp | 18 ++++-- apps/openmw/mwlua/types/armor.cpp | 56 +++++++++++++------ apps/openmw/mwlua/types/book.cpp | 69 +++++++++++++++-------- apps/openmw/mwlua/types/clothing.cpp | 50 ++++++++++++----- apps/openmw/mwlua/types/misc.cpp | 28 +++++++--- apps/openmw/mwlua/types/potion.cpp | 41 +++++++++----- apps/openmw/mwlua/types/weapon.cpp | 80 ++++++++++++++++++--------- files/lua_api/openmw/types.lua | 14 ++--- 8 files changed, 239 insertions(+), 117 deletions(-) diff --git a/apps/openmw/mwlua/types/activator.cpp b/apps/openmw/mwlua/types/activator.cpp index 9fec22b221..a9edc1493f 100644 --- a/apps/openmw/mwlua/types/activator.cpp +++ b/apps/openmw/mwlua/types/activator.cpp @@ -22,11 +22,19 @@ namespace ESM::Activator tableToActivator(const sol::table& rec) { ESM::Activator activator; - activator.mName = rec["name"]; - activator.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); - std::string_view scriptId = rec["mwscript"].get(); - activator.mScript = ESM::RefId::deserializeText(scriptId); - activator.mRecordFlags = 0; + if (rec["template"] != sol::nil) + activator = LuaUtil::cast(rec["template"]); + else + activator.blank(); + if (rec["name"] != sol::nil) + activator.mName = rec["name"]; + if (rec["model"] != sol::nil) + activator.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); + if (rec["mwscript"] != sol::nil) + { + std::string_view scriptId = rec["mwscript"].get(); + activator.mScript = ESM::RefId::deserializeText(scriptId); + } return activator; } } diff --git a/apps/openmw/mwlua/types/armor.cpp b/apps/openmw/mwlua/types/armor.cpp index 9f28f56e2f..4808107ebf 100644 --- a/apps/openmw/mwlua/types/armor.cpp +++ b/apps/openmw/mwlua/types/armor.cpp @@ -22,25 +22,45 @@ namespace ESM::Armor tableToArmor(const sol::table& rec) { ESM::Armor armor; - armor.mName = rec["name"]; - armor.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); - armor.mIcon = rec["icon"]; - std::string_view enchantId = rec["enchant"].get(); - armor.mEnchant = ESM::RefId::deserializeText(enchantId); - std::string_view scriptId = rec["mwscript"].get(); - armor.mScript = ESM::RefId::deserializeText(scriptId); - - armor.mData.mWeight = rec["weight"]; - armor.mData.mValue = rec["value"]; - int armorType = rec["type"].get(); - if (armorType >= 0 && armorType <= ESM::Armor::RBracer) - armor.mData.mType = armorType; + if (rec["template"] != sol::nil) + armor = LuaUtil::cast(rec["template"]); else - throw std::runtime_error("Invalid Armor Type provided: " + std::to_string(armorType)); - armor.mData.mHealth = rec["health"]; - armor.mData.mArmor = rec["baseArmor"]; - armor.mData.mEnchant = std::round(rec["enchantCapacity"].get() * 10); - armor.mRecordFlags = 0; + armor.blank(); + if (rec["name"] != sol::nil) + armor.mName = rec["name"]; + if (rec["model"] != sol::nil) + armor.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); + if (rec["icon"] != sol::nil) + armor.mIcon = rec["icon"]; + if (rec["enchant"] != sol::nil) + { + std::string_view enchantId = rec["enchant"].get(); + armor.mEnchant = ESM::RefId::deserializeText(enchantId); + } + if (rec["mwscript"] != sol::nil) + { + std::string_view scriptId = rec["mwscript"].get(); + armor.mScript = ESM::RefId::deserializeText(scriptId); + } + + if (rec["weight"] != sol::nil) + armor.mData.mWeight = rec["weight"]; + if (rec["value"] != sol::nil) + armor.mData.mValue = rec["value"]; + if (rec["type"] != sol::nil) + { + int armorType = rec["type"].get(); + if (armorType >= 0 && armorType <= ESM::Armor::RBracer) + armor.mData.mType = armorType; + else + throw std::runtime_error("Invalid Armor Type provided: " + std::to_string(armorType)); + } + if (rec["health"] != sol::nil) + armor.mData.mHealth = rec["health"]; + if (rec["baseArmor"] != sol::nil) + armor.mData.mArmor = rec["baseArmor"]; + if (rec["enchantCapacity"] != sol::nil) + armor.mData.mEnchant = std::round(rec["enchantCapacity"].get() * 10); return armor; } diff --git a/apps/openmw/mwlua/types/book.cpp b/apps/openmw/mwlua/types/book.cpp index 9501691a72..3436882803 100644 --- a/apps/openmw/mwlua/types/book.cpp +++ b/apps/openmw/mwlua/types/book.cpp @@ -27,30 +27,55 @@ namespace ESM::Book tableToBook(const sol::table& rec) { ESM::Book book; - book.mName = rec["name"]; - book.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); - book.mIcon = rec["icon"]; - book.mText = rec["text"]; - std::string_view enchantId = rec["enchant"].get(); - book.mEnchant = ESM::RefId::deserializeText(enchantId); - - book.mData.mEnchant = std::round(rec["enchantCapacity"].get() * 10); - std::string_view scriptId = rec["mwscript"].get(); - book.mScript = ESM::RefId::deserializeText(scriptId); - book.mData.mWeight = rec["weight"]; - book.mData.mValue = rec["value"]; - book.mData.mIsScroll = rec["isScroll"]; - book.mRecordFlags = 0; - - ESM::RefId skill = ESM::RefId::deserializeText(rec["skill"].get()); - - book.mData.mSkillId = -1; - if (!skill.empty()) + if (rec["template"] != sol::nil) + book = LuaUtil::cast(rec["template"]); + else { - book.mData.mSkillId = ESM::Skill::refIdToIndex(skill); - if (book.mData.mSkillId == -1) - throw std::runtime_error("Incorrect skill: " + skill.toDebugString()); + book.blank(); + book.mData.mSkillId = -1; } + if (rec["name"] != sol::nil) + book.mName = rec["name"]; + if (rec["model"] != sol::nil) + book.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); + if (rec["icon"] != sol::nil) + book.mIcon = rec["icon"]; + if (rec["text"] != sol::nil) + book.mText = rec["text"]; + if (rec["enchant"] != sol::nil) + { + std::string_view enchantId = rec["enchant"].get(); + book.mEnchant = ESM::RefId::deserializeText(enchantId); + } + + if (rec["enchantCapacity"] != sol::nil) + book.mData.mEnchant = std::round(rec["enchantCapacity"].get() * 10); + if (rec["mwscript"] != sol::nil) + { + std::string_view scriptId = rec["mwscript"].get(); + book.mScript = ESM::RefId::deserializeText(scriptId); + } + if (rec["weight"] != sol::nil) + book.mData.mWeight = rec["weight"]; + if (rec["value"] != sol::nil) + book.mData.mValue = rec["value"]; + if (rec["isScroll"] != sol::nil) + book.mData.mIsScroll = rec["isScroll"]; + + if (rec["skill"] != sol::nil) + { + ESM::RefId skill = ESM::RefId::deserializeText(rec["skill"].get()); + + book.mData.mSkillId = -1; + if (!skill.empty()) + { + book.mData.mSkillId = ESM::Skill::refIdToIndex(skill); + if (book.mData.mSkillId == -1) + throw std::runtime_error("Incorrect skill: " + skill.toDebugString()); + } + } + + return book; } } diff --git a/apps/openmw/mwlua/types/clothing.cpp b/apps/openmw/mwlua/types/clothing.cpp index 9bdd579286..d9d0e42579 100644 --- a/apps/openmw/mwlua/types/clothing.cpp +++ b/apps/openmw/mwlua/types/clothing.cpp @@ -22,22 +22,42 @@ namespace ESM::Clothing tableToClothing(const sol::table& rec) { ESM::Clothing clothing; - clothing.mName = rec["name"]; - clothing.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); - clothing.mIcon = rec["icon"]; - std::string_view scriptId = rec["mwscript"].get(); - clothing.mScript = ESM::RefId::deserializeText(scriptId); - clothing.mData.mEnchant = std::round(rec["enchantCapacity"].get() * 10); - std::string_view enchantId = rec["enchant"].get(); - clothing.mEnchant = ESM::RefId::deserializeText(enchantId); - clothing.mData.mWeight = rec["weight"]; - clothing.mData.mValue = rec["value"]; - clothing.mRecordFlags = 0; - int clothingType = rec["type"].get(); - if (clothingType >= 0 && clothingType <= ESM::Clothing::Amulet) - clothing.mData.mType = clothingType; + if (rec["template"] != sol::nil) + clothing = LuaUtil::cast(rec["template"]); else - throw std::runtime_error("Invalid Clothing Type provided: " + std::to_string(clothingType)); + clothing.blank(); + + if (rec["name"] != sol::nil) + clothing.mName = rec["name"]; + if (rec["model"] != sol::nil) + clothing.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); + if (rec["icon"] != sol::nil) + clothing.mIcon = rec["icon"]; + if (rec["mwscript"] != sol::nil) + { + std::string_view scriptId = rec["mwscript"].get(); + clothing.mScript = ESM::RefId::deserializeText(scriptId); + } + + if (rec["enchant"] != sol::nil) + { + std::string_view enchantId = rec["enchant"].get(); + clothing.mEnchant = ESM::RefId::deserializeText(enchantId); + } + if (rec["enchantCapacity"] != sol::nil) + clothing.mData.mEnchant = std::round(rec["enchantCapacity"].get() * 10); + if (rec["weight"] != sol::nil) + clothing.mData.mWeight = rec["weight"]; + if (rec["value"] != sol::nil) + clothing.mData.mValue = rec["value"]; + if (rec["type"] != sol::nil) + { + int clothingType = rec["type"].get(); + if (clothingType >= 0 && clothingType <= ESM::Clothing::Amulet) + clothing.mData.mType = clothingType; + else + throw std::runtime_error("Invalid Clothing Type provided: " + std::to_string(clothingType)); + } return clothing; } } diff --git a/apps/openmw/mwlua/types/misc.cpp b/apps/openmw/mwlua/types/misc.cpp index 461444abff..d359534638 100644 --- a/apps/openmw/mwlua/types/misc.cpp +++ b/apps/openmw/mwlua/types/misc.cpp @@ -24,15 +24,25 @@ namespace ESM::Miscellaneous tableToMisc(const sol::table& rec) { ESM::Miscellaneous misc; - misc.mName = rec["name"]; - misc.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); - misc.mIcon = rec["icon"]; - std::string_view scriptId = rec["mwscript"].get(); - misc.mScript = ESM::RefId::deserializeText(scriptId); - misc.mData.mWeight = rec["weight"]; - misc.mData.mValue = rec["value"]; - misc.mData.mFlags = 0; - misc.mRecordFlags = 0; + if (rec["template"] != sol::nil) + misc = LuaUtil::cast(rec["template"]); + else + misc.blank(); + if (rec["name"] != sol::nil) + misc.mName = rec["name"]; + if (rec["model"] != sol::nil) + misc.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); + if (rec["icon"] != sol::nil) + misc.mIcon = rec["icon"]; + if (rec["mwscript"] != sol::nil) + { + std::string_view scriptId = rec["mwscript"].get(); + misc.mScript = ESM::RefId::deserializeText(scriptId); + } + if (rec["weight"] != sol::nil) + misc.mData.mWeight = rec["weight"]; + if (rec["value"] != sol::nil) + misc.mData.mValue = rec["value"]; return misc; } } diff --git a/apps/openmw/mwlua/types/potion.cpp b/apps/openmw/mwlua/types/potion.cpp index badf611bc7..022af56b02 100644 --- a/apps/openmw/mwlua/types/potion.cpp +++ b/apps/openmw/mwlua/types/potion.cpp @@ -23,20 +23,33 @@ namespace ESM::Potion tableToPotion(const sol::table& rec) { ESM::Potion potion; - potion.mName = rec["name"]; - potion.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); - potion.mIcon = rec["icon"]; - std::string_view scriptId = rec["mwscript"].get(); - potion.mScript = ESM::RefId::deserializeText(scriptId); - potion.mData.mWeight = rec["weight"]; - potion.mData.mValue = rec["value"]; - potion.mData.mAutoCalc = 0; - potion.mRecordFlags = 0; - sol::table effectsTable = rec["effects"]; - size_t numEffects = effectsTable.size(); - potion.mEffects.mList.resize(numEffects); - for (size_t i = 0; i < numEffects; ++i) - potion.mEffects.mList[i] = LuaUtil::cast(effectsTable[i + 1]); + if (rec["template"] != sol::nil) + potion = LuaUtil::cast(rec["template"]); + else + potion.blank(); + if (rec["name"] != sol::nil) + potion.mName = rec["name"]; + if (rec["model"] != sol::nil) + potion.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); + if (rec["icon"] != sol::nil) + potion.mIcon = rec["icon"]; + if (rec["mwscript"] != sol::nil) + { + std::string_view scriptId = rec["mwscript"].get(); + potion.mScript = ESM::RefId::deserializeText(scriptId); + } + if (rec["weight"] != sol::nil) + potion.mData.mWeight = rec["weight"]; + if (rec["value"] != sol::nil) + potion.mData.mValue = rec["value"]; + if (rec["effects"] != sol::nil) + { + sol::table effectsTable = rec["effects"]; + size_t numEffects = effectsTable.size(); + potion.mEffects.mList.resize(numEffects); + for (size_t i = 0; i < numEffects; ++i) + potion.mEffects.mList[i] = LuaUtil::cast(effectsTable[i + 1]); + } return potion; } } diff --git a/apps/openmw/mwlua/types/weapon.cpp b/apps/openmw/mwlua/types/weapon.cpp index 1cbe9b1d26..e927fedadd 100644 --- a/apps/openmw/mwlua/types/weapon.cpp +++ b/apps/openmw/mwlua/types/weapon.cpp @@ -24,37 +24,63 @@ namespace ESM::Weapon tableToWeapon(const sol::table& rec) { ESM::Weapon weapon; - weapon.mName = rec["name"]; - weapon.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); - weapon.mIcon = rec["icon"]; - std::string_view enchantId = rec["enchant"].get(); - weapon.mEnchant = ESM::RefId::deserializeText(enchantId); - std::string_view scriptId = rec["mwscript"].get(); - weapon.mScript = ESM::RefId::deserializeText(scriptId); - weapon.mData.mFlags = 0; - weapon.mRecordFlags = 0; + if (rec["template"] != sol::nil) + weapon = LuaUtil::cast(rec["template"]); + else + weapon.blank(); + + if (rec["name"] != sol::nil) + weapon.mName = rec["name"]; + if (rec["model"] != sol::nil) + weapon.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get()); + if (rec["icon"] != sol::nil) + weapon.mIcon = rec["icon"]; + if (rec["enchant"] != sol::nil) + { + std::string_view enchantId = rec["enchant"].get(); + weapon.mEnchant = ESM::RefId::deserializeText(enchantId); + } + if (rec["mwscript"] != sol::nil) + { + std::string_view scriptId = rec["mwscript"].get(); + weapon.mScript = ESM::RefId::deserializeText(scriptId); + } if (rec["isMagical"]) weapon.mData.mFlags |= ESM::Weapon::Magical; if (rec["isSilver"]) weapon.mData.mFlags |= ESM::Weapon::Silver; - int weaponType = rec["type"].get(); - if (weaponType >= 0 && weaponType <= ESM::Weapon::MarksmanThrown) - weapon.mData.mType = weaponType; - else - throw std::runtime_error("Invalid Weapon Type provided: " + std::to_string(weaponType)); - - weapon.mData.mWeight = rec["weight"]; - weapon.mData.mValue = rec["value"]; - weapon.mData.mHealth = rec["health"]; - weapon.mData.mSpeed = rec["speed"]; - weapon.mData.mReach = rec["reach"]; - weapon.mData.mEnchant = std::round(rec["enchantCapacity"].get() * 10); - weapon.mData.mChop[0] = rec["chopMinDamage"]; - weapon.mData.mChop[1] = rec["chopMaxDamage"]; - weapon.mData.mSlash[0] = rec["slashMinDamage"]; - weapon.mData.mSlash[1] = rec["slashMaxDamage"]; - weapon.mData.mThrust[0] = rec["thrustMinDamage"]; - weapon.mData.mThrust[1] = rec["thrustMaxDamage"]; + if (rec["type"] != sol::nil) + { + int weaponType = rec["type"].get(); + if (weaponType >= 0 && weaponType <= ESM::Weapon::MarksmanThrown) + weapon.mData.mType = weaponType; + else + throw std::runtime_error("Invalid Weapon Type provided: " + std::to_string(weaponType)); + } + if (rec["weight"] != sol::nil) + weapon.mData.mWeight = rec["weight"]; + if (rec["value"] != sol::nil) + weapon.mData.mValue = rec["value"]; + if (rec["health"] != sol::nil) + weapon.mData.mHealth = rec["health"]; + if (rec["speed"] != sol::nil) + weapon.mData.mSpeed = rec["speed"]; + if (rec["reach"] != sol::nil) + weapon.mData.mReach = rec["reach"]; + if (rec["enchantCapacity"] != sol::nil) + weapon.mData.mEnchant = std::round(rec["enchantCapacity"].get() * 10); + if (rec["chopMinDamage"] != sol::nil) + weapon.mData.mChop[0] = rec["chopMinDamage"]; + if (rec["chopMaxDamage"] != sol::nil) + weapon.mData.mChop[1] = rec["chopMaxDamage"]; + if (rec["slashMinDamage"] != sol::nil) + weapon.mData.mSlash[0] = rec["slashMinDamage"]; + if (rec["slashMaxDamage"] != sol::nil) + weapon.mData.mSlash[1] = rec["slashMaxDamage"]; + if (rec["thrustMinDamage"] != sol::nil) + weapon.mData.mThrust[0] = rec["thrustMinDamage"]; + if (rec["thrustMaxDamage"] != sol::nil) + weapon.mData.mThrust[1] = rec["thrustMaxDamage"]; return weapon; } diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index cc8a0365f1..382fb64a43 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -849,7 +849,7 @@ -- Creates a @{#ArmorRecord} without adding it to the world database. -- Use @{openmw_world#(world).createRecord} to add the record to the world. -- @function [parent=#Armor] createRecordDraft --- @param #ArmorRecord armor A Lua table with the fields of a ArmorRecord. +-- @param #ArmorRecord armor A Lua table with the fields of a ArmorRecord, with an additional field `template` that accepts a @{#ArmorRecord} as a base. -- @return #ArmorRecord A strongly typed Armor record. @@ -926,7 +926,7 @@ -- Creates a @{#BookRecord} without adding it to the world database. -- Use @{openmw_world#(world).createRecord} to add the record to the world. -- @function [parent=#Book] createRecordDraft --- @param #BookRecord book A Lua table with the fields of a BookRecord. +-- @param #BookRecord book A Lua table with the fields of a BookRecord, with an additional field `template` that accepts a @{#BookRecord} as a base. -- @return #BookRecord A strongly typed Book record. --- @{#Clothing} functions @@ -970,7 +970,7 @@ -- Creates a @{#ClothingRecord} without adding it to the world database. -- Use @{openmw_world#(world).createRecord} to add the record to the world. -- @function [parent=#Clothing] createRecordDraft --- @param #ClothingRecord clothing A Lua table with the fields of a ClothingRecord. +-- @param #ClothingRecord clothing A Lua table with the fields of a ClothingRecord, with an additional field `template` that accepts a @{#ClothingRecord} as a base. -- @return #ClothingRecord A strongly typed clothing record. --- @@ -1145,7 +1145,7 @@ -- Creates a @{#MiscellaneousRecord} without adding it to the world database. -- Use @{openmw_world#(world).createRecord} to add the record to the world. -- @function [parent=#Miscellaneous] createRecordDraft --- @param #MiscellaneousRecord miscellaneous A Lua table with the fields of a MiscellaneousRecord. +-- @param #MiscellaneousRecord miscellaneous A Lua table with the fields of a MiscellaneousRecord, with an additional field `template` that accepts a @{#MiscellaneousRecord} as a base. -- @return #MiscellaneousRecord A strongly typed Miscellaneous record. --- @@ -1190,7 +1190,7 @@ -- Creates a @{#PotionRecord} without adding it to the world database. -- Use @{openmw_world#(world).createRecord} to add the record to the world. -- @function [parent=#Potion] createRecordDraft --- @param #PotionRecord potion A Lua table with the fields of a PotionRecord. +-- @param #PotionRecord potion A Lua table with the fields of a PotionRecord, with an additional field `template` that accepts a @{#PotionRecord} as a base. -- @return #PotionRecord A strongly typed Potion record. --- @@ -1275,7 +1275,7 @@ -- Creates a @{#WeaponRecord} without adding it to the world database. -- Use @{openmw_world#(world).createRecord} to add the record to the world. -- @function [parent=#Weapon] createRecordDraft --- @param #WeaponRecord weapon A Lua table with the fields of a WeaponRecord. +-- @param #WeaponRecord weapon A Lua table with the fields of a WeaponRecord, with an additional field `template` that accepts a @{#WeaponRecord} as a base. -- @return #WeaponRecord A strongly typed Weapon record. --- @{#Apparatus} functions @@ -1450,7 +1450,7 @@ -- Creates a @{#ActivatorRecord} without adding it to the world database. -- Use @{openmw_world#(world).createRecord} to add the record to the world. -- @function [parent=#Activator] createRecordDraft --- @param #ActivatorRecord activator A Lua table with the fields of a ActivatorRecord. +-- @param #ActivatorRecord activator A Lua table with the fields of a ActivatorRecord, with an additional field `template` that accepts a @{#ActivatorRecord} as a base. -- @return #ActivatorRecord A strongly typed Activator record.