Merge branch 'lua_template_new' into 'master'

Support 'template' field in createRecordDraft, to use an existing record as a base in lua

See merge request OpenMW/openmw!3387
macos_ci_fix
psi29a 1 year ago
commit 5ba13f7aae

@ -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>());
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
activator.mScript = ESM::RefId::deserializeText(scriptId);
activator.mRecordFlags = 0;
if (rec["template"] != sol::nil)
activator = LuaUtil::cast<ESM::Activator>(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<std::string_view>());
if (rec["mwscript"] != sol::nil)
{
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
activator.mScript = ESM::RefId::deserializeText(scriptId);
}
return activator;
}
}

@ -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<std::string_view>());
armor.mIcon = rec["icon"];
std::string_view enchantId = rec["enchant"].get<std::string_view>();
armor.mEnchant = ESM::RefId::deserializeText(enchantId);
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
armor.mScript = ESM::RefId::deserializeText(scriptId);
armor.mData.mWeight = rec["weight"];
armor.mData.mValue = rec["value"];
int armorType = rec["type"].get<int>();
if (armorType >= 0 && armorType <= ESM::Armor::RBracer)
armor.mData.mType = armorType;
if (rec["template"] != sol::nil)
armor = LuaUtil::cast<ESM::Armor>(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<float>() * 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<std::string_view>());
if (rec["icon"] != sol::nil)
armor.mIcon = rec["icon"];
if (rec["enchant"] != sol::nil)
{
std::string_view enchantId = rec["enchant"].get<std::string_view>();
armor.mEnchant = ESM::RefId::deserializeText(enchantId);
}
if (rec["mwscript"] != sol::nil)
{
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
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<int>();
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<float>() * 10);
return armor;
}

@ -27,30 +27,54 @@ namespace
ESM::Book tableToBook(const sol::table& rec)
{
ESM::Book book;
book.mName = rec["name"];
book.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get<std::string_view>());
book.mIcon = rec["icon"];
book.mText = rec["text"];
std::string_view enchantId = rec["enchant"].get<std::string_view>();
book.mEnchant = ESM::RefId::deserializeText(enchantId);
book.mData.mEnchant = std::round(rec["enchantCapacity"].get<float>() * 10);
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
book.mScript = ESM::RefId::deserializeText(scriptId);
book.mData.mWeight = rec["weight"];
book.mData.mValue = rec["value"];
book.mData.mIsScroll = rec["isScroll"];
book.mRecordFlags = 0;
if (rec["template"] != sol::nil)
book = LuaUtil::cast<ESM::Book>(rec["template"]);
else
{
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<std::string_view>());
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<std::string_view>();
book.mEnchant = ESM::RefId::deserializeText(enchantId);
}
ESM::RefId skill = ESM::RefId::deserializeText(rec["skill"].get<std::string_view>());
if (rec["enchantCapacity"] != sol::nil)
book.mData.mEnchant = std::round(rec["enchantCapacity"].get<float>() * 10);
if (rec["mwscript"] != sol::nil)
{
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
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"];
book.mData.mSkillId = -1;
if (!skill.empty())
if (rec["skill"] != sol::nil)
{
book.mData.mSkillId = ESM::Skill::refIdToIndex(skill);
if (book.mData.mSkillId == -1)
throw std::runtime_error("Incorrect skill: " + skill.toDebugString());
ESM::RefId skill = ESM::RefId::deserializeText(rec["skill"].get<std::string_view>());
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;
}
}

@ -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<std::string_view>());
clothing.mIcon = rec["icon"];
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
clothing.mScript = ESM::RefId::deserializeText(scriptId);
clothing.mData.mEnchant = std::round(rec["enchantCapacity"].get<float>() * 10);
std::string_view enchantId = rec["enchant"].get<std::string_view>();
clothing.mEnchant = ESM::RefId::deserializeText(enchantId);
clothing.mData.mWeight = rec["weight"];
clothing.mData.mValue = rec["value"];
clothing.mRecordFlags = 0;
int clothingType = rec["type"].get<int>();
if (clothingType >= 0 && clothingType <= ESM::Clothing::Amulet)
clothing.mData.mType = clothingType;
if (rec["template"] != sol::nil)
clothing = LuaUtil::cast<ESM::Clothing>(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<std::string_view>());
if (rec["icon"] != sol::nil)
clothing.mIcon = rec["icon"];
if (rec["mwscript"] != sol::nil)
{
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
clothing.mScript = ESM::RefId::deserializeText(scriptId);
}
if (rec["enchant"] != sol::nil)
{
std::string_view enchantId = rec["enchant"].get<std::string_view>();
clothing.mEnchant = ESM::RefId::deserializeText(enchantId);
}
if (rec["enchantCapacity"] != sol::nil)
clothing.mData.mEnchant = std::round(rec["enchantCapacity"].get<float>() * 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<int>();
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;
}
}

@ -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<std::string_view>());
misc.mIcon = rec["icon"];
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
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<ESM::Miscellaneous>(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<std::string_view>());
if (rec["icon"] != sol::nil)
misc.mIcon = rec["icon"];
if (rec["mwscript"] != sol::nil)
{
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
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;
}
}

@ -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<std::string_view>());
potion.mIcon = rec["icon"];
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
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<ESM::ENAMstruct>(effectsTable[i + 1]);
if (rec["template"] != sol::nil)
potion = LuaUtil::cast<ESM::Potion>(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<std::string_view>());
if (rec["icon"] != sol::nil)
potion.mIcon = rec["icon"];
if (rec["mwscript"] != sol::nil)
{
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
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<ESM::ENAMstruct>(effectsTable[i + 1]);
}
return potion;
}
}

@ -24,37 +24,74 @@ namespace
ESM::Weapon tableToWeapon(const sol::table& rec)
{
ESM::Weapon weapon;
weapon.mName = rec["name"];
weapon.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get<std::string_view>());
weapon.mIcon = rec["icon"];
std::string_view enchantId = rec["enchant"].get<std::string_view>();
weapon.mEnchant = ESM::RefId::deserializeText(enchantId);
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
weapon.mScript = ESM::RefId::deserializeText(scriptId);
weapon.mData.mFlags = 0;
weapon.mRecordFlags = 0;
if (rec["isMagical"])
weapon.mData.mFlags |= ESM::Weapon::Magical;
if (rec["isSilver"])
weapon.mData.mFlags |= ESM::Weapon::Silver;
int weaponType = rec["type"].get<int>();
if (weaponType >= 0 && weaponType <= ESM::Weapon::MarksmanThrown)
weapon.mData.mType = weaponType;
if (rec["template"] != sol::nil)
weapon = LuaUtil::cast<ESM::Weapon>(rec["template"]);
else
throw std::runtime_error("Invalid Weapon Type provided: " + std::to_string(weaponType));
weapon.blank();
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<float>() * 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["name"] != sol::nil)
weapon.mName = rec["name"];
if (rec["model"] != sol::nil)
weapon.mModel = Misc::ResourceHelpers::meshPathForESM3(rec["model"].get<std::string_view>());
if (rec["icon"] != sol::nil)
weapon.mIcon = rec["icon"];
if (rec["enchant"] != sol::nil)
{
std::string_view enchantId = rec["enchant"].get<std::string_view>();
weapon.mEnchant = ESM::RefId::deserializeText(enchantId);
}
if (rec["mwscript"] != sol::nil)
{
std::string_view scriptId = rec["mwscript"].get<std::string_view>();
weapon.mScript = ESM::RefId::deserializeText(scriptId);
}
if (auto isMagical = rec["isMagical"]; isMagical != sol::nil)
{
if (isMagical)
weapon.mData.mFlags |= ESM::Weapon::Magical;
else
weapon.mData.mFlags &= ~ESM::Weapon::Magical;
}
if (auto isSilver = rec["isSilver"]; isSilver != sol::nil)
{
if (isSilver)
weapon.mData.mFlags |= ESM::Weapon::Silver;
else
weapon.mData.mFlags &= ~ESM::Weapon::Silver;
}
if (rec["type"] != sol::nil)
{
int weaponType = rec["type"].get<int>();
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<float>() * 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;
}

@ -846,11 +846,17 @@
-- @field #number enchantCapacity
---
-- Creates a @{#ArmorRecord} without adding it to the world database.
-- Creates a @{#ArmorRecord} without adding it to the world database, for the armor to appear correctly on the body, make sure to use a template as described below.
-- 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.
-- @usage local armorTemplate = types.Armor.record('orcish_cuirass')
-- local armorTable = {name = "Better Orcish Cuirass",template = armorTemplate,baseArmor = armorTemplate.baseArmor + 10}
-- --This is the new record we want to create, with a record provided as a template.
-- local recordDraft = types.Armor.createRecordDraft(armorTable)--Need to convert the table into the record draft
-- local newRecord = world.createRecord(recordDraft)--This creates the actual record
-- world.createObject(newRecord):moveInto(playerActor)--Create an instance of this object, and move it into the player's inventory
--- @{#Book} functions
@ -926,7 +932,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 optional field `template` that accepts a @{#BookRecord} as a base.
-- @return #BookRecord A strongly typed Book record.
--- @{#Clothing} functions
@ -967,11 +973,17 @@
-- @return #ClothingRecord
---
-- Creates a @{#ClothingRecord} without adding it to the world database.
-- Creates a @{#ClothingRecord} without adding it to the world database, for the clothing to appear correctly on the body, make sure to use a template as described below.
-- 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.
-- @usage local clothingTemplate = types.Clothing.record('exquisite_robe_01')
-- local clothingTable = {name = "Better Exquisite Robe",template = clothingTemplate,enchantCapacity = clothingTemplate.enchantCapacity + 10}
-- --This is the new record we want to create, with a record provided as a template.
-- local recordDraft = types.Clothing.createRecordDraft(clothingTable)--Need to convert the table into the record draft
-- local newRecord = world.createRecord(recordDraft)--This creates the actual record
-- world.createObject(newRecord):moveInto(playerActor)--Create an instance of this object, and move it into the player's inventory
---
-- @type ClothingRecord
@ -1145,7 +1157,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 optional field `template` that accepts a @{#MiscellaneousRecord} as a base.
-- @return #MiscellaneousRecord A strongly typed Miscellaneous record.
---
@ -1190,7 +1202,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 optional field `template` that accepts a @{#PotionRecord} as a base.
-- @return #PotionRecord A strongly typed Potion record.
---
@ -1275,7 +1287,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 optional field `template` that accepts a @{#WeaponRecord} as a base.
-- @return #WeaponRecord A strongly typed Weapon record.
--- @{#Apparatus} functions
@ -1450,7 +1462,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 optional field `template` that accepts a @{#ActivatorRecord} as a base.
-- @return #ActivatorRecord A strongly typed Activator record.

Loading…
Cancel
Save