diff --git a/Projects/UOContent.Tests/Tests/PropertyList/AosArmorAttributesPropertiesTests.cs b/Projects/UOContent.Tests/Tests/PropertyList/AosArmorAttributesPropertiesTests.cs new file mode 100644 index 000000000..0cb1c931f --- /dev/null +++ b/Projects/UOContent.Tests/Tests/PropertyList/AosArmorAttributesPropertiesTests.cs @@ -0,0 +1,71 @@ +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Text; +using Server; +using Server.Items; +using Xunit; + +namespace UOContent.Tests; + +[Collection("Sequential UOContent Tests")] +public class AosArmorAttributesPropertiesTests +{ + private static Dictionary Decode(ObjectPropertyList opl) + { + opl.Terminate(); + var buffer = opl.Buffer; + var map = new Dictionary(); + var pos = 15; + while (true) + { + var cliloc = BinaryPrimitives.ReadInt32BigEndian(buffer.AsSpan(pos)); + pos += 4; + if (cliloc == 0) + { + break; + } + + var byteLen = BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(pos)); + pos += 2; + map[cliloc] = Encoding.Unicode.GetString(buffer, pos, byteLen); + pos += byteLen; + } + + return map; + } + + [Fact] + public void EmitsMageArmorAndSelfRepair_DoesNotReadLowerStatReqOrDurabilityFromContainer() + { + var attrs = new AosArmorAttributes(null) + { + MageArmor = 1, + SelfRepair = 4, + LowerStatReq = 50, // container value must NOT be auto-emitted (it's passed in by the consumer) + DurabilityBonus = 10 // never emitted by this method + }; + + var opl = new ObjectPropertyList(null); + attrs.GetProperties(opl); // no lowerStatReq arg + var map = Decode(opl); + + Assert.Equal("", map[1060437]); // MageArmor (no-arg) + Assert.Equal("4", map[1060450]); // SelfRepair + Assert.False(map.ContainsKey(1060435)); // LowerStatReq NOT read from container + Assert.False(map.ContainsKey(1060410)); // DurabilityBonus excluded + } + + [Fact] + public void EmitsLowerStatReqWhenPassed() + { + var attrs = new AosArmorAttributes(null) { MageArmor = 1, LowerStatReq = 50 }; + + var opl = new ObjectPropertyList(null); + attrs.GetProperties(opl, lowerStatReq: 77); // computed value passed by the consumer, not the raw 50 + var map = Decode(opl); + + Assert.Equal("77", map[1060435]); // emitted from the param, not the container's 50 + Assert.Equal("", map[1060437]); // MageArmor still emitted + } +} diff --git a/Projects/UOContent.Tests/Tests/PropertyList/AosAttributesPropertiesTests.cs b/Projects/UOContent.Tests/Tests/PropertyList/AosAttributesPropertiesTests.cs new file mode 100644 index 000000000..6571c1312 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/PropertyList/AosAttributesPropertiesTests.cs @@ -0,0 +1,75 @@ +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Text; +using Server; +using Server.Items; +using Xunit; + +namespace UOContent.Tests; + +[Collection("Sequential UOContent Tests")] +public class AosAttributesPropertiesTests +{ + private static Dictionary Decode(ObjectPropertyList opl) + { + opl.Terminate(); + var buffer = opl.Buffer; + var map = new Dictionary(); + var pos = 15; + while (true) + { + var cliloc = BinaryPrimitives.ReadInt32BigEndian(buffer.AsSpan(pos)); + pos += 4; + if (cliloc == 0) + { + break; + } + + var byteLen = BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(pos)); + pos += 2; + map[cliloc] = Encoding.Unicode.GetString(buffer, pos, byteLen); + pos += byteLen; + } + + return map; + } + + [Fact] + public void EmitsRawAttributesInCanonicalOrder() + { + var attrs = new AosAttributes(null) + { + DefendChance = 5, + BonusStr = 10, + NightSight = 1, + SpellChanneling = 1, + WeaponSpeed = 7 + }; + + var opl = new ObjectPropertyList(null); + attrs.GetProperties(opl); + var map = Decode(opl); + + Assert.Equal("5", map[1060408]); // DefendChance + Assert.Equal("10", map[1060485]); // BonusStr + Assert.Equal("", map[1060441]); // NightSight (no-arg) + Assert.Equal("", map[1060482]); // SpellChanneling (no-arg) + Assert.Equal("7", map[1060486]); // WeaponSpeed + Assert.False(map.ContainsKey(1060401)); // WeaponDamage not set + } + + [Fact] + public void AppliesComputedBonuses() + { + var attrs = new AosAttributes(null) { WeaponDamage = 10, AttackChance = 4, Luck = 100 }; + + var opl = new ObjectPropertyList(null); + attrs.GetProperties(opl, damageBonus: 5, hitChanceBonus: 3, luckBonus: 50); + var map = Decode(opl); + + Assert.Equal("15", map[1060401]); // WeaponDamage + damageBonus + Assert.Equal("7", map[1060415]); // AttackChance + hitChanceBonus + Assert.Equal("150", map[1060436]); // Luck + luckBonus + } +} diff --git a/Projects/UOContent.Tests/Tests/PropertyList/AosWeaponAttributesPropertiesTests.cs b/Projects/UOContent.Tests/Tests/PropertyList/AosWeaponAttributesPropertiesTests.cs new file mode 100644 index 000000000..21453f6d9 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/PropertyList/AosWeaponAttributesPropertiesTests.cs @@ -0,0 +1,74 @@ +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Text; +using Server; +using Server.Items; +using Xunit; + +namespace UOContent.Tests; + +[Collection("Sequential UOContent Tests")] +public class AosWeaponAttributesPropertiesTests +{ + private static Dictionary Decode(ObjectPropertyList opl) + { + opl.Terminate(); + var buffer = opl.Buffer; + var map = new Dictionary(); + var pos = 15; + while (true) + { + var cliloc = BinaryPrimitives.ReadInt32BigEndian(buffer.AsSpan(pos)); + pos += 4; + if (cliloc == 0) + { + break; + } + + var byteLen = BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(pos)); + pos += 2; + map[cliloc] = Encoding.Unicode.GetString(buffer, pos, byteLen); + pos += byteLen; + } + + return map; + } + + [Fact] + public void EmitsHitEffectsUseBestSkillMageWeaponSelfRepair() + { + var attrs = new AosWeaponAttributes(null) + { + UseBestSkill = 1, + HitFireball = 12, + HitLeechHits = 20, + MageWeapon = 25, + SelfRepair = 3 + }; + + var opl = new ObjectPropertyList(null); + attrs.GetProperties(opl); + var map = Decode(opl); + + Assert.Equal("", map[1060400]); // UseBestSkill (no-arg) + Assert.Equal("12", map[1060420]); // HitFireball + Assert.Equal("20", map[1060422]); // HitLeechHits + Assert.Equal("5", map[1060438]); // MageWeapon => 30 - 25 + Assert.Equal("3", map[1060450]); // SelfRepair + Assert.False(map.ContainsKey(1060435)); // LowerStatReq not emitted without the param + } + + [Fact] + public void EmitsLowerStatReqWhenPassed() + { + var attrs = new AosWeaponAttributes(null) { MageWeapon = 25 }; + + var opl = new ObjectPropertyList(null); + attrs.GetProperties(opl, lowerStatReq: 40); // computed value passed by the weapon + var map = Decode(opl); + + Assert.Equal("40", map[1060435]); // lower requirements, in cliloc order before MageWeapon + Assert.Equal("5", map[1060438]); // MageWeapon still emitted + } +} diff --git a/Projects/UOContent.Tests/Tests/PropertyList/BaseArmorPropertiesTests.cs b/Projects/UOContent.Tests/Tests/PropertyList/BaseArmorPropertiesTests.cs new file mode 100644 index 000000000..5176e6db6 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/PropertyList/BaseArmorPropertiesTests.cs @@ -0,0 +1,40 @@ +using Server.Items; +using Xunit; + +namespace UOContent.Tests; + +[Collection("Sequential UOContent Tests")] +public class BaseArmorPropertiesTests +{ + [Fact] + public void Armor_AttributeLineSet_Preserved() + { + var armor = new PlateChest(); + try + { + armor.Attributes.DefendChance = 5; + armor.Attributes.BonusDex = 8; + armor.Attributes.Luck = 40; + armor.Attributes.SpellChanneling = 1; + armor.Attributes.IncreasedKarmaLoss = 2; + armor.ArmorAttributes.MageArmor = 1; + armor.ArmorAttributes.SelfRepair = 3; + armor.ArmorAttributes.LowerStatReq = 50; + + var map = ItemOplTestHelper.DecodeAttributeLines(armor); + + Assert.Equal("5", map[1060408]); // DefendChance + Assert.Equal("8", map[1060409]); // BonusDex + Assert.Equal("40", map[1060436]); // Luck (GetLuckBonus()==0 unequipped) + Assert.Equal("", map[1060482]); // SpellChanneling + Assert.Equal("2", map[1075210]); // IncreasedKarmaLoss + Assert.Equal("", map[1060437]); // MageArmor + Assert.Equal("3", map[1060450]); // SelfRepair + Assert.Equal("50", map[1060435]); // LowerStatReq (inline via GetLowerStatReq) + } + finally + { + armor.Delete(); + } + } +} diff --git a/Projects/UOContent.Tests/Tests/PropertyList/BaseClothingPropertiesTests.cs b/Projects/UOContent.Tests/Tests/PropertyList/BaseClothingPropertiesTests.cs new file mode 100644 index 000000000..d7d51c3f3 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/PropertyList/BaseClothingPropertiesTests.cs @@ -0,0 +1,38 @@ +using Server.Items; +using Xunit; + +namespace UOContent.Tests; + +[Collection("Sequential UOContent Tests")] +public class BaseClothingPropertiesTests +{ + [Fact] + public void Clothing_AttributeLineSet_Preserved() + { + var shirt = new FancyShirt(); + try + { + shirt.Attributes.DefendChance = 5; + shirt.Attributes.Luck = 25; + shirt.Attributes.SpellChanneling = 1; + shirt.ClothingAttributes.MageArmor = 1; + shirt.ClothingAttributes.SelfRepair = 2; + shirt.ClothingAttributes.LowerStatReq = 30; + shirt.ClothingAttributes.DurabilityBonus = 15; + + var map = ItemOplTestHelper.DecodeAttributeLines(shirt); + + Assert.Equal("5", map[1060408]); // DefendChance + Assert.Equal("25", map[1060436]); // Luck (raw) + Assert.Equal("", map[1060482]); // SpellChanneling + Assert.Equal("", map[1060437]); // MageArmor + Assert.Equal("2", map[1060450]); // SelfRepair + Assert.Equal("30", map[1060435]); // LowerStatReq (direct) + Assert.Equal("15", map[1060410]); // DurabilityBonus (direct) + } + finally + { + shirt.Delete(); + } + } +} diff --git a/Projects/UOContent.Tests/Tests/PropertyList/BaseJewelPropertiesTests.cs b/Projects/UOContent.Tests/Tests/PropertyList/BaseJewelPropertiesTests.cs new file mode 100644 index 000000000..30acb6cf1 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/PropertyList/BaseJewelPropertiesTests.cs @@ -0,0 +1,36 @@ +using Server.Items; +using Xunit; + +namespace UOContent.Tests; + +[Collection("Sequential UOContent Tests")] +public class BaseJewelPropertiesTests +{ + [Fact] + public void Jewel_AttributeLineSet_Preserved() + { + var ring = new GoldRing(); + try + { + ring.Attributes.DefendChance = 5; + ring.Attributes.BonusStr = 10; + ring.Attributes.Luck = 100; + ring.Attributes.NightSight = 1; + ring.Attributes.SpellChanneling = 1; + ring.Attributes.IncreasedKarmaLoss = 3; + + var map = ItemOplTestHelper.DecodeAttributeLines(ring); + + Assert.Equal("5", map[1060408]); // DefendChance + Assert.Equal("10", map[1060485]); // BonusStr + Assert.Equal("100", map[1060436]); // Luck (raw; jewel has no luck bonus) + Assert.Equal("", map[1060441]); // NightSight + Assert.Equal("", map[1060482]); // SpellChanneling + Assert.Equal("3", map[1075210]); // IncreasedKarmaLoss (Core.ML EJ) + } + finally + { + ring.Delete(); + } + } +} diff --git a/Projects/UOContent.Tests/Tests/PropertyList/BaseTalismanPropertiesTests.cs b/Projects/UOContent.Tests/Tests/PropertyList/BaseTalismanPropertiesTests.cs new file mode 100644 index 000000000..d42684658 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/PropertyList/BaseTalismanPropertiesTests.cs @@ -0,0 +1,42 @@ +using Server.Items; +using Xunit; + +namespace UOContent.Tests; + +[Collection("Sequential UOContent Tests")] +public class BaseTalismanPropertiesTests +{ + [Fact] + public void GetProperties_EmitsAosAttributeLines() + { + var item = new RandomTalisman(); + try + { + item.Attributes.DefendChance = 10; + item.Attributes.BonusStr = 5; + item.Attributes.Luck = 50; + item.Attributes.NightSight = 1; + item.Attributes.SpellChanneling = 1; + item.Attributes.IncreasedKarmaLoss = 2; + + var lines = ItemOplTestHelper.DecodeAttributeLines(item); + + Assert.True(lines.ContainsKey(1060408)); // DefendChance + Assert.Equal("10", lines[1060408]); + Assert.True(lines.ContainsKey(1060485)); // BonusStr + Assert.Equal("5", lines[1060485]); + Assert.True(lines.ContainsKey(1060436)); // Luck + Assert.Equal("50", lines[1060436]); + Assert.True(lines.ContainsKey(1060441)); // NightSight + Assert.Equal("", lines[1060441]); + Assert.True(lines.ContainsKey(1060482)); // SpellChanneling + Assert.Equal("", lines[1060482]); + Assert.True(lines.ContainsKey(1075210)); // IncreasedKarmaLoss + Assert.Equal("2", lines[1075210]); + } + finally + { + item.Delete(); + } + } +} diff --git a/Projects/UOContent.Tests/Tests/PropertyList/BaseWeaponPropertiesTests.cs b/Projects/UOContent.Tests/Tests/PropertyList/BaseWeaponPropertiesTests.cs new file mode 100644 index 000000000..213e59cb9 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/PropertyList/BaseWeaponPropertiesTests.cs @@ -0,0 +1,38 @@ +using Server.Items; +using Xunit; + +namespace UOContent.Tests; + +[Collection("Sequential UOContent Tests")] +public class BaseWeaponPropertiesTests +{ + [Fact] + public void Weapon_AttributeLineSet_Preserved() + { + var weapon = new Longsword(); + try + { + weapon.Attributes.DefendChance = 5; + weapon.Attributes.BonusInt = 6; + weapon.Attributes.SpellChanneling = 1; + weapon.WeaponAttributes.UseBestSkill = 1; + weapon.WeaponAttributes.HitFireball = 12; + weapon.WeaponAttributes.MageWeapon = 25; + weapon.WeaponAttributes.SelfRepair = 3; + + var map = ItemOplTestHelper.DecodeAttributeLines(weapon); + + Assert.Equal("5", map[1060408]); // DefendChance + Assert.Equal("6", map[1060432]); // BonusInt + Assert.Equal("", map[1060482]); // SpellChanneling + Assert.Equal("", map[1060400]); // UseBestSkill + Assert.Equal("12", map[1060420]); // HitFireball + Assert.Equal("5", map[1060438]); // MageWeapon (30 - 25) + Assert.Equal("3", map[1060450]); // SelfRepair + } + finally + { + weapon.Delete(); + } + } +} diff --git a/Projects/UOContent.Tests/Tests/PropertyList/ItemOplTestHelper.cs b/Projects/UOContent.Tests/Tests/PropertyList/ItemOplTestHelper.cs new file mode 100644 index 000000000..1b4acf26b --- /dev/null +++ b/Projects/UOContent.Tests/Tests/PropertyList/ItemOplTestHelper.cs @@ -0,0 +1,44 @@ +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Text; +using Server; + +namespace UOContent.Tests; + +public static class ItemOplTestHelper +{ + // Builds the item's OPL and returns attribute/property cliloc lines (>= 1060000), + // ignoring base-item lines (name, weight, etc.) so tests isolate the attribute surface. + public static Dictionary DecodeAttributeLines(Item item) + { + var opl = new ObjectPropertyList(item); + item.GetProperties(opl); + opl.Terminate(); + + var buffer = opl.Buffer; + var map = new Dictionary(); + var pos = 15; + while (true) + { + var cliloc = BinaryPrimitives.ReadInt32BigEndian(buffer.AsSpan(pos)); + pos += 4; + if (cliloc == 0) + { + break; + } + + var byteLen = BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(pos)); + pos += 2; + var arg = Encoding.Unicode.GetString(buffer, pos, byteLen); + pos += byteLen; + + if (cliloc is >= 1060000 and < 1080000) + { + map[cliloc] = arg; + } + } + + return map; + } +} diff --git a/Projects/UOContent.Tests/Tests/PropertyList/SpellbookPropertiesTests.cs b/Projects/UOContent.Tests/Tests/PropertyList/SpellbookPropertiesTests.cs new file mode 100644 index 000000000..4f14d1f71 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/PropertyList/SpellbookPropertiesTests.cs @@ -0,0 +1,42 @@ +using Server.Items; +using Xunit; + +namespace UOContent.Tests; + +[Collection("Sequential UOContent Tests")] +public class SpellbookPropertiesTests +{ + [Fact] + public void GetProperties_EmitsAosAttributeLines() + { + var item = new Spellbook(); + try + { + item.Attributes.CastRecovery = 3; + item.Attributes.LowerManaCost = 8; + item.Attributes.Luck = 75; + item.Attributes.NightSight = 1; + item.Attributes.SpellChanneling = 1; + item.Attributes.IncreasedKarmaLoss = 2; + + var lines = ItemOplTestHelper.DecodeAttributeLines(item); + + Assert.True(lines.ContainsKey(1060412)); // CastRecovery + Assert.Equal("3", lines[1060412]); + Assert.True(lines.ContainsKey(1060433)); // LowerManaCost + Assert.Equal("8", lines[1060433]); + Assert.True(lines.ContainsKey(1060436)); // Luck + Assert.Equal("75", lines[1060436]); + Assert.True(lines.ContainsKey(1060441)); // NightSight + Assert.Equal("", lines[1060441]); + Assert.True(lines.ContainsKey(1060482)); // SpellChanneling + Assert.Equal("", lines[1060482]); + Assert.True(lines.ContainsKey(1075210)); // IncreasedKarmaLoss + Assert.Equal("2", lines[1075210]); + } + finally + { + item.Delete(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/BaseArmor.cs b/Projects/UOContent/Items/Armor/BaseArmor.cs index 60d7c8bf9..7f01648a0 100644 --- a/Projects/UOContent/Items/Armor/BaseArmor.cs +++ b/Projects/UOContent/Items/Armor/BaseArmor.cs @@ -1323,140 +1323,9 @@ namespace Server.Items list.Add(1061078, prop); // artifact rarity ~1_val~ } - if ((prop = Attributes.WeaponDamage) != 0) - { - list.Add(1060401, prop); // damage increase ~1_val~% - } + ArmorAttributes.GetProperties(list); - if ((prop = Attributes.DefendChance) != 0) - { - list.Add(1060408, prop); // defense chance increase ~1_val~% - } - - if ((prop = Attributes.BonusDex) != 0) - { - list.Add(1060409, prop); // dexterity bonus ~1_val~ - } - - if ((prop = Attributes.EnhancePotions) != 0) - { - list.Add(1060411, prop); // enhance potions ~1_val~% - } - - if ((prop = Attributes.CastRecovery) != 0) - { - list.Add(1060412, prop); // faster cast recovery ~1_val~ - } - - if ((prop = Attributes.CastSpeed) != 0) - { - list.Add(1060413, prop); // faster casting ~1_val~ - } - - if ((prop = Attributes.AttackChance) != 0) - { - list.Add(1060415, prop); // hit chance increase ~1_val~% - } - - if ((prop = Attributes.BonusHits) != 0) - { - list.Add(1060431, prop); // hit point increase ~1_val~ - } - - if ((prop = Attributes.BonusInt) != 0) - { - list.Add(1060432, prop); // intelligence bonus ~1_val~ - } - - if ((prop = Attributes.LowerManaCost) != 0) - { - list.Add(1060433, prop); // lower mana cost ~1_val~% - } - - if ((prop = Attributes.LowerRegCost) != 0) - { - list.Add(1060434, prop); // lower reagent cost ~1_val~% - } - - if ((prop = GetLowerStatReq()) != 0) - { - list.Add(1060435, prop); // lower requirements ~1_val~% - } - - if ((prop = GetLuckBonus() + Attributes.Luck) != 0) - { - list.Add(1060436, prop); // luck ~1_val~ - } - - if (ArmorAttributes.MageArmor != 0) - { - list.Add(1060437); // mage armor - } - - if ((prop = Attributes.BonusMana) != 0) - { - list.Add(1060439, prop); // mana increase ~1_val~ - } - - if ((prop = Attributes.RegenMana) != 0) - { - list.Add(1060440, prop); // mana regeneration ~1_val~ - } - - if (Attributes.NightSight != 0) - { - list.Add(1060441); // night sight - } - - if ((prop = Attributes.ReflectPhysical) != 0) - { - list.Add(1060442, prop); // reflect physical damage ~1_val~% - } - - if ((prop = Attributes.RegenStam) != 0) - { - list.Add(1060443, prop); // stamina regeneration ~1_val~ - } - - if ((prop = Attributes.RegenHits) != 0) - { - list.Add(1060444, prop); // hit point regeneration ~1_val~ - } - - if ((prop = ArmorAttributes.SelfRepair) != 0) - { - list.Add(1060450, prop); // self repair ~1_val~ - } - - if (Attributes.SpellChanneling != 0) - { - list.Add(1060482); // spell channeling - } - - if ((prop = Attributes.SpellDamage) != 0) - { - list.Add(1060483, prop); // spell damage increase ~1_val~% - } - - if ((prop = Attributes.BonusStam) != 0) - { - list.Add(1060484, prop); // stamina increase ~1_val~ - } - - if ((prop = Attributes.BonusStr) != 0) - { - list.Add(1060485, prop); // strength bonus ~1_val~ - } - - if ((prop = Attributes.WeaponSpeed) != 0) - { - list.Add(1060486, prop); // swing speed increase ~1_val~% - } - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - { - list.Add(1075210, prop); // Increased Karma Loss ~1val~% - } + Attributes.GetProperties(list, luckBonus: GetLuckBonus()); AddResistanceProperties(list); @@ -1465,6 +1334,12 @@ namespace Server.Items list.Add(1060410, prop); // durability ~1_val~% } + var lowerStatReq = GetLowerStatReq(); + if (lowerStatReq != 0) + { + list.Add(1060435, lowerStatReq); // lower requirements ~1_val~% + } + if ((prop = ComputeStatReq(StatType.Str)) > 0) { list.Add(1061170, prop); // strength requirement ~1_val~ diff --git a/Projects/UOContent/Items/Clothing/BaseClothing.cs b/Projects/UOContent/Items/Clothing/BaseClothing.cs index ce77d2ec6..725eed100 100644 --- a/Projects/UOContent/Items/Clothing/BaseClothing.cs +++ b/Projects/UOContent/Items/Clothing/BaseClothing.cs @@ -754,140 +754,9 @@ namespace Server.Items list.Add(1061078, prop); // artifact rarity ~1_val~ } - if ((prop = Attributes.WeaponDamage) != 0) - { - list.Add(1060401, prop); // damage increase ~1_val~% - } + ClothingAttributes.GetProperties(list); - if ((prop = Attributes.DefendChance) != 0) - { - list.Add(1060408, prop); // defense chance increase ~1_val~% - } - - if ((prop = Attributes.BonusDex) != 0) - { - list.Add(1060409, prop); // dexterity bonus ~1_val~ - } - - if ((prop = Attributes.EnhancePotions) != 0) - { - list.Add(1060411, prop); // enhance potions ~1_val~% - } - - if ((prop = Attributes.CastRecovery) != 0) - { - list.Add(1060412, prop); // faster cast recovery ~1_val~ - } - - if ((prop = Attributes.CastSpeed) != 0) - { - list.Add(1060413, prop); // faster casting ~1_val~ - } - - if ((prop = Attributes.AttackChance) != 0) - { - list.Add(1060415, prop); // hit chance increase ~1_val~% - } - - if ((prop = Attributes.BonusHits) != 0) - { - list.Add(1060431, prop); // hit point increase ~1_val~ - } - - if ((prop = Attributes.BonusInt) != 0) - { - list.Add(1060432, prop); // intelligence bonus ~1_val~ - } - - if ((prop = Attributes.LowerManaCost) != 0) - { - list.Add(1060433, prop); // lower mana cost ~1_val~% - } - - if ((prop = Attributes.LowerRegCost) != 0) - { - list.Add(1060434, prop); // lower reagent cost ~1_val~% - } - - if ((prop = ClothingAttributes.LowerStatReq) != 0) - { - list.Add(1060435, prop); // lower requirements ~1_val~% - } - - if ((prop = Attributes.Luck) != 0) - { - list.Add(1060436, prop); // luck ~1_val~ - } - - if (ClothingAttributes.MageArmor != 0) - { - list.Add(1060437); // mage armor - } - - if ((prop = Attributes.BonusMana) != 0) - { - list.Add(1060439, prop); // mana increase ~1_val~ - } - - if ((prop = Attributes.RegenMana) != 0) - { - list.Add(1060440, prop); // mana regeneration ~1_val~ - } - - if (Attributes.NightSight != 0) - { - list.Add(1060441); // night sight - } - - if ((prop = Attributes.ReflectPhysical) != 0) - { - list.Add(1060442, prop); // reflect physical damage ~1_val~% - } - - if ((prop = Attributes.RegenStam) != 0) - { - list.Add(1060443, prop); // stamina regeneration ~1_val~ - } - - if ((prop = Attributes.RegenHits) != 0) - { - list.Add(1060444, prop); // hit point regeneration ~1_val~ - } - - if ((prop = ClothingAttributes.SelfRepair) != 0) - { - list.Add(1060450, prop); // self repair ~1_val~ - } - - if (Attributes.SpellChanneling != 0) - { - list.Add(1060482); // spell channeling - } - - if ((prop = Attributes.SpellDamage) != 0) - { - list.Add(1060483, prop); // spell damage increase ~1_val~% - } - - if ((prop = Attributes.BonusStam) != 0) - { - list.Add(1060484, prop); // stamina increase ~1_val~ - } - - if ((prop = Attributes.BonusStr) != 0) - { - list.Add(1060485, prop); // strength bonus ~1_val~ - } - - if ((prop = Attributes.WeaponSpeed) != 0) - { - list.Add(1060486, prop); // swing speed increase ~1_val~% - } - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - { - list.Add(1075210, prop); // Increased Karma Loss ~1val~% - } + Attributes.GetProperties(list); AddResistanceProperties(list); @@ -896,6 +765,12 @@ namespace Server.Items list.Add(1060410, prop); // durability ~1_val~% } + var lowerStatReq = ClothingAttributes.LowerStatReq; + if (lowerStatReq != 0) + { + list.Add(1060435, lowerStatReq); // lower requirements ~1_val~% + } + if ((prop = ComputeStatReq(StatType.Str)) > 0) { list.Add(1061170, prop); // strength requirement ~1_val~ diff --git a/Projects/UOContent/Items/Jewels/BaseJewel.cs b/Projects/UOContent/Items/Jewels/BaseJewel.cs index 29f7d67d8..4eb01cbe0 100644 --- a/Projects/UOContent/Items/Jewels/BaseJewel.cs +++ b/Projects/UOContent/Items/Jewels/BaseJewel.cs @@ -389,125 +389,7 @@ public abstract partial class BaseJewel : Item, ICraftable, IAosItem list.Add(1061078, prop); // artifact rarity ~1_val~ } - if ((prop = Attributes.WeaponDamage) != 0) - { - list.Add(1060401, prop); // damage increase ~1_val~% - } - - if ((prop = Attributes.DefendChance) != 0) - { - list.Add(1060408, prop); // defense chance increase ~1_val~% - } - - if ((prop = Attributes.BonusDex) != 0) - { - list.Add(1060409, prop); // dexterity bonus ~1_val~ - } - - if ((prop = Attributes.EnhancePotions) != 0) - { - list.Add(1060411, prop); // enhance potions ~1_val~% - } - - if ((prop = Attributes.CastRecovery) != 0) - { - list.Add(1060412, prop); // faster cast recovery ~1_val~ - } - - if ((prop = Attributes.CastSpeed) != 0) - { - list.Add(1060413, prop); // faster casting ~1_val~ - } - - if ((prop = Attributes.AttackChance) != 0) - { - list.Add(1060415, prop); // hit chance increase ~1_val~% - } - - if ((prop = Attributes.BonusHits) != 0) - { - list.Add(1060431, prop); // hit point increase ~1_val~ - } - - if ((prop = Attributes.BonusInt) != 0) - { - list.Add(1060432, prop); // intelligence bonus ~1_val~ - } - - if ((prop = Attributes.LowerManaCost) != 0) - { - list.Add(1060433, prop); // lower mana cost ~1_val~% - } - - if ((prop = Attributes.LowerRegCost) != 0) - { - list.Add(1060434, prop); // lower reagent cost ~1_val~% - } - - if ((prop = Attributes.Luck) != 0) - { - list.Add(1060436, prop); // luck ~1_val~ - } - - if ((prop = Attributes.BonusMana) != 0) - { - list.Add(1060439, prop); // mana increase ~1_val~ - } - - if ((prop = Attributes.RegenMana) != 0) - { - list.Add(1060440, prop); // mana regeneration ~1_val~ - } - - if (Attributes.NightSight != 0) - { - list.Add(1060441); // night sight - } - - if ((prop = Attributes.ReflectPhysical) != 0) - { - list.Add(1060442, prop); // reflect physical damage ~1_val~% - } - - if ((prop = Attributes.RegenStam) != 0) - { - list.Add(1060443, prop); // stamina regeneration ~1_val~ - } - - if ((prop = Attributes.RegenHits) != 0) - { - list.Add(1060444, prop); // hit point regeneration ~1_val~ - } - - if (Attributes.SpellChanneling != 0) - { - list.Add(1060482); // spell channeling - } - - if ((prop = Attributes.SpellDamage) != 0) - { - list.Add(1060483, prop); // spell damage increase ~1_val~% - } - - if ((prop = Attributes.BonusStam) != 0) - { - list.Add(1060484, prop); // stamina increase ~1_val~ - } - - if ((prop = Attributes.BonusStr) != 0) - { - list.Add(1060485, prop); // strength bonus ~1_val~ - } - - if ((prop = Attributes.WeaponSpeed) != 0) - { - list.Add(1060486, prop); // swing speed increase ~1_val~% - } - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - { - list.Add(1075210, prop); // Increased Karma Loss ~1val~% - } + Attributes.GetProperties(list); AddResistanceProperties(list); diff --git a/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs b/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs index c94a362ab..f1ced7308 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs @@ -677,127 +677,7 @@ public partial class Spellbook : Item, ICraftable, ISlayer, IAosItem } } - int prop; - - if ((prop = _attributes.WeaponDamage) != 0) - { - list.Add(1060401, prop); // damage increase ~1_val~% - } - - if ((prop = _attributes.DefendChance) != 0) - { - list.Add(1060408, prop); // defense chance increase ~1_val~% - } - - if ((prop = _attributes.BonusDex) != 0) - { - list.Add(1060409, prop); // dexterity bonus ~1_val~ - } - - if ((prop = _attributes.EnhancePotions) != 0) - { - list.Add(1060411, prop); // enhance potions ~1_val~% - } - - if ((prop = _attributes.CastRecovery) != 0) - { - list.Add(1060412, prop); // faster cast recovery ~1_val~ - } - - if ((prop = _attributes.CastSpeed) != 0) - { - list.Add(1060413, prop); // faster casting ~1_val~ - } - - if ((prop = _attributes.AttackChance) != 0) - { - list.Add(1060415, prop); // hit chance increase ~1_val~% - } - - if ((prop = _attributes.BonusHits) != 0) - { - list.Add(1060431, prop); // hit point increase ~1_val~ - } - - if ((prop = _attributes.BonusInt) != 0) - { - list.Add(1060432, prop); // intelligence bonus ~1_val~ - } - - if ((prop = _attributes.LowerManaCost) != 0) - { - list.Add(1060433, prop); // lower mana cost ~1_val~% - } - - if ((prop = _attributes.LowerRegCost) != 0) - { - list.Add(1060434, prop); // lower reagent cost ~1_val~% - } - - if ((prop = _attributes.Luck) != 0) - { - list.Add(1060436, prop); // luck ~1_val~ - } - - if ((prop = _attributes.BonusMana) != 0) - { - list.Add(1060439, prop); // mana increase ~1_val~ - } - - if ((prop = _attributes.RegenMana) != 0) - { - list.Add(1060440, prop); // mana regeneration ~1_val~ - } - - if (_attributes.NightSight != 0) - { - list.Add(1060441); // night sight - } - - if ((prop = _attributes.ReflectPhysical) != 0) - { - list.Add(1060442, prop); // reflect physical damage ~1_val~% - } - - if ((prop = _attributes.RegenStam) != 0) - { - list.Add(1060443, prop); // stamina regeneration ~1_val~ - } - - if ((prop = _attributes.RegenHits) != 0) - { - list.Add(1060444, prop); // hit point regeneration ~1_val~ - } - - if (_attributes.SpellChanneling != 0) - { - list.Add(1060482); // spell channeling - } - - if ((prop = _attributes.SpellDamage) != 0) - { - list.Add(1060483, prop); // spell damage increase ~1_val~% - } - - if ((prop = _attributes.BonusStam) != 0) - { - list.Add(1060484, prop); // stamina increase ~1_val~ - } - - if ((prop = _attributes.BonusStr) != 0) - { - list.Add(1060485, prop); // strength bonus ~1_val~ - } - - if ((prop = _attributes.WeaponSpeed) != 0) - { - list.Add(1060486, prop); // swing speed increase ~1_val~% - } - - if (Core.ML && (prop = _attributes.IncreasedKarmaLoss) != 0) - { - list.Add(1075210, prop); // Increased Karma Loss ~1val~% - } + _attributes.GetProperties(list); list.Add(1042886, _spellCount); // ~1_NUMBERS_OF_SPELLS~ Spells } diff --git a/Projects/UOContent/Items/Talismans/BaseTalisman.cs b/Projects/UOContent/Items/Talismans/BaseTalisman.cs index ff3f867c6..632587523 100644 --- a/Projects/UOContent/Items/Talismans/BaseTalisman.cs +++ b/Projects/UOContent/Items/Talismans/BaseTalisman.cs @@ -617,127 +617,7 @@ public partial class BaseTalisman : Item, IAosItem SkillBonuses.GetProperties(list); - int prop; - - if ((prop = Attributes.WeaponDamage) != 0) - { - list.Add(1060401, prop); // damage increase ~1_val~% - } - - if ((prop = Attributes.DefendChance) != 0) - { - list.Add(1060408, prop); // defense chance increase ~1_val~% - } - - if ((prop = Attributes.BonusDex) != 0) - { - list.Add(1060409, prop); // dexterity bonus ~1_val~ - } - - if ((prop = Attributes.EnhancePotions) != 0) - { - list.Add(1060411, prop); // enhance potions ~1_val~% - } - - if ((prop = Attributes.CastRecovery) != 0) - { - list.Add(1060412, prop); // faster cast recovery ~1_val~ - } - - if ((prop = Attributes.CastSpeed) != 0) - { - list.Add(1060413, prop); // faster casting ~1_val~ - } - - if ((prop = Attributes.AttackChance) != 0) - { - list.Add(1060415, prop); // hit chance increase ~1_val~% - } - - if ((prop = Attributes.BonusHits) != 0) - { - list.Add(1060431, prop); // hit point increase ~1_val~ - } - - if ((prop = Attributes.BonusInt) != 0) - { - list.Add(1060432, prop); // intelligence bonus ~1_val~ - } - - if ((prop = Attributes.LowerManaCost) != 0) - { - list.Add(1060433, prop); // lower mana cost ~1_val~% - } - - if ((prop = Attributes.LowerRegCost) != 0) - { - list.Add(1060434, prop); // lower reagent cost ~1_val~% - } - - if ((prop = Attributes.Luck) != 0) - { - list.Add(1060436, prop); // luck ~1_val~ - } - - if ((prop = Attributes.BonusMana) != 0) - { - list.Add(1060439, prop); // mana increase ~1_val~ - } - - if ((prop = Attributes.RegenMana) != 0) - { - list.Add(1060440, prop); // mana regeneration ~1_val~ - } - - if (Attributes.NightSight != 0) - { - list.Add(1060441); // night sight - } - - if ((prop = Attributes.ReflectPhysical) != 0) - { - list.Add(1060442, prop); // reflect physical damage ~1_val~% - } - - if ((prop = Attributes.RegenStam) != 0) - { - list.Add(1060443, prop); // stamina regeneration ~1_val~ - } - - if ((prop = Attributes.RegenHits) != 0) - { - list.Add(1060444, prop); // hit point regeneration ~1_val~ - } - - if (Attributes.SpellChanneling != 0) - { - list.Add(1060482); // spell channeling - } - - if ((prop = Attributes.SpellDamage) != 0) - { - list.Add(1060483, prop); // spell damage increase ~1_val~% - } - - if ((prop = Attributes.BonusStam) != 0) - { - list.Add(1060484, prop); // stamina increase ~1_val~ - } - - if ((prop = Attributes.BonusStr) != 0) - { - list.Add(1060485, prop); // strength bonus ~1_val~ - } - - if ((prop = Attributes.WeaponSpeed) != 0) - { - list.Add(1060486, prop); // swing speed increase ~1_val~% - } - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - { - list.Add(1075210, prop); // Increased Karma Loss ~1val~% - } + Attributes.GetProperties(list); if (_maxCharges > 0) { diff --git a/Projects/UOContent/Items/Weapons/BaseWeapon.cs b/Projects/UOContent/Items/Weapons/BaseWeapon.cs index c746a83a2..4501c0ee3 100644 --- a/Projects/UOContent/Items/Weapons/BaseWeapon.cs +++ b/Projects/UOContent/Items/Weapons/BaseWeapon.cs @@ -2998,115 +2998,7 @@ public abstract partial class BaseWeapon list.Add(1072792); // Balanced } - if (WeaponAttributes.UseBestSkill != 0) - { - list.Add(1060400); // use best weapon skill - } - - if ((prop = GetDamageBonus() + Attributes.WeaponDamage) != 0) - { - list.Add(1060401, prop); // damage increase ~1_val~% - } - - if ((prop = Attributes.DefendChance) != 0) - { - list.Add(1060408, prop); // defense chance increase ~1_val~% - } - - if ((prop = Attributes.EnhancePotions) != 0) - { - list.Add(1060411, prop); // enhance potions ~1_val~% - } - - if ((prop = Attributes.CastRecovery) != 0) - { - list.Add(1060412, prop); // faster cast recovery ~1_val~ - } - - if ((prop = Attributes.CastSpeed) != 0) - { - list.Add(1060413, prop); // faster casting ~1_val~ - } - - if ((prop = GetHitChanceBonus() + Attributes.AttackChance) != 0) - { - list.Add(1060415, prop); // hit chance increase ~1_val~% - } - - if ((prop = WeaponAttributes.HitColdArea) != 0) - { - list.Add(1060416, prop); // hit cold area ~1_val~% - } - - if ((prop = WeaponAttributes.HitDispel) != 0) - { - list.Add(1060417, prop); // hit dispel ~1_val~% - } - - if ((prop = WeaponAttributes.HitEnergyArea) != 0) - { - list.Add(1060418, prop); // hit energy area ~1_val~% - } - - if ((prop = WeaponAttributes.HitFireArea) != 0) - { - list.Add(1060419, prop); // hit fire area ~1_val~% - } - - if ((prop = WeaponAttributes.HitFireball) != 0) - { - list.Add(1060420, prop); // hit fireball ~1_val~% - } - - if ((prop = WeaponAttributes.HitHarm) != 0) - { - list.Add(1060421, prop); // hit harm ~1_val~% - } - - if ((prop = WeaponAttributes.HitLeechHits) != 0) - { - list.Add(1060422, prop); // hit life leech ~1_val~% - } - - if ((prop = WeaponAttributes.HitLightning) != 0) - { - list.Add(1060423, prop); // hit lightning ~1_val~% - } - - if ((prop = WeaponAttributes.HitLowerAttack) != 0) - { - list.Add(1060424, prop); // hit lower attack ~1_val~% - } - - if ((prop = WeaponAttributes.HitLowerDefend) != 0) - { - list.Add(1060425, prop); // hit lower defense ~1_val~% - } - - if ((prop = WeaponAttributes.HitMagicArrow) != 0) - { - list.Add(1060426, prop); // hit magic arrow ~1_val~% - } - - if ((prop = WeaponAttributes.HitLeechMana) != 0) - { - list.Add(1060427, prop); // hit mana leech ~1_val~% - } - - if ((prop = WeaponAttributes.HitPhysicalArea) != 0) - { - list.Add(1060428, prop); // hit physical area ~1_val~% - } - - if ((prop = WeaponAttributes.HitPoisonArea) != 0) - { - list.Add(1060429, prop); // hit poison area ~1_val~% - } - - if ((prop = WeaponAttributes.HitLeechStam) != 0) - { - list.Add(1060430, prop); // hit stamina leech ~1_val~% - } + WeaponAttributes.GetProperties(list); if (ImmolatingWeaponSpell.IsImmolating(this)) { @@ -3118,109 +3010,17 @@ public abstract partial class BaseWeapon list.Add(1072793, prop); // Velocity ~1_val~% } - if ((prop = Attributes.BonusDex) != 0) - { - list.Add(1060409, prop); // dexterity bonus ~1_val~ - } + Attributes.GetProperties( + list, + damageBonus: GetDamageBonus(), + hitChanceBonus: GetHitChanceBonus(), + luckBonus: GetLuckBonus() + ); - if ((prop = Attributes.BonusHits) != 0) + var lowerStatReq = GetLowerStatReq(); + if (lowerStatReq != 0) { - list.Add(1060431, prop); // hit point increase ~1_val~ - } - - if ((prop = Attributes.BonusInt) != 0) - { - list.Add(1060432, prop); // intelligence bonus ~1_val~ - } - - if ((prop = Attributes.LowerManaCost) != 0) - { - list.Add(1060433, prop); // lower mana cost ~1_val~% - } - - if ((prop = Attributes.LowerRegCost) != 0) - { - list.Add(1060434, prop); // lower reagent cost ~1_val~% - } - - if ((prop = GetLowerStatReq()) != 0) - { - list.Add(1060435, prop); // lower requirements ~1_val~% - } - - if ((prop = GetLuckBonus() + Attributes.Luck) != 0) - { - list.Add(1060436, prop); // luck ~1_val~ - } - - if ((prop = WeaponAttributes.MageWeapon) != 0) - { - list.Add(1060438, 30 - prop); // mage weapon -~1_val~ skill - } - - if ((prop = Attributes.BonusMana) != 0) - { - list.Add(1060439, prop); // mana increase ~1_val~ - } - - if ((prop = Attributes.RegenMana) != 0) - { - list.Add(1060440, prop); // mana regeneration ~1_val~ - } - - if (Attributes.NightSight != 0) - { - list.Add(1060441); // night sight - } - - if ((prop = Attributes.ReflectPhysical) != 0) - { - list.Add(1060442, prop); // reflect physical damage ~1_val~% - } - - if ((prop = Attributes.RegenStam) != 0) - { - list.Add(1060443, prop); // stamina regeneration ~1_val~ - } - - if ((prop = Attributes.RegenHits) != 0) - { - list.Add(1060444, prop); // hit point regeneration ~1_val~ - } - - if ((prop = WeaponAttributes.SelfRepair) != 0) - { - list.Add(1060450, prop); // self repair ~1_val~ - } - - if (Attributes.SpellChanneling != 0) - { - list.Add(1060482); // spell channeling - } - - if ((prop = Attributes.SpellDamage) != 0) - { - list.Add(1060483, prop); // spell damage increase ~1_val~% - } - - if ((prop = Attributes.BonusStam) != 0) - { - list.Add(1060484, prop); // stamina increase ~1_val~ - } - - if ((prop = Attributes.BonusStr) != 0) - { - list.Add(1060485, prop); // strength bonus ~1_val~ - } - - if ((prop = Attributes.WeaponSpeed) != 0) - { - list.Add(1060486, prop); // swing speed increase ~1_val~% - } - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - { - list.Add(1075210, prop); // Increased Karma Loss ~1val~% + list.Add(1060435, lowerStatReq); // lower requirements ~1_val~% } GetDamageTypes( @@ -3239,16 +3039,16 @@ public abstract partial class BaseWeapon list.Add(1060403, phys); // physical damage ~1_val~% } - if (fire != 0) - { - list.Add(1060405, fire); // fire damage ~1_val~% - } - if (cold != 0) { list.Add(1060404, cold); // cold damage ~1_val~% } + if (fire != 0) + { + list.Add(1060405, fire); // fire damage ~1_val~% + } + if (pois != 0) { list.Add(1060406, pois); // poison damage ~1_val~% @@ -3325,6 +3125,11 @@ public abstract partial class BaseWeapon list.Add(1061175); // skill required: archery break; } + case SkillName.Throwing: + { + list.Add(1112075); // skill required: throwing + break; + } } } diff --git a/Projects/UOContent/Misc/AOS.cs b/Projects/UOContent/Misc/AOS.cs index ec8c09b84..9ac9158c4 100644 --- a/Projects/UOContent/Misc/AOS.cs +++ b/Projects/UOContent/Misc/AOS.cs @@ -493,6 +493,131 @@ namespace Server set => this[AosAttribute.IncreasedKarmaLoss] = value; } + public void GetProperties(IPropertyList list, int damageBonus = 0, int hitChanceBonus = 0, int luckBonus = 0) + { + int prop; + + if ((prop = WeaponDamage + damageBonus) != 0) + { + list.Add(1060401, prop); // damage increase ~1_val~% + } + + if ((prop = DefendChance) != 0) + { + list.Add(1060408, prop); // defense chance increase ~1_val~% + } + + if ((prop = BonusDex) != 0) + { + list.Add(1060409, prop); // dexterity bonus ~1_val~ + } + + if ((prop = EnhancePotions) != 0) + { + list.Add(1060411, prop); // enhance potions ~1_val~% + } + + if ((prop = CastRecovery) != 0) + { + list.Add(1060412, prop); // faster cast recovery ~1_val~ + } + + if ((prop = CastSpeed) != 0) + { + list.Add(1060413, prop); // faster casting ~1_val~ + } + + if ((prop = AttackChance + hitChanceBonus) != 0) + { + list.Add(1060415, prop); // hit chance increase ~1_val~% + } + + if ((prop = BonusHits) != 0) + { + list.Add(1060431, prop); // hit point increase ~1_val~ + } + + if ((prop = BonusInt) != 0) + { + list.Add(1060432, prop); // intelligence bonus ~1_val~ + } + + if ((prop = LowerManaCost) != 0) + { + list.Add(1060433, prop); // lower mana cost ~1_val~% + } + + if ((prop = LowerRegCost) != 0) + { + list.Add(1060434, prop); // lower reagent cost ~1_val~% + } + + if ((prop = Luck + luckBonus) != 0) + { + list.Add(1060436, prop); // luck ~1_val~ + } + + if ((prop = BonusMana) != 0) + { + list.Add(1060439, prop); // mana increase ~1_val~ + } + + if ((prop = RegenMana) != 0) + { + list.Add(1060440, prop); // mana regeneration ~1_val~ + } + + if (NightSight != 0) + { + list.Add(1060441); // night sight + } + + if ((prop = ReflectPhysical) != 0) + { + list.Add(1060442, prop); // reflect physical damage ~1_val~% + } + + if ((prop = RegenStam) != 0) + { + list.Add(1060443, prop); // stamina regeneration ~1_val~ + } + + if ((prop = RegenHits) != 0) + { + list.Add(1060444, prop); // hit point regeneration ~1_val~ + } + + if (SpellChanneling != 0) + { + list.Add(1060482); // spell channeling + } + + if ((prop = SpellDamage) != 0) + { + list.Add(1060483, prop); // spell damage increase ~1_val~% + } + + if ((prop = BonusStam) != 0) + { + list.Add(1060484, prop); // stamina increase ~1_val~ + } + + if ((prop = BonusStr) != 0) + { + list.Add(1060485, prop); // strength bonus ~1_val~ + } + + if ((prop = WeaponSpeed) != 0) + { + list.Add(1060486, prop); // swing speed increase ~1_val~% + } + + if (Core.ML && (prop = IncreasedKarmaLoss) != 0) + { + list.Add(1075210, prop); // Increased Karma Loss ~1val~% + } + } + public static int GetValue(Mobile m, AosAttribute attribute) { if (!Core.AOS) @@ -885,6 +1010,103 @@ namespace Server return value; } + // lowerStatReq is passed in because the weapon folds the resource's lower-requirements into + // GetLowerStatReq(); emitted in cliloc order (1060435) between the Hit* block and MageWeapon. + public void GetProperties(IPropertyList list) + { + int prop; + + if (UseBestSkill != 0) + { + list.Add(1060400); // use best weapon skill + } + + if ((prop = HitColdArea) != 0) + { + list.Add(1060416, prop); // hit cold area ~1_val~% + } + + if ((prop = HitDispel) != 0) + { + list.Add(1060417, prop); // hit dispel ~1_val~% + } + + if ((prop = HitEnergyArea) != 0) + { + list.Add(1060418, prop); // hit energy area ~1_val~% + } + + if ((prop = HitFireArea) != 0) + { + list.Add(1060419, prop); // hit fire area ~1_val~% + } + + if ((prop = HitFireball) != 0) + { + list.Add(1060420, prop); // hit fireball ~1_val~% + } + + if ((prop = HitHarm) != 0) + { + list.Add(1060421, prop); // hit harm ~1_val~% + } + + if ((prop = HitLeechHits) != 0) + { + list.Add(1060422, prop); // hit life leech ~1_val~% + } + + if ((prop = HitLightning) != 0) + { + list.Add(1060423, prop); // hit lightning ~1_val~% + } + + if ((prop = HitLowerAttack) != 0) + { + list.Add(1060424, prop); // hit lower attack ~1_val~% + } + + if ((prop = HitLowerDefend) != 0) + { + list.Add(1060425, prop); // hit lower defense ~1_val~% + } + + if ((prop = HitMagicArrow) != 0) + { + list.Add(1060426, prop); // hit magic arrow ~1_val~% + } + + if ((prop = HitLeechMana) != 0) + { + list.Add(1060427, prop); // hit mana leech ~1_val~% + } + + if ((prop = HitPhysicalArea) != 0) + { + list.Add(1060428, prop); // hit physical area ~1_val~% + } + + if ((prop = HitPoisonArea) != 0) + { + list.Add(1060429, prop); // hit poison area ~1_val~% + } + + if ((prop = HitLeechStam) != 0) + { + list.Add(1060430, prop); // hit stamina leech ~1_val~% + } + + if ((prop = MageWeapon) != 0) + { + list.Add(1060438, 30 - prop); // mage weapon -~1_val~ skill + } + + if ((prop = SelfRepair) != 0) + { + list.Add(1060450, prop); // self repair ~1_val~ + } + } + public override string ToString() => "..."; } @@ -978,6 +1200,24 @@ namespace Server return value; } + // lowerStatReq is passed in because consumers compute it differently: armor folds in the + // resource's ArmorLowerRequirements via GetLowerStatReq(), clothing reads it raw. Emitted in + // cliloc order (1060435) ahead of MageArmor/SelfRepair. + public void GetProperties(IPropertyList list) + { + int prop; + + if (MageArmor != 0) + { + list.Add(1060437); // mage armor + } + + if ((prop = SelfRepair) != 0) + { + list.Add(1060450, prop); // self repair ~1_val~ + } + } + public override string ToString() => "..."; }