using System; using System.Collections.Generic; using Server.Engines.Craft; using Server.Ethics; using Server.Factions; using Server.Network; namespace Server.Items { public enum ClothingQuality { Low, Regular, Exceptional } public interface IArcaneEquip { bool IsArcane{ get; } int CurArcaneCharges{ get; set; } int MaxArcaneCharges{ get; set; } } public abstract class BaseClothing : Item, IDyable, IScissorable, IFactionItem, ICraftable, IWearableDurability { private Mobile m_Crafter; private int m_HitPoints; private int m_MaxHitPoints; private ClothingQuality m_Quality; protected CraftResource m_Resource; private int m_StrReq = -1; public BaseClothing(int itemID, Layer layer, int hue = 0) : base(itemID) { Layer = layer; Hue = hue; m_Resource = DefaultResource; m_Quality = ClothingQuality.Regular; m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); Attributes = new AosAttributes(this); ClothingAttributes = new AosArmorAttributes(this); SkillBonuses = new AosSkillBonuses(this); Resistances = new AosElementAttributes(this); } public BaseClothing(Serial serial) : base(serial) { } [CommandProperty(AccessLevel.GameMaster)] public Mobile Crafter { get => m_Crafter; set { m_Crafter = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public int StrRequirement { get => m_StrReq == -1 ? Core.AOS ? AosStrReq : OldStrReq : m_StrReq; set { m_StrReq = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public ClothingQuality Quality { get => m_Quality; set { m_Quality = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public bool PlayerConstructed{ get; set; } public virtual CraftResource DefaultResource => CraftResource.None; [CommandProperty(AccessLevel.GameMaster)] public CraftResource Resource { get => m_Resource; set { m_Resource = value; Hue = CraftResources.GetHue(m_Resource); InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public AosAttributes Attributes{ get; private set; } [CommandProperty(AccessLevel.GameMaster)] public AosArmorAttributes ClothingAttributes{ get; private set; } [CommandProperty(AccessLevel.GameMaster)] public AosSkillBonuses SkillBonuses{ get; private set; } [CommandProperty(AccessLevel.GameMaster)] public AosElementAttributes Resistances{ get; private set; } public virtual int BasePhysicalResistance => 0; public virtual int BaseFireResistance => 0; public virtual int BaseColdResistance => 0; public virtual int BasePoisonResistance => 0; public virtual int BaseEnergyResistance => 0; public override int PhysicalResistance => BasePhysicalResistance + Resistances.Physical; public override int FireResistance => BaseFireResistance + Resistances.Fire; public override int ColdResistance => BaseColdResistance + Resistances.Cold; public override int PoisonResistance => BasePoisonResistance + Resistances.Poison; public override int EnergyResistance => BaseEnergyResistance + Resistances.Energy; public virtual int ArtifactRarity => 0; public virtual int BaseStrBonus => 0; public virtual int BaseDexBonus => 0; public virtual int BaseIntBonus => 0; public virtual Race RequiredRace => null; public virtual int AosStrReq => 10; public virtual int OldStrReq => 0; public virtual bool AllowMaleWearer => true; public virtual bool AllowFemaleWearer => true; public virtual bool CanBeBlessed => true; #region ICraftable Members public virtual int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CraftItem craftItem, int resHue) { Quality = (ClothingQuality)quality; if (makersMark) Crafter = from; if (DefaultResource != CraftResource.None) { Type resourceType = typeRes; if (resourceType == null) resourceType = craftItem.Resources.GetAt(0).ItemType; Resource = CraftResources.GetFromType(resourceType); } else { Hue = resHue; } PlayerConstructed = true; CraftContext context = craftSystem.GetContext(from); if (context?.DoNotColor == true) Hue = 0; return quality; } #endregion public virtual bool Dye(Mobile from, DyeTub sender) { if (Deleted) return false; if (RootParent is Mobile && from != RootParent) return false; Hue = sender.DyedHue; return true; } public virtual bool Scissor(Mobile from, Scissors scissors) { if (!IsChildOf(from.Backpack)) { from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack. return false; } if (Ethic.IsImbued(this)) { from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. return false; } CraftSystem system = DefTailoring.CraftSystem; CraftItem item = system.CraftItems.SearchFor(GetType()); if (item?.Resources.Count == 1 && item.Resources.GetAt(0).Amount >= 2) try { CraftResourceInfo info = CraftResources.GetInfo(m_Resource); Type resourceType = info.ResourceTypes?[0] ?? item.Resources.GetAt(0).ItemType; Item res = (Item)Activator.CreateInstance(resourceType); ScissorHelper(from, res, PlayerConstructed ? item.Resources.GetAt(0).Amount / 2 : 1); res.LootType = LootType.Regular; return true; } catch { // ignored } from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. return false; } public virtual bool CanFortify => true; [CommandProperty(AccessLevel.GameMaster)] public int MaxHitPoints { get => m_MaxHitPoints; set { m_MaxHitPoints = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public int HitPoints { get => m_HitPoints; set { if (value != m_HitPoints && MaxHitPoints > 0) { m_HitPoints = value; if (m_HitPoints < 0) Delete(); else if (m_HitPoints > MaxHitPoints) m_HitPoints = MaxHitPoints; InvalidateProperties(); } } } public virtual int InitMinHits => 0; public virtual int InitMaxHits => 0; public virtual int OnHit(BaseWeapon weapon, int damageTaken) { int Absorbed = Utility.RandomMinMax(1, 4); damageTaken -= Absorbed; if (damageTaken < 0) damageTaken = 0; if (25 > Utility.Random(100)) // 25% chance to lower durability { if (Core.AOS && ClothingAttributes.SelfRepair > Utility.Random(10)) { HitPoints += 2; } else { int wear; if (weapon.Type == WeaponType.Bashing) wear = Absorbed / 2; else wear = Utility.Random(2); if (wear > 0 && m_MaxHitPoints > 0) { if (m_HitPoints >= wear) { HitPoints -= wear; wear = 0; } else { wear -= HitPoints; HitPoints = 0; } if (wear > 0) { if (m_MaxHitPoints > wear) { MaxHitPoints -= wear; (Parent as Mobile)?.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061121); // Your equipment is severely damaged. } else { Delete(); } } } } } return damageTaken; } public void UnscaleDurability() { int scale = 100 + ClothingAttributes.DurabilityBonus; m_HitPoints = (m_HitPoints * 100 + (scale - 1)) / scale; m_MaxHitPoints = (m_MaxHitPoints * 100 + (scale - 1)) / scale; InvalidateProperties(); } public void ScaleDurability() { int scale = 100 + ClothingAttributes.DurabilityBonus; m_HitPoints = (m_HitPoints * scale + 99) / 100; m_MaxHitPoints = (m_MaxHitPoints * scale + 99) / 100; InvalidateProperties(); } public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) { if (!Ethic.CheckTrade(from, to, newOwner, this)) return false; return base.AllowSecureTrade(from, to, newOwner, accepted); } public override bool CanEquip(Mobile from) { if (!Ethic.CheckEquip(from, this)) return false; if (from.AccessLevel < AccessLevel.GameMaster) { if (RequiredRace != null && from.Race != RequiredRace) { if (RequiredRace == Race.Elf) from.SendLocalizedMessage(1072203); // Only Elves may use this. else from.SendMessage("Only {0} may use this.", RequiredRace.PluralName); return false; } if (!AllowMaleWearer && !from.Female) { if (AllowFemaleWearer) from.SendLocalizedMessage(1010388); // Only females can wear this. else from.SendMessage("You may not wear this."); return false; } if (!AllowFemaleWearer && from.Female) { if (AllowMaleWearer) from.SendLocalizedMessage(1063343); // Only males can wear this. else from.SendMessage("You may not wear this."); return false; } int strBonus = ComputeStatBonus(StatType.Str); int strReq = ComputeStatReq(StatType.Str); if (from.Str < strReq || from.Str + strBonus < 1) { from.SendLocalizedMessage(500213); // You are not strong enough to equip that. return false; } } return base.CanEquip(from); } public int ComputeStatReq(StatType type) { int v; //if ( type == StatType.Str ) v = StrRequirement; return AOS.Scale(v, 100 - GetLowerStatReq()); } public int ComputeStatBonus(StatType type) { if (type == StatType.Str) return BaseStrBonus + Attributes.BonusStr; if (type == StatType.Dex) return BaseDexBonus + Attributes.BonusDex; return BaseIntBonus + Attributes.BonusInt; } public virtual void AddStatBonuses(Mobile parent) { if (parent == null) return; int strBonus = ComputeStatBonus(StatType.Str); int dexBonus = ComputeStatBonus(StatType.Dex); int intBonus = ComputeStatBonus(StatType.Int); if (strBonus == 0 && dexBonus == 0 && intBonus == 0) return; string modName = Serial.ToString(); if (strBonus != 0) parent.AddStatMod(new StatMod(StatType.Str, modName + "Str", strBonus, TimeSpan.Zero)); if (dexBonus != 0) parent.AddStatMod(new StatMod(StatType.Dex, modName + "Dex", dexBonus, TimeSpan.Zero)); if (intBonus != 0) parent.AddStatMod(new StatMod(StatType.Int, modName + "Int", intBonus, TimeSpan.Zero)); } public static void ValidateMobile(Mobile m) { for (int i = m.Items.Count - 1; i >= 0; --i) { if (i >= m.Items.Count) continue; Item item = m.Items[i]; if (item is BaseClothing clothing) { if (clothing.RequiredRace != null && m.Race != clothing.RequiredRace) { if (clothing.RequiredRace == Race.Elf) m.SendLocalizedMessage(1072203); // Only Elves may use this. else m.SendMessage("Only {0} may use this.", clothing.RequiredRace.PluralName); m.AddToBackpack(clothing); } else if (!clothing.AllowMaleWearer && !m.Female && m.AccessLevel < AccessLevel.GameMaster) { if (clothing.AllowFemaleWearer) m.SendLocalizedMessage(1010388); // Only females can wear this. else m.SendMessage("You may not wear this."); m.AddToBackpack(clothing); } else if (!clothing.AllowFemaleWearer && m.Female && m.AccessLevel < AccessLevel.GameMaster) { if (clothing.AllowMaleWearer) m.SendLocalizedMessage(1063343); // Only males can wear this. else m.SendMessage("You may not wear this."); m.AddToBackpack(clothing); } } } } public int GetLowerStatReq() { if (!Core.AOS) return 0; return ClothingAttributes.LowerStatReq; } public override void OnAdded(IEntity parent) { if (parent is Mobile mob) { if (Core.AOS) SkillBonuses.AddTo(mob); AddStatBonuses(mob); mob.CheckStatTimers(); } base.OnAdded(parent); } public override void OnRemoved(IEntity parent) { if (parent is Mobile mob) { if (Core.AOS) SkillBonuses.Remove(); string modName = Serial.ToString(); mob.RemoveStatMod(modName + "Str"); mob.RemoveStatMod(modName + "Dex"); mob.RemoveStatMod(modName + "Int"); mob.CheckStatTimers(); } base.OnRemoved(parent); } public override void OnAfterDuped(Item newItem) { if (!(newItem is BaseClothing clothing)) return; clothing.Attributes = new AosAttributes(newItem, Attributes); clothing.Resistances = new AosElementAttributes(newItem, Resistances); clothing.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); clothing.ClothingAttributes = new AosArmorAttributes(newItem, ClothingAttributes); } public override bool AllowEquippedCast(Mobile from) { if (base.AllowEquippedCast(from)) return true; return Attributes.SpellChanneling != 0; } public override bool CheckPropertyConfliction(Mobile m) { if (base.CheckPropertyConfliction(m)) return true; if (Layer == Layer.Pants) return m.FindItemOnLayer(Layer.InnerLegs) != null; if (Layer == Layer.Shirt) return m.FindItemOnLayer(Layer.InnerTorso) != null; return false; } private string GetNameString() { return Name ?? $"#{LabelNumber}"; } public override void AddNameProperty(ObjectPropertyList list) { int oreType; switch (m_Resource) { case CraftResource.DullCopper: oreType = 1053108; break; // dull copper case CraftResource.ShadowIron: oreType = 1053107; break; // shadow iron case CraftResource.Copper: oreType = 1053106; break; // copper case CraftResource.Bronze: oreType = 1053105; break; // bronze case CraftResource.Gold: oreType = 1053104; break; // golden case CraftResource.Agapite: oreType = 1053103; break; // agapite case CraftResource.Verite: oreType = 1053102; break; // verite case CraftResource.Valorite: oreType = 1053101; break; // valorite case CraftResource.SpinedLeather: oreType = 1061118; break; // spined case CraftResource.HornedLeather: oreType = 1061117; break; // horned case CraftResource.BarbedLeather: oreType = 1061116; break; // barbed case CraftResource.RedScales: oreType = 1060814; break; // red case CraftResource.YellowScales: oreType = 1060818; break; // yellow case CraftResource.BlackScales: oreType = 1060820; break; // black case CraftResource.GreenScales: oreType = 1060819; break; // green case CraftResource.WhiteScales: oreType = 1060821; break; // white case CraftResource.BlueScales: oreType = 1060815; break; // blue default: oreType = 0; break; } if (oreType != 0) list.Add(1053099, "#{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~ else if (Name == null) list.Add(LabelNumber); else list.Add(Name); } public override void GetProperties(ObjectPropertyList list) { base.GetProperties(list); if (m_Crafter != null) list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ #region Factions if (m_FactionState != null) list.Add(1041350); // faction item #endregion if (m_Quality == ClothingQuality.Exceptional) list.Add(1060636); // exceptional if (RequiredRace == Race.Elf) list.Add(1075086); // Elves Only SkillBonuses?.GetProperties(list); int prop; if ((prop = ArtifactRarity) > 0) list.Add(1061078, prop.ToString()); // artifact rarity ~1_val~ if ((prop = Attributes.WeaponDamage) != 0) list.Add(1060401, prop.ToString()); // damage increase ~1_val~% if ((prop = Attributes.DefendChance) != 0) list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% if ((prop = Attributes.BonusDex) != 0) list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ if ((prop = Attributes.EnhancePotions) != 0) list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% if ((prop = Attributes.CastRecovery) != 0) list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ if ((prop = Attributes.CastSpeed) != 0) list.Add(1060413, prop.ToString()); // faster casting ~1_val~ if ((prop = Attributes.AttackChance) != 0) list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% if ((prop = Attributes.BonusHits) != 0) list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ if ((prop = Attributes.BonusInt) != 0) list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ if ((prop = Attributes.LowerManaCost) != 0) list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% if ((prop = Attributes.LowerRegCost) != 0) list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% if ((prop = ClothingAttributes.LowerStatReq) != 0) list.Add(1060435, prop.ToString()); // lower requirements ~1_val~% if ((prop = Attributes.Luck) != 0) list.Add(1060436, prop.ToString()); // luck ~1_val~ if ((prop = ClothingAttributes.MageArmor) != 0) list.Add(1060437); // mage armor if ((prop = Attributes.BonusMana) != 0) list.Add(1060439, prop.ToString()); // mana increase ~1_val~ if ((prop = Attributes.RegenMana) != 0) list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ if ((prop = Attributes.NightSight) != 0) list.Add(1060441); // night sight if ((prop = Attributes.ReflectPhysical) != 0) list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% if ((prop = Attributes.RegenStam) != 0) list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ if ((prop = Attributes.RegenHits) != 0) list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ if ((prop = ClothingAttributes.SelfRepair) != 0) list.Add(1060450, prop.ToString()); // self repair ~1_val~ if ((prop = Attributes.SpellChanneling) != 0) list.Add(1060482); // spell channeling if ((prop = Attributes.SpellDamage) != 0) list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% if ((prop = Attributes.BonusStam) != 0) list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ if ((prop = Attributes.BonusStr) != 0) list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ if ((prop = Attributes.WeaponSpeed) != 0) list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% base.AddResistanceProperties(list); if ((prop = ClothingAttributes.DurabilityBonus) > 0) list.Add(1060410, prop.ToString()); // durability ~1_val~% if ((prop = ComputeStatReq(StatType.Str)) > 0) list.Add(1061170, prop.ToString()); // strength requirement ~1_val~ if (m_HitPoints >= 0 && m_MaxHitPoints > 0) list.Add(1060639, "{0}\t{1}", m_HitPoints, m_MaxHitPoints); // durability ~1_val~ / ~2_val~ } public override void OnSingleClick(Mobile from) { List attrs = new List(); AddEquipInfoAttributes(from, attrs); int number; if (Name == null) { number = LabelNumber; } else { LabelTo(from, Name); number = 1041000; } if (attrs.Count == 0 && Crafter == null && Name != null) return; EquipmentInfo eqInfo = new EquipmentInfo(number, m_Crafter, false, attrs.ToArray()); from.Send(new DisplayEquipmentInfo(this, eqInfo)); } public virtual void AddEquipInfoAttributes(Mobile from, List attrs) { if (DisplayLootType) { if (LootType == LootType.Blessed) attrs.Add(new EquipInfoAttribute(1038021)); // blessed else if (LootType == LootType.Cursed) attrs.Add(new EquipInfoAttribute(1049643)); // cursed } #region Factions if (m_FactionState != null) attrs.Add(new EquipInfoAttribute(1041350)); // faction item #endregion if (m_Quality == ClothingQuality.Exceptional) attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); } public void DistributeBonuses(int amount) { for (int i = 0; i < amount; ++i) switch (Utility.Random(5)) { case 0: ++Resistances.Physical; break; case 1: ++Resistances.Fire; break; case 2: ++Resistances.Cold; break; case 3: ++Resistances.Poison; break; case 4: ++Resistances.Energy; break; } InvalidateProperties(); } #region Factions private FactionItem m_FactionState; public FactionItem FactionItemState { get => m_FactionState; set { m_FactionState = value; if (m_FactionState == null) Hue = 0; LootType = m_FactionState == null ? LootType.Regular : LootType.Blessed; } } #endregion #region Serialization private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) { if (setIf) flags |= toSet; } private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) { return (flags & toGet) != 0; } [Flags] private enum SaveFlag { None = 0x00000000, Resource = 0x00000001, Attributes = 0x00000002, ClothingAttributes = 0x00000004, SkillBonuses = 0x00000008, Resistances = 0x00000010, MaxHitPoints = 0x00000020, HitPoints = 0x00000040, PlayerConstructed = 0x00000080, Crafter = 0x00000100, Quality = 0x00000200, StrReq = 0x00000400 } public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write(5); // version SaveFlag flags = SaveFlag.None; SetSaveFlag(ref flags, SaveFlag.Resource, m_Resource != DefaultResource); SetSaveFlag(ref flags, SaveFlag.Attributes, !Attributes.IsEmpty); SetSaveFlag(ref flags, SaveFlag.ClothingAttributes, !ClothingAttributes.IsEmpty); SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !SkillBonuses.IsEmpty); SetSaveFlag(ref flags, SaveFlag.Resistances, !Resistances.IsEmpty); SetSaveFlag(ref flags, SaveFlag.MaxHitPoints, m_MaxHitPoints != 0); SetSaveFlag(ref flags, SaveFlag.HitPoints, m_HitPoints != 0); SetSaveFlag(ref flags, SaveFlag.PlayerConstructed, PlayerConstructed); SetSaveFlag(ref flags, SaveFlag.Crafter, m_Crafter != null); SetSaveFlag(ref flags, SaveFlag.Quality, m_Quality != ClothingQuality.Regular); SetSaveFlag(ref flags, SaveFlag.StrReq, m_StrReq != -1); writer.WriteEncodedInt((int)flags); if (GetSaveFlag(flags, SaveFlag.Resource)) writer.WriteEncodedInt((int)m_Resource); if (GetSaveFlag(flags, SaveFlag.Attributes)) Attributes.Serialize(writer); if (GetSaveFlag(flags, SaveFlag.ClothingAttributes)) ClothingAttributes.Serialize(writer); if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) SkillBonuses.Serialize(writer); if (GetSaveFlag(flags, SaveFlag.Resistances)) Resistances.Serialize(writer); if (GetSaveFlag(flags, SaveFlag.MaxHitPoints)) writer.WriteEncodedInt(m_MaxHitPoints); if (GetSaveFlag(flags, SaveFlag.HitPoints)) writer.WriteEncodedInt(m_HitPoints); if (GetSaveFlag(flags, SaveFlag.Crafter)) writer.Write(m_Crafter); if (GetSaveFlag(flags, SaveFlag.Quality)) writer.WriteEncodedInt((int)m_Quality); if (GetSaveFlag(flags, SaveFlag.StrReq)) writer.WriteEncodedInt(m_StrReq); } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); int version = reader.ReadInt(); switch (version) { case 5: { SaveFlag flags = (SaveFlag)reader.ReadEncodedInt(); if (GetSaveFlag(flags, SaveFlag.Resource)) m_Resource = (CraftResource)reader.ReadEncodedInt(); else m_Resource = DefaultResource; if (GetSaveFlag(flags, SaveFlag.Attributes)) Attributes = new AosAttributes(this, reader); else Attributes = new AosAttributes(this); if (GetSaveFlag(flags, SaveFlag.ClothingAttributes)) ClothingAttributes = new AosArmorAttributes(this, reader); else ClothingAttributes = new AosArmorAttributes(this); if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) SkillBonuses = new AosSkillBonuses(this, reader); else SkillBonuses = new AosSkillBonuses(this); if (GetSaveFlag(flags, SaveFlag.Resistances)) Resistances = new AosElementAttributes(this, reader); else Resistances = new AosElementAttributes(this); if (GetSaveFlag(flags, SaveFlag.MaxHitPoints)) m_MaxHitPoints = reader.ReadEncodedInt(); if (GetSaveFlag(flags, SaveFlag.HitPoints)) m_HitPoints = reader.ReadEncodedInt(); if (GetSaveFlag(flags, SaveFlag.Crafter)) m_Crafter = reader.ReadMobile(); if (GetSaveFlag(flags, SaveFlag.Quality)) m_Quality = (ClothingQuality)reader.ReadEncodedInt(); else m_Quality = ClothingQuality.Regular; if (GetSaveFlag(flags, SaveFlag.StrReq)) m_StrReq = reader.ReadEncodedInt(); else m_StrReq = -1; if (GetSaveFlag(flags, SaveFlag.PlayerConstructed)) PlayerConstructed = true; break; } case 4: { m_Resource = (CraftResource)reader.ReadInt(); goto case 3; } case 3: { Attributes = new AosAttributes(this, reader); ClothingAttributes = new AosArmorAttributes(this, reader); SkillBonuses = new AosSkillBonuses(this, reader); Resistances = new AosElementAttributes(this, reader); goto case 2; } case 2: { PlayerConstructed = reader.ReadBool(); goto case 1; } case 1: { m_Crafter = reader.ReadMobile(); m_Quality = (ClothingQuality)reader.ReadInt(); break; } case 0: { m_Crafter = null; m_Quality = ClothingQuality.Regular; break; } } if (version < 2) PlayerConstructed = true; // we don't know, so, assume it's crafted if (version < 3) { Attributes = new AosAttributes(this); ClothingAttributes = new AosArmorAttributes(this); SkillBonuses = new AosSkillBonuses(this); Resistances = new AosElementAttributes(this); } if (version < 4) m_Resource = DefaultResource; if (m_MaxHitPoints == 0 && m_HitPoints == 0) m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); if (Parent is Mobile parent) { if (Core.AOS) SkillBonuses.AddTo(parent); AddStatBonuses(parent); parent.CheckStatTimers(); } } #endregion } }