using System; using ModernUO.Serialization; using Server.Engines.Craft; namespace Server.Items; public enum GemType { None, StarSapphire, Emerald, Sapphire, Ruby, Citrine, Amethyst, Tourmaline, Amber, Diamond } [SerializationGenerator(4, false)] public abstract partial class BaseJewel : Item, ICraftable, IAosItem { [EncodedInt] [InvalidateProperties] [SerializableField(0)] [SerializedCommandProperty(AccessLevel.GameMaster)] private int _maxHitPoints; [SerializableField(3)] [InvalidateProperties] [SerializedCommandProperty(AccessLevel.GameMaster)] private GemType _gemType; [SerializedIgnoreDupe] [SerializableField(4, setter: "private")] [SerializedCommandProperty(AccessLevel.GameMaster, canModify: true)] private AosAttributes _attributes; [SerializedIgnoreDupe] [SerializableField(5, setter: "private")] [SerializedCommandProperty(AccessLevel.GameMaster, canModify: true)] private AosElementAttributes _resistances; [SerializedIgnoreDupe] [SerializableField(6, setter: "private")] [SerializedCommandProperty(AccessLevel.GameMaster, canModify: true)] private AosSkillBonuses _skillBonuses; public BaseJewel(int itemID, Layer layer) : base(itemID) { _attributes = new AosAttributes(this); _resistances = new AosElementAttributes(this); _skillBonuses = new AosSkillBonuses(this); _resource = CraftResource.Iron; Hue = CraftResources.GetHue(_resource); _gemType = GemType.None; Layer = layer; _hitPoints = _maxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); } [EncodedInt] [SerializableProperty(1)] [CommandProperty(AccessLevel.GameMaster)] public int HitPoints { get => _hitPoints; set { if (value != _hitPoints && _maxHitPoints > 0) { _hitPoints = value; if (_hitPoints < 0) { Delete(); } else if (_hitPoints > _maxHitPoints) { _hitPoints = _maxHitPoints; } InvalidateProperties(); this.MarkDirty(); } } } [SerializableProperty(2)] [CommandProperty(AccessLevel.GameMaster)] public CraftResource Resource { get => _resource; set { _resource = value; Hue = CraftResources.GetHue(_resource); } } public override int PhysicalResistance => Resistances.Physical; public override int FireResistance => Resistances.Fire; public override int ColdResistance => Resistances.Cold; public override int PoisonResistance => Resistances.Poison; public override int EnergyResistance => Resistances.Energy; public virtual int BaseGemTypeNumber => 0; public virtual int InitMinHits => 0; public virtual int InitMaxHits => 0; public override int LabelNumber { get { if (_gemType == GemType.None) { return base.LabelNumber; } return BaseGemTypeNumber + (int)_gemType - 1; } } public virtual int ArtifactRarity => 0; public int OnCraft( int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CraftItem craftItem, int resHue ) { var resourceType = typeRes ?? craftItem.Resources[0].ItemType; Resource = CraftResources.GetFromType(resourceType); var context = craftSystem.GetContext(from); if (context?.DoNotColor == true) { Hue = 0; } if (craftItem.Resources.Count > 1) { resourceType = craftItem.Resources[1].ItemType; if (resourceType == typeof(StarSapphire)) { GemType = GemType.StarSapphire; } else if (resourceType == typeof(Emerald)) { GemType = GemType.Emerald; } else if (resourceType == typeof(Sapphire)) { GemType = GemType.Sapphire; } else if (resourceType == typeof(Ruby)) { GemType = GemType.Ruby; } else if (resourceType == typeof(Citrine)) { GemType = GemType.Citrine; } else if (resourceType == typeof(Amethyst)) { GemType = GemType.Amethyst; } else if (resourceType == typeof(Tourmaline)) { GemType = GemType.Tourmaline; } else if (resourceType == typeof(Amber)) { GemType = GemType.Amber; } else if (resourceType == typeof(Diamond)) { GemType = GemType.Diamond; } } return 1; } public override void OnAfterDuped(Item newItem) { if (newItem is not BaseJewel jewel) { return; } jewel.Attributes = new AosAttributes(newItem, Attributes); jewel.Resistances = new AosElementAttributes(newItem, Resistances); jewel.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); // Set hue again because of resource jewel.Hue = Hue; } public override void OnAdded(IEntity parent) { if (Core.AOS && parent is Mobile from) { SkillBonuses.AddTo(from); var strBonus = Attributes.BonusStr; var dexBonus = Attributes.BonusDex; var intBonus = Attributes.BonusInt; if (strBonus != 0 || dexBonus != 0 || intBonus != 0) { var serial = Serial; if (strBonus != 0) { from.AddStatMod(new StatMod(StatType.Str, $"{serial}Str", strBonus, TimeSpan.Zero)); } if (dexBonus != 0) { from.AddStatMod(new StatMod(StatType.Dex, $"{serial}Dex", dexBonus, TimeSpan.Zero)); } if (intBonus != 0) { from.AddStatMod(new StatMod(StatType.Int, $"{serial}Int", intBonus, TimeSpan.Zero)); } } from.CheckStatTimers(); } } public override void OnRemoved(IEntity parent) { if (Core.AOS && parent is Mobile from) { SkillBonuses.Remove(); var serial = Serial; from.RemoveStatMod($"{serial}Str"); from.RemoveStatMod($"{serial}Dex"); from.RemoveStatMod($"{serial}Int"); from.CheckStatTimers(); } } public override void GetProperties(IPropertyList list) { base.GetProperties(list); SkillBonuses.GetProperties(list); int prop; if ((prop = ArtifactRarity) > 0) { 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~% } AddResistanceProperties(list); if (_hitPoints >= 0 && _maxHitPoints > 0) { list.Add(1060639, $"{_hitPoints}\t{_maxHitPoints}"); // durability ~1_val~ / ~2_val~ } } private void Deserialize(IGenericReader reader, int version) { _maxHitPoints = reader.ReadEncodedInt(); _hitPoints = reader.ReadEncodedInt(); _resource = (CraftResource)reader.ReadEncodedInt(); _gemType = (GemType)reader.ReadEncodedInt(); _attributes = new AosAttributes(this); _attributes.Deserialize(reader); _resistances = new AosElementAttributes(this); _resistances.Deserialize(reader); _skillBonuses = new AosSkillBonuses(this); _skillBonuses.Deserialize(reader); } [AfterDeserialization] private void AfterDeserialization() { var m = Parent as Mobile; if (Core.AOS && m != null) { SkillBonuses.AddTo(m); } var strBonus = Attributes.BonusStr; var dexBonus = Attributes.BonusDex; var intBonus = Attributes.BonusInt; if (m != null && (strBonus != 0 || dexBonus != 0 || intBonus != 0)) { var serial = Serial; if (strBonus != 0) { m.AddStatMod(new StatMod(StatType.Str, $"{serial}Str", strBonus, TimeSpan.Zero)); } if (dexBonus != 0) { m.AddStatMod(new StatMod(StatType.Dex, $"{serial}Dex", dexBonus, TimeSpan.Zero)); } if (intBonus != 0) { m.AddStatMod(new StatMod(StatType.Int, $"{serial}Int", intBonus, TimeSpan.Zero)); } } m?.CheckStatTimers(); } }