diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/BambooFlute.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/BambooFlute.cs index 017893ec6..7bf75926b 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/BambooFlute.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/BambooFlute.cs @@ -1,31 +1,10 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class BambooFlute : BaseInstrument { - public class BambooFlute : BaseInstrument - { - [Constructible] - public BambooFlute() : base(0x2805, 0x504, 0x503) => Weight = 2.0; - - public BambooFlute(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (Weight == 3.0) - { - Weight = 2.0; - } - } - } + [Constructible] + public BambooFlute() : base(0x2805, 0x504, 0x503) => Weight = 2.0; } diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs index c92f853f2..5024891a8 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs @@ -1,608 +1,530 @@ using System; using System.Collections.Generic; +using ModernUO.Serialization; using Server.Engines.Craft; using Server.Mobiles; using Server.Network; using Server.Targeting; -namespace Server.Items -{ - public delegate void InstrumentPickedCallback(Mobile from, BaseInstrument instrument); +namespace Server.Items; - public enum InstrumentQuality +public delegate void InstrumentPickedCallback(Mobile from, BaseInstrument instrument); + +public enum InstrumentQuality +{ + Low, + Regular, + Exceptional +} + +[SerializationGenerator(4, false)] +public abstract partial class BaseInstrument : Item, ICraftable, ISlayer +{ + private static readonly Dictionary _instruments = new(); + + [InvalidateProperties] + [SerializableField(2)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private string _crafter; + + [InvalidateProperties] + [SerializableField(4)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private SlayerName _slayer; + + [InvalidateProperties] + [SerializableField(5)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private SlayerName _slayer2; + + [SerializableField(7)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private int _successSound; + + [SerializableField(8)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private int _failureSound; + + public BaseInstrument(int itemID, int wellSound, int badlySound) : base(itemID) { - Low, - Regular, - Exceptional + _successSound = wellSound; + _failureSound = badlySound; + _usesRemaining = Utility.RandomMinMax(InitMinUses, InitMaxUses); } - public abstract class BaseInstrument : Item, ICraftable, ISlayer + public virtual int InitMinUses => 350; + public virtual int InitMaxUses => 450; + + public virtual TimeSpan ChargeReplenishRate => TimeSpan.FromMinutes(5.0); + + [SerializableProperty(0)] + [CommandProperty(AccessLevel.GameMaster)] + public bool ReplenishesCharges { - private static readonly Dictionary m_Instruments = new(); - private Mobile m_Crafter; - - private DateTime m_LastReplenished; - private InstrumentQuality m_Quality; - - private bool m_ReplenishesCharges; - private SlayerName m_Slayer, m_Slayer2; - private int m_UsesRemaining; - - public BaseInstrument(int itemID, int wellSound, int badlySound) : base(itemID) + get => _replenishesCharges; + set { - SuccessSound = wellSound; - FailureSound = badlySound; - UsesRemaining = Utility.RandomMinMax(InitMinUses, InitMaxUses); + if (value != _replenishesCharges && value) + { + LastReplenished = Core.Now; + } + + _replenishesCharges = value; + this.MarkDirty(); } + } - public BaseInstrument(Serial serial) : base(serial) + [SerializableProperty(1)] + [CommandProperty(AccessLevel.GameMaster)] + public DateTime LastReplenished + { + get => _lastReplenished; + set { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SuccessSound { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int FailureSound { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public InstrumentQuality Quality - { - get => m_Quality; - set - { - UnscaleUses(); - m_Quality = value; - InvalidateProperties(); - ScaleUses(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - public virtual int InitMinUses => 350; - public virtual int InitMaxUses => 450; - - public virtual TimeSpan ChargeReplenishRate => TimeSpan.FromMinutes(5.0); - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get - { - CheckReplenishUses(); - return m_UsesRemaining; - } - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime LastReplenished - { - get => m_LastReplenished; - set - { - m_LastReplenished = value; - CheckReplenishUses(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ReplenishesCharges - { - get => m_ReplenishesCharges; - set - { - if (value != m_ReplenishesCharges && value) - { - m_LastReplenished = Core.Now; - } - - m_ReplenishesCharges = value; - } - } - - public int OnCraft( - int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue - ) - { - Quality = (InstrumentQuality)quality; - - if (makersMark) - { - Crafter = from; - } - - return quality; - } - - [CommandProperty(AccessLevel.GameMaster)] - public SlayerName Slayer - { - get => m_Slayer; - set - { - m_Slayer = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public SlayerName Slayer2 - { - get => m_Slayer2; - set - { - m_Slayer2 = value; - InvalidateProperties(); - } - } - - public void CheckReplenishUses(bool invalidate = true) - { - if (!m_ReplenishesCharges || m_UsesRemaining >= InitMaxUses) - { - return; - } - - if (m_LastReplenished + ChargeReplenishRate < Core.Now) - { - var timeDifference = Core.Now - m_LastReplenished; - - m_UsesRemaining = Math.Min( - m_UsesRemaining + (int)(timeDifference.Ticks / ChargeReplenishRate.Ticks), - InitMaxUses - ); // How rude of TimeSpan to not allow timespan division. - m_LastReplenished = Core.Now; - - if (invalidate) - { - InvalidateProperties(); - } - } - } - - public void ScaleUses() - { - UsesRemaining = UsesRemaining * GetUsesScalar() / 100; - // InvalidateProperties(); - } - - public void UnscaleUses() - { - UsesRemaining = UsesRemaining * 100 / GetUsesScalar(); - } - - public int GetUsesScalar() => m_Quality == InstrumentQuality.Exceptional ? 200 : 100; - - public void ConsumeUse(Mobile from) - { - // TODO: Confirm what must happen here? - - if (UsesRemaining > 1) - { - --UsesRemaining; - } - else - { - from?.SendLocalizedMessage(502079); // The instrument played its last tune. - - Delete(); - } - } - - public static BaseInstrument GetInstrument(Mobile from) - { - if (m_Instruments.TryGetValue(from, out var instrument) && instrument.IsChildOf(from.Backpack)) - { - return instrument; - } - - m_Instruments.Remove(from); - return null; - } - - public static int GetBardRange(Mobile bard, SkillName skill) => 8 + (int)(bard.Skills[skill].Value / 15); - - public static void PickInstrument(Mobile from, InstrumentPickedCallback callback) - { - var instrument = GetInstrument(from); - if (instrument != null) - { - callback?.Invoke(from, instrument); - } - else - { - from.SendLocalizedMessage(500617); // What instrument shall you play? - from.BeginTarget(1, false, TargetFlags.None, OnPickedInstrument, callback); - } - } - - public static void OnPickedInstrument(Mobile from, object targeted, InstrumentPickedCallback callback) - { - if (targeted is not BaseInstrument instrument) - { - from.SendLocalizedMessage(500619); // That is not a musical instrument. - } - else - { - SetInstrument(from, instrument); - callback?.Invoke(from, instrument); - } - } - - public static bool IsMageryCreature(BaseCreature bc) => bc?.AI == AIType.AI_Mage && bc.Skills.Magery.Base > 5.0; - - public static bool IsFireBreathingCreature(BaseCreature bc) => bc?.GetAbility(MonsterAbilityType.FireBreath) != null; - - public static bool IsPoisonImmune(BaseCreature bc) => bc?.PoisonImmune != null; - - public static int GetPoisonLevel(BaseCreature bc) => (bc?.HitPoison?.Level ?? -1) + 1; - - public static double GetBaseDifficulty(Mobile targ) - { - /* Difficulty TODO: Add another 100 points for each of the following abilities: - - Radiation or Aura Damage (Heat, Cold etc.) - - Summoning Undead - */ - - // Before LBR, the success rate is actually your skill rate. - // We are going to fudge the numbers so it feels right without having two separate provocation calculations - // To do this, we should *undo* the 1.6x multiplier on HitsMaxSeed - var val = targ.HitsMax * (Core.LBR ? 1.6 : 0.625) + targ.StamMax + targ.ManaMax; - - val += targ.SkillsTotal / 10.0; - - if (val > 700) - { - val = 700 + (int)((val - 700) * (3.0 / 11)); - } - - var bc = targ as BaseCreature; - - if (IsMageryCreature(bc)) - { - val += 100; - } - - if (IsFireBreathingCreature(bc)) - { - val += 100; - } - - if (IsPoisonImmune(bc)) - { - val += 100; - } - - if (targ is VampireBat or VampireBatFamiliar) - { - val += 100; - } - - val += GetPoisonLevel(bc) * 20; - - val /= 10; - - if (bc?.IsParagon == true) - { - val += 40.0; - } - - if (Core.SE && val > 160.0) - { - val = 160.0; - } - - return val; - } - - public double GetDifficultyFor(Mobile targ) - { - var val = GetBaseDifficulty(targ); - - if (m_Quality == InstrumentQuality.Exceptional) - { - val -= 5.0; // 10% - } - - if (m_Slayer != SlayerName.None) - { - var entry = SlayerGroup.GetEntryByName(m_Slayer); - - if (entry != null) - { - if (entry.Slays(targ)) - { - val -= 10.0; // 20% - } - else if (entry.Group.OppositionSuperSlays(targ)) - { - val += 10.0; // -20% - } - } - } - - if (m_Slayer2 != SlayerName.None) - { - var entry = SlayerGroup.GetEntryByName(m_Slayer2); - - if (entry != null) - { - if (entry.Slays(targ)) - { - val -= 10.0; // 20% - } - else if (entry.Group.OppositionSuperSlays(targ)) - { - val += 10.0; // -20% - } - } - } - - return val; - } - - public static void SetInstrument(Mobile from, BaseInstrument item) - { - m_Instruments[from] = item; - } - - public override void GetProperties(IPropertyList list) - { - var oldUses = m_UsesRemaining; - CheckReplenishUses(false); - - base.GetProperties(list); - - if (m_Crafter != null) - { - list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ - } - - if (m_Quality == InstrumentQuality.Exceptional) - { - list.Add(1060636); // exceptional - } - - list.Add(1060584, m_UsesRemaining); // uses remaining: ~1_val~ - - if (m_ReplenishesCharges) - { - list.Add(1070928); // Replenish Charges - } - - if (m_Slayer != SlayerName.None) - { - var entry = SlayerGroup.GetEntryByName(m_Slayer); - if (entry != null) - { - list.Add(entry.Title); - } - } - - if (m_Slayer2 != SlayerName.None) - { - var entry = SlayerGroup.GetEntryByName(m_Slayer2); - if (entry != null) - { - list.Add(entry.Title); - } - } - - if (m_UsesRemaining != oldUses) - { - Timer.StartTimer(InvalidateProperties); - } - } - - public override void OnSingleClick(Mobile from) - { - var attrs = new List(); - - if (DisplayLootType) - { - if (LootType == LootType.Blessed) - { - attrs.Add(new EquipInfoAttribute(1038021)); // blessed - } - else if (LootType == LootType.Cursed) - { - attrs.Add(new EquipInfoAttribute(1049643)); // cursed - } - } - - if (m_Quality == InstrumentQuality.Exceptional) - { - attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); - } - - if (m_ReplenishesCharges) - { - attrs.Add(new EquipInfoAttribute(1070928)); // Replenish Charges - } - - // TODO: Must this support item identification? - if (m_Slayer != SlayerName.None) - { - var entry = SlayerGroup.GetEntryByName(m_Slayer); - if (entry != null) - { - attrs.Add(new EquipInfoAttribute(entry.Title)); - } - } - - if (m_Slayer2 != SlayerName.None) - { - var entry = SlayerGroup.GetEntryByName(m_Slayer2); - if (entry != null) - { - attrs.Add(new EquipInfoAttribute(entry.Title)); - } - } - - int number; - - if (Name == null) - { - number = LabelNumber; - } - else - { - LabelTo(from, Name); - number = 1041000; - } - - if (attrs.Count == 0 && Crafter == null && Name != null) - { - return; - } - - from.NetState.SendDisplayEquipmentInfo(Serial, number, m_Crafter?.RawName, false, attrs); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(3); // version - - writer.Write(m_ReplenishesCharges); - if (m_ReplenishesCharges) - { - writer.Write(m_LastReplenished); - } - - writer.Write(m_Crafter); - - writer.WriteEncodedInt((int)m_Quality); - writer.WriteEncodedInt((int)m_Slayer); - writer.WriteEncodedInt((int)m_Slayer2); - - writer.WriteEncodedInt(UsesRemaining); - - writer.WriteEncodedInt(SuccessSound); - writer.WriteEncodedInt(FailureSound); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 3: - { - m_ReplenishesCharges = reader.ReadBool(); - - if (m_ReplenishesCharges) - { - m_LastReplenished = reader.ReadDateTime(); - } - - goto case 2; - } - case 2: - { - m_Crafter = reader.ReadEntity(); - - m_Quality = (InstrumentQuality)reader.ReadEncodedInt(); - m_Slayer = (SlayerName)reader.ReadEncodedInt(); - m_Slayer2 = (SlayerName)reader.ReadEncodedInt(); - - UsesRemaining = reader.ReadEncodedInt(); - - SuccessSound = reader.ReadEncodedInt(); - FailureSound = reader.ReadEncodedInt(); - - break; - } - case 1: - { - m_Crafter = reader.ReadEntity(); - - m_Quality = (InstrumentQuality)reader.ReadEncodedInt(); - m_Slayer = (SlayerName)reader.ReadEncodedInt(); - - UsesRemaining = reader.ReadEncodedInt(); - - SuccessSound = reader.ReadEncodedInt(); - FailureSound = reader.ReadEncodedInt(); - - break; - } - case 0: - { - SuccessSound = reader.ReadInt(); - FailureSound = reader.ReadInt(); - UsesRemaining = Utility.RandomMinMax(InitMinUses, InitMaxUses); - - break; - } - } - + _lastReplenished = value; CheckReplenishUses(); } + } - public override void OnDoubleClick(Mobile from) + [SerializableProperty(3)] + [CommandProperty(AccessLevel.GameMaster)] + public InstrumentQuality Quality + { + get => _quality; + set { - if (!from.InRange(GetWorldLocation(), 1)) + UnscaleUses(); + _quality = value; + InvalidateProperties(); + ScaleUses(); + } + } + + [SerializableProperty(6)] + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get + { + CheckReplenishUses(); + return _usesRemaining; + } + set + { + _usesRemaining = value; + InvalidateProperties(); + } + } + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + Quality = (InstrumentQuality)quality; + + if (makersMark) + { + Crafter = from?.RawName; + } + + return quality; + } + + public void CheckReplenishUses(bool invalidate = true) + { + if (!_replenishesCharges || _usesRemaining >= InitMaxUses) + { + return; + } + + if (_lastReplenished + ChargeReplenishRate < Core.Now) + { + var timeDifference = Core.Now - _lastReplenished; + + // How rude of TimeSpan to not allow timespan division. + _usesRemaining = Math.Min( + _usesRemaining + (int)(timeDifference.Ticks / ChargeReplenishRate.Ticks), InitMaxUses + ); + + // Don't use the property here otherwise you will get an infinite loop. + _lastReplenished = Core.Now; + + if (invalidate) { - from.SendLocalizedMessage(500446); // That is too far away. + InvalidateProperties(); } - else if (from.BeginAction()) + } + } + + public void ScaleUses() + { + UsesRemaining = UsesRemaining * GetUsesScalar() / 100; + // InvalidateProperties(); + } + + public void UnscaleUses() + { + UsesRemaining = UsesRemaining * 100 / GetUsesScalar(); + } + + public int GetUsesScalar() => _quality == InstrumentQuality.Exceptional ? 200 : 100; + + public void ConsumeUse(Mobile from) + { + // TODO: Confirm what must happen here? + + if (UsesRemaining > 1) + { + --UsesRemaining; + } + else + { + from?.SendLocalizedMessage(502079); // The instrument played its last tune. + + Delete(); + } + } + + public static BaseInstrument GetInstrument(Mobile from) + { + if (_instruments.TryGetValue(from, out var instrument) && instrument.IsChildOf(from.Backpack)) + { + return instrument; + } + + _instruments.Remove(from); + return null; + } + + public static int GetBardRange(Mobile bard, SkillName skill) => 8 + (int)(bard.Skills[skill].Value / 15); + + public static void PickInstrument(Mobile from, InstrumentPickedCallback callback) + { + var instrument = GetInstrument(from); + if (instrument != null) + { + callback?.Invoke(from, instrument); + } + else + { + from.SendLocalizedMessage(500617); // What instrument shall you play? + from.BeginTarget(1, false, TargetFlags.None, OnPickedInstrument, callback); + } + } + + public static void OnPickedInstrument(Mobile from, object targeted, InstrumentPickedCallback callback) + { + if (targeted is not BaseInstrument instrument) + { + from.SendLocalizedMessage(500619); // That is not a musical instrument. + } + else + { + SetInstrument(from, instrument); + callback?.Invoke(from, instrument); + } + } + + public static bool IsMageryCreature(BaseCreature bc) => bc?.AI == AIType.AI_Mage && bc.Skills.Magery.Base > 5.0; + + public static bool IsFireBreathingCreature(BaseCreature bc) => bc?.GetAbility(MonsterAbilityType.FireBreath) != null; + + public static bool IsPoisonImmune(BaseCreature bc) => bc?.PoisonImmune != null; + + public static int GetPoisonLevel(BaseCreature bc) => (bc?.HitPoison?.Level ?? -1) + 1; + + public static double GetBaseDifficulty(Mobile targ) + { + /* Difficulty TODO: Add another 100 points for each of the following abilities: + - Radiation or Aura Damage (Heat, Cold etc.) + - Summoning Undead + */ + + // Before LBR, the success rate is actually your skill rate. + // We are going to fudge the numbers so it feels right without having two separate provocation calculations + // To do this, we should *undo* the 1.6x multiplier on HitsMaxSeed + var val = targ.HitsMax * (Core.LBR ? 1.6 : 0.625) + targ.StamMax + targ.ManaMax; + + val += targ.SkillsTotal / 10.0; + + if (val > 700) + { + val = 700 + (int)((val - 700) * (3.0 / 11)); + } + + var bc = targ as BaseCreature; + + if (IsMageryCreature(bc)) + { + val += 100; + } + + if (IsFireBreathingCreature(bc)) + { + val += 100; + } + + if (IsPoisonImmune(bc)) + { + val += 100; + } + + if (targ is VampireBat or VampireBatFamiliar) + { + val += 100; + } + + val += GetPoisonLevel(bc) * 20; + + val /= 10; + + if (bc?.IsParagon == true) + { + val += 40.0; + } + + if (Core.SE && val > 160.0) + { + val = 160.0; + } + + return val; + } + + public double GetDifficultyFor(Mobile targ) + { + var val = GetBaseDifficulty(targ); + + if (_quality == InstrumentQuality.Exceptional) + { + val -= 5.0; // 10% + } + + if (_slayer != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(_slayer); + + if (entry != null) { - SetInstrument(from, this); - - // Delay of 6 second before being able to play another instrument again - Timer.StartTimer(TimeSpan.FromSeconds(6), from.EndAction); - - if (CheckMusicianship(from)) + if (entry.Slays(targ)) { - PlayInstrumentWell(from); + val -= 10.0; // 20% } - else + else if (entry.Group.OppositionSuperSlays(targ)) { - PlayInstrumentBadly(from); + val += 10.0; // -20% } } + } + + if (_slayer2 != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(_slayer2); + + if (entry != null) + { + if (entry.Slays(targ)) + { + val -= 10.0; // 20% + } + else if (entry.Group.OppositionSuperSlays(targ)) + { + val += 10.0; // -20% + } + } + } + + return val; + } + + public static void SetInstrument(Mobile from, BaseInstrument item) + { + _instruments[from] = item; + } + + public override void GetProperties(IPropertyList list) + { + var oldUses = _usesRemaining; + CheckReplenishUses(false); + + base.GetProperties(list); + + if (_crafter != null) + { + list.Add(1050043, _crafter); // crafted by ~1_NAME~ + } + + if (_quality == InstrumentQuality.Exceptional) + { + list.Add(1060636); // exceptional + } + + list.Add(1060584, _usesRemaining); // uses remaining: ~1_val~ + + if (_replenishesCharges) + { + list.Add(1070928); // Replenish Charges + } + + if (_slayer != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(_slayer); + if (entry != null) + { + list.Add(entry.Title); + } + } + + if (_slayer2 != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(_slayer2); + if (entry != null) + { + list.Add(entry.Title); + } + } + + if (_usesRemaining != oldUses) + { + Timer.StartTimer(InvalidateProperties); + } + } + + public override void OnSingleClick(Mobile from) + { + var attrs = new List(); + + if (DisplayLootType) + { + if (LootType == LootType.Blessed) + { + attrs.Add(new EquipInfoAttribute(1038021)); // blessed + } + else if (LootType == LootType.Cursed) + { + attrs.Add(new EquipInfoAttribute(1049643)); // cursed + } + } + + if (_quality == InstrumentQuality.Exceptional) + { + attrs.Add(new EquipInfoAttribute(1018305 - (int)_quality)); + } + + if (_replenishesCharges) + { + attrs.Add(new EquipInfoAttribute(1070928)); // Replenish Charges + } + + // TODO: Must this support item identification? + if (_slayer != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(_slayer); + if (entry != null) + { + attrs.Add(new EquipInfoAttribute(entry.Title)); + } + } + + if (_slayer2 != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(_slayer2); + if (entry != null) + { + attrs.Add(new EquipInfoAttribute(entry.Title)); + } + } + + int number; + + if (Name == null) + { + number = LabelNumber; + } + else + { + LabelTo(from, Name); + number = 1041000; + } + + if (attrs.Count == 0 && Crafter == null && Name != null) + { + return; + } + + from.NetState.SendDisplayEquipmentInfo(Serial, number, _crafter, false, attrs); + } + + private void Deserialize(IGenericReader reader, int version) + { + _replenishesCharges = reader.ReadBool(); + + if (_replenishesCharges) + { + _lastReplenished = reader.ReadDateTime(); + } + + Timer.DelayCall((item, crafter) => item._crafter = crafter?.RawName, this, reader.ReadEntity()); + + _quality = (InstrumentQuality)reader.ReadEncodedInt(); + _slayer = (SlayerName)reader.ReadEncodedInt(); + _slayer2 = (SlayerName)reader.ReadEncodedInt(); + + UsesRemaining = reader.ReadEncodedInt(); + + SuccessSound = reader.ReadEncodedInt(); + FailureSound = reader.ReadEncodedInt(); + } + + [AfterDeserialization] + private void AfterDeserialization() + { + CheckReplenishUses(false); + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 1)) + { + from.SendLocalizedMessage(500446); // That is too far away. + } + else if (from.BeginAction()) + { + SetInstrument(from, this); + + // Delay of 6 second before being able to play another instrument again + Timer.StartTimer(TimeSpan.FromSeconds(6), from.EndAction); + + if (CheckMusicianship(from)) + { + PlayInstrumentWell(from); + } else { - from.SendLocalizedMessage(500119); // You must wait to perform another action + PlayInstrumentBadly(from); } } - - public static bool CheckMusicianship(Mobile m) + else { - m.CheckSkill(SkillName.Musicianship, 0.0, 120.0); - - return m.Skills.Musicianship.Value / 100 > Utility.RandomDouble(); - } - - public void PlayInstrumentWell(Mobile from) - { - from.PlaySound(SuccessSound); - } - - public void PlayInstrumentBadly(Mobile from) - { - from.PlaySound(FailureSound); + from.SendLocalizedMessage(500119); // You must wait to perform another action } } + + public static bool CheckMusicianship(Mobile m) + { + m.CheckSkill(SkillName.Musicianship, 0.0, 120.0); + + return m.Skills.Musicianship.Value / 100 > Utility.RandomDouble(); + } + + public void PlayInstrumentWell(Mobile from) + { + from.PlaySound(SuccessSound); + } + + public void PlayInstrumentBadly(Mobile from) + { + from.PlaySound(FailureSound); + } } diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/Drums.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/Drums.cs index da9567aa2..893768a5a 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/Drums.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/Drums.cs @@ -1,31 +1,10 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class Drums : BaseInstrument { - public class Drums : BaseInstrument - { - [Constructible] - public Drums() : base(0xE9C, 0x38, 0x39) => Weight = 4.0; - - public Drums(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (Weight == 3.0) - { - Weight = 4.0; - } - } - } + [Constructible] + public Drums() : base(0xE9C, 0x38, 0x39) => Weight = 4.0; } diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/Harp.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/Harp.cs index e317788bc..69e5609dc 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/Harp.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/Harp.cs @@ -1,31 +1,10 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class Harp : BaseInstrument { - public class Harp : BaseInstrument - { - [Constructible] - public Harp() : base(0xEB1, 0x43, 0x44) => Weight = 35.0; - - public Harp(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (Weight == 3.0) - { - Weight = 35.0; - } - } - } + [Constructible] + public Harp() : base(0xEB1, 0x43, 0x44) => Weight = 35.0; } diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/LapHarp.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/LapHarp.cs index e6eef310f..ebd96445c 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/LapHarp.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/LapHarp.cs @@ -1,31 +1,10 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class LapHarp : BaseInstrument { - public class LapHarp : BaseInstrument - { - [Constructible] - public LapHarp() : base(0xEB2, 0x45, 0x46) => Weight = 10.0; - - public LapHarp(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (Weight == 3.0) - { - Weight = 10.0; - } - } - } + [Constructible] + public LapHarp() : base(0xEB2, 0x45, 0x46) => Weight = 10.0; } diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/Lute.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/Lute.cs index 90c82d01a..308394492 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/Lute.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/Lute.cs @@ -1,31 +1,10 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class Lute : BaseInstrument { - public class Lute : BaseInstrument - { - [Constructible] - public Lute() : base(0xEB3, 0x4C, 0x4D) => Weight = 5.0; - - public Lute(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (Weight == 3.0) - { - Weight = 5.0; - } - } - } + [Constructible] + public Lute() : base(0xEB3, 0x4C, 0x4D) => Weight = 5.0; } diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/Tambourine.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/Tambourine.cs index 97870d002..3e768b929 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/Tambourine.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/Tambourine.cs @@ -1,31 +1,10 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class Tambourine : BaseInstrument { - public class Tambourine : BaseInstrument - { - [Constructible] - public Tambourine() : base(0xE9D, 0x52, 0x53) => Weight = 1.0; - - public Tambourine(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (Weight == 2.0) - { - Weight = 1.0; - } - } - } + [Constructible] + public Tambourine() : base(0xE9D, 0x52, 0x53) => Weight = 1.0; } diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/TambourineTassel.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/TambourineTassel.cs index 54aeb33f0..7f4a5a951 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/TambourineTassel.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/TambourineTassel.cs @@ -1,31 +1,10 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class TambourineTassel : BaseInstrument { - public class TambourineTassel : BaseInstrument - { - [Constructible] - public TambourineTassel() : base(0xE9E, 0x52, 0x53) => Weight = 1.0; - - public TambourineTassel(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (Weight == 2.0) - { - Weight = 1.0; - } - } - } + [Constructible] + public TambourineTassel() : base(0xE9E, 0x52, 0x53) => Weight = 1.0; } diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/EggBomb.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/EggBomb.cs index 92340098c..d766555bb 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/EggBomb.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/EggBomb.cs @@ -1,80 +1,58 @@ +using ModernUO.Serialization; using Server.SkillHandlers; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class EggBomb : Item { - public class EggBomb : Item + [Constructible] + public EggBomb() : base(0x2808) { - [Constructible] - public EggBomb() : base(0x2808) + // Item ID should be 0x2809 - Temporary solution for clients 7.0.0.0 and up + Stackable = Core.ML; + Weight = 1.0; + } + + public override int LabelNumber => 1030249; + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) { - // Item ID should be 0x2809 - Temporary solution for clients 7.0.0.0 and up - Stackable = Core.ML; - Weight = 1.0; + // The item must be in your backpack to use it. + from.SendLocalizedMessage(1060640); } - - public EggBomb(Serial serial) : base(serial) + else if (from.Skills.Ninjitsu.Value < 50.0) { + // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. + from.SendLocalizedMessage(1063013, "50\tNinjitsu"); } - - public override int LabelNumber => 1030249; - - public override void OnDoubleClick(Mobile from) + else if (Core.TickCount - from.NextSkillTime < 0) { - if (!IsChildOf(from.Backpack)) - { - // The item must be in your backpack to use it. - from.SendLocalizedMessage(1060640); - } - else if (from.Skills.Ninjitsu.Value < 50.0) - { - // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. - from.SendLocalizedMessage(1063013, "50\tNinjitsu"); - } - else if (Core.TickCount - from.NextSkillTime < 0) - { - // You must wait a few seconds before you can use that item. - from.SendLocalizedMessage(1070772); - } - else if (from.Mana < 10) - { - // You don't have enough mana to do that. - from.SendLocalizedMessage(1049456); - } - else - { - Hiding.CombatOverride = true; - - if (from.UseSkill(SkillName.Hiding)) - { - from.Mana -= 10; - - from.FixedParticles(0x3709, 1, 30, 9904, 1108, 6, EffectLayer.RightFoot); - from.PlaySound(0x22F); - - Consume(); - } - - Hiding.CombatOverride = false; - } + // You must wait a few seconds before you can use that item. + from.SendLocalizedMessage(1070772); } - - public override void Serialize(IGenericWriter writer) + else if (from.Mana < 10) { - base.Serialize(writer); - - writer.Write(0); + // You don't have enough mana to do that. + from.SendLocalizedMessage(1049456); } - - public override void Deserialize(IGenericReader reader) + else { - base.Deserialize(reader); + Hiding.CombatOverride = true; - var version = reader.ReadInt(); - - if (ItemID == 0x2809) // Temporary solution for clients 7.0.0.0 and up + if (from.UseSkill(SkillName.Hiding)) { - ItemID = 0x2808; + from.Mana -= 10; + + from.FixedParticles(0x3709, 1, 30, 9904, 1108, 6, EffectLayer.RightFoot); + from.PlaySound(0x22F); + + Consume(); } + + Hiding.CombatOverride = false; } } } diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/Fukiya.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/Fukiya.cs index 73a46bebc..75b5ee33e 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/Fukiya.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/Fukiya.cs @@ -1,150 +1,92 @@ using System; using System.Collections.Generic; +using ModernUO.Serialization; using Server.ContextMenus; using Server.Mobiles; -namespace Server.Items +namespace Server.Items; + +[Flippable(0x27AA, 0x27F5)] +[SerializationGenerator(0, false)] +public partial class Fukiya : Item, INinjaWeapon { - [Flippable(0x27AA, 0x27F5)] - public class Fukiya : Item, INinjaWeapon + [InvalidateProperties] + [SerializableField(0)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private int _usesRemaining; + + [InvalidateProperties] + [SerializableField(1)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private Poison _poison; + + [InvalidateProperties] + [SerializableField(2)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private int _poisonCharges; + + [Constructible] + public Fukiya() : base(0x27AA) { - private Poison m_Poison; - private int m_PoisonCharges; + Weight = 4.0; + Layer = Layer.OneHanded; + } - private int m_UsesRemaining; + public virtual int WrongAmmoMessage => 1063329; // You can only load fukiya darts + public virtual int NoFreeHandMessage => 1063327; // You must have a free hand to use a fukiya. + public virtual int EmptyWeaponMessage => 1063325; // You have no fukiya darts! + public virtual int RecentlyUsedMessage => 1063326; // You are already using that fukiya. + public virtual int FullWeaponMessage => 1063330; // You can only load fukiya darts - [Constructible] - public Fukiya() : base(0x27AA) + public virtual int WeaponMinRange => 0; + public virtual int WeaponMaxRange => 6; + + public virtual int WeaponDamage => Utility.RandomMinMax(4, 6); + + public Type AmmoType => typeof(FukiyaDarts); + + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } + + public void AttackAnimation(Mobile from, Mobile to) + { + if (from.Body.IsHuman && !from.Mounted) { - Weight = 4.0; - Layer = Layer.OneHanded; + from.Animate(33, 2, 1, true, true, 0); } - public Fukiya(Serial serial) : base(serial) + from.PlaySound(0x223); + from.MovingEffect(to, 0x2804, 5, 0, false, false); + } + + public override void GetProperties(IPropertyList list) + { + base.GetProperties(list); + + list.Add(1060584, _usesRemaining); // uses remaining: ~1_val~ + + if (_poison != null && _poisonCharges > 0) { + list.Add(1062412 + _poison.Level, _poisonCharges); } + } - public virtual int WrongAmmoMessage => 1063329; // You can only load fukiya darts - public virtual int NoFreeHandMessage => 1063327; // You must have a free hand to use a fukiya. - public virtual int EmptyWeaponMessage => 1063325; // You have no fukiya darts! - public virtual int RecentlyUsedMessage => 1063326; // You are already using that fukiya. - public virtual int FullWeaponMessage => 1063330; // You can only load fukiya darts + public override void OnDoubleClick(Mobile from) + { + NinjaWeapon.AttemptShoot((PlayerMobile)from, this); + } - public virtual int WeaponMinRange => 0; - public virtual int WeaponMaxRange => 6; + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); - public virtual int WeaponDamage => Utility.RandomMinMax(4, 6); - - public Type AmmoType => typeof(FukiyaDarts); - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining + if (IsChildOf(from)) { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison - { - get => m_Poison; - set - { - m_Poison = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonCharges - { - get => m_PoisonCharges; - set - { - m_PoisonCharges = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - - public void AttackAnimation(Mobile from, Mobile to) - { - if (from.Body.IsHuman && !from.Mounted) - { - from.Animate(33, 2, 1, true, true, 0); - } - - from.PlaySound(0x223); - from.MovingEffect(to, 0x2804, 5, 0, false, false); - } - - public override void GetProperties(IPropertyList list) - { - base.GetProperties(list); - - list.Add(1060584, m_UsesRemaining); // uses remaining: ~1_val~ - - if (m_Poison != null && m_PoisonCharges > 0) - { - list.Add(1062412 + m_Poison.Level, m_PoisonCharges); - } - } - - public override void OnDoubleClick(Mobile from) - { - NinjaWeapon.AttemptShoot((PlayerMobile)from, this); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (IsChildOf(from)) - { - list.Add(new NinjaWeapon.LoadEntry(this, 6224)); - list.Add(new NinjaWeapon.UnloadEntry(this, 6225)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_UsesRemaining); - - writer.Write(m_Poison); - writer.Write(m_PoisonCharges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_UsesRemaining = reader.ReadInt(); - - m_Poison = reader.ReadPoison(); - m_PoisonCharges = reader.ReadInt(); - - break; - } - } + list.Add(new NinjaWeapon.LoadEntry(this, 6224)); + list.Add(new NinjaWeapon.UnloadEntry(this, 6225)); } } } diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/FukiyaDarts.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/FukiyaDarts.cs index e01b718f3..82a7950ee 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/FukiyaDarts.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/FukiyaDarts.cs @@ -1,120 +1,66 @@ using System; +using ModernUO.Serialization; using Server.Engines.Craft; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class FukiyaDarts : Item, ICraftable, INinjaAmmo { - public class FukiyaDarts : Item, ICraftable, INinjaAmmo + [InvalidateProperties] + [SerializableField(0)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private int _usesRemaining; + + [InvalidateProperties] + [SerializableField(1)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private Poison _poison; + + [InvalidateProperties] + [SerializableField(2)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private int _poisonCharges; + + [Constructible] + public FukiyaDarts(int amount = 1) : base(0x2806) { - private Poison m_Poison; - private int m_PoisonCharges; - private int m_UsesRemaining; + Weight = 1.0; + _usesRemaining = amount; + } - [Constructible] - public FukiyaDarts(int amount = 1) : base(0x2806) + public FukiyaDarts(Serial serial) : base(serial) + { + } + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + if (quality == 2) { - Weight = 1.0; - - m_UsesRemaining = amount; + UsesRemaining *= 2; } - public FukiyaDarts(Serial serial) : base(serial) + return quality; + } + + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } + + public override void GetProperties(IPropertyList list) + { + base.GetProperties(list); + + list.Add(1060584, _usesRemaining); // uses remaining: ~1_val~ + + if (_poison != null && _poisonCharges > 0) { - } - - public int OnCraft( - int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue - ) - { - if (quality == 2) - { - UsesRemaining *= 2; - } - - return quality; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison - { - get => m_Poison; - set - { - m_Poison = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonCharges - { - get => m_PoisonCharges; - set - { - m_PoisonCharges = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - - public override void GetProperties(IPropertyList list) - { - base.GetProperties(list); - - list.Add(1060584, m_UsesRemaining); // uses remaining: ~1_val~ - - if (m_Poison != null && m_PoisonCharges > 0) - { - list.Add(1062412 + m_Poison.Level, m_PoisonCharges); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_UsesRemaining); - - writer.Write(m_Poison); - writer.Write(m_PoisonCharges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_UsesRemaining = reader.ReadInt(); - - m_Poison = reader.ReadPoison(); - m_PoisonCharges = reader.ReadInt(); - - break; - } - } + list.Add(1062412 + _poison.Level, _poisonCharges); } } } diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/LeatherNinjaBelt.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/LeatherNinjaBelt.cs index acfebce0c..e9ba47270 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/LeatherNinjaBelt.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/LeatherNinjaBelt.cs @@ -1,163 +1,105 @@ using System; using System.Collections.Generic; +using ModernUO.Serialization; using Server.ContextMenus; using Server.Mobiles; -namespace Server.Items +namespace Server.Items; + +[Flippable(0x2790, 0x27DB)] +[SerializationGenerator(0, false)] +public partial class LeatherNinjaBelt : BaseWaist, INinjaWeapon { - [Flippable(0x2790, 0x27DB)] - public class LeatherNinjaBelt : BaseWaist, INinjaWeapon + [InvalidateProperties] + [SerializableField(0)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private int _usesRemaining; + + [InvalidateProperties] + [SerializableField(1)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private Poison _poison; + + [InvalidateProperties] + [SerializableField(2)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private int _poisonCharges; + + [Constructible] + public LeatherNinjaBelt() : base(0x2790) { - private Poison m_Poison; - private int m_PoisonCharges; + Weight = 1.0; + Layer = Layer.Waist; + } - private int m_UsesRemaining; + public override CraftResource DefaultResource => CraftResource.RegularLeather; - [Constructible] - public LeatherNinjaBelt() : base(0x2790) + public virtual int WrongAmmoMessage => 1063301; // You can only place shuriken in a ninja belt. + public virtual int NoFreeHandMessage => 1063299; // You must have a free hand to throw shuriken. + public virtual int EmptyWeaponMessage => 1063297; // You have no shuriken in your ninja belt! + public virtual int RecentlyUsedMessage => 1063298; // You cannot throw another shuriken yet. + public virtual int FullWeaponMessage => 1063302; // You cannot add any more shuriken. + + public virtual int WeaponMinRange => 2; + public virtual int WeaponMaxRange => 10; + + public virtual int WeaponDamage => Utility.RandomMinMax(3, 5); + + public virtual Type AmmoType => typeof(Shuriken); + + public bool ShowUsesRemaining + { + get => true; + set { } + } + + public void AttackAnimation(Mobile from, Mobile to) + { + if (from.Body.IsHuman) { - Weight = 1.0; - Layer = Layer.Waist; + from.Animate(from.Mounted ? 26 : 9, 7, 1, true, false, 0); } - public LeatherNinjaBelt(Serial serial) : base(serial) + from.PlaySound(0x23A); + from.MovingEffect(to, 0x27AC, 1, 0, false, false); + } + + public override void GetProperties(IPropertyList list) + { + base.GetProperties(list); + + list.Add(1060584, _usesRemaining); // uses remaining: ~1_val~ + + if (_poison != null && _poisonCharges > 0) { + list.Add(1062412 + _poison.Level, _poisonCharges); + } + } + + public override bool OnEquip(Mobile from) + { + if (base.OnEquip(from)) + { + from.SendLocalizedMessage(1070785); // Double click this item each time you wish to throw a shuriken. + return true; } - public override CraftResource DefaultResource => CraftResource.RegularLeather; + return false; + } - public virtual int WrongAmmoMessage => 1063301; // You can only place shuriken in a ninja belt. - public virtual int NoFreeHandMessage => 1063299; // You must have a free hand to throw shuriken. - public virtual int EmptyWeaponMessage => 1063297; // You have no shuriken in your ninja belt! - public virtual int RecentlyUsedMessage => 1063298; // You cannot throw another shuriken yet. - public virtual int FullWeaponMessage => 1063302; // You cannot add any more shuriken. + public override void OnDoubleClick(Mobile from) + { + NinjaWeapon.AttemptShoot((PlayerMobile)from, this); + } - public virtual int WeaponMinRange => 2; - public virtual int WeaponMaxRange => 10; + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); - public virtual int WeaponDamage => Utility.RandomMinMax(3, 5); - - public virtual Type AmmoType => typeof(Shuriken); - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining + if (IsChildOf(from)) { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison - { - get => m_Poison; - set - { - m_Poison = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonCharges - { - get => m_PoisonCharges; - set - { - m_PoisonCharges = value; - InvalidateProperties(); - } - } - - public bool ShowUsesRemaining - { - get => true; - set { } - } - - public void AttackAnimation(Mobile from, Mobile to) - { - if (from.Body.IsHuman) - { - from.Animate(from.Mounted ? 26 : 9, 7, 1, true, false, 0); - } - - from.PlaySound(0x23A); - from.MovingEffect(to, 0x27AC, 1, 0, false, false); - } - - public override void GetProperties(IPropertyList list) - { - base.GetProperties(list); - - list.Add(1060584, m_UsesRemaining); // uses remaining: ~1_val~ - - if (m_Poison != null && m_PoisonCharges > 0) - { - list.Add(1062412 + m_Poison.Level, m_PoisonCharges); - } - } - - public override bool OnEquip(Mobile from) - { - if (base.OnEquip(from)) - { - from.SendLocalizedMessage(1070785); // Double click this item each time you wish to throw a shuriken. - return true; - } - - return false; - } - - public override void OnDoubleClick(Mobile from) - { - NinjaWeapon.AttemptShoot((PlayerMobile)from, this); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (IsChildOf(from)) - { - list.Add(new NinjaWeapon.LoadEntry(this, 6222)); - list.Add(new NinjaWeapon.UnloadEntry(this, 6223)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_UsesRemaining); - - writer.Write(m_Poison); - writer.Write(m_PoisonCharges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_UsesRemaining = reader.ReadInt(); - - m_Poison = reader.ReadPoison(); - m_PoisonCharges = reader.ReadInt(); - - break; - } - } + list.Add(new NinjaWeapon.LoadEntry(this, 6222)); + list.Add(new NinjaWeapon.UnloadEntry(this, 6223)); } } } diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/NinjaWeapons.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/NinjaWeapons.cs index d3ff3f60d..5508d1e21 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/NinjaWeapons.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/NinjaWeapons.cs @@ -14,356 +14,355 @@ using Server.Utilities; * own serialization, due to the way these weapons were originaly coded. */ -namespace Server.Items +namespace Server.Items; + +public interface INinjaAmmo : IUsesRemaining { - public interface INinjaAmmo : IUsesRemaining + int PoisonCharges { get; set; } + Poison Poison { get; set; } +} + +public interface INinjaWeapon : IUsesRemaining +{ + int NoFreeHandMessage { get; } + int EmptyWeaponMessage { get; } + int RecentlyUsedMessage { get; } + int FullWeaponMessage { get; } + int WrongAmmoMessage { get; } + Type AmmoType { get; } + int PoisonCharges { get; set; } + Poison Poison { get; set; } + int WeaponDamage { get; } + int WeaponMinRange { get; } + int WeaponMaxRange { get; } + + void AttackAnimation(Mobile from, Mobile to); +} + +public static class NinjaWeapon +{ + private const int MaxUses = 10; + + public static void AttemptShoot(PlayerMobile from, INinjaWeapon weapon) { - int PoisonCharges { get; set; } - Poison Poison { get; set; } + if (CanUseWeapon(from, weapon)) + { + from.BeginTarget(weapon.WeaponMaxRange, false, TargetFlags.Harmful, OnTarget, weapon); + } } - public interface INinjaWeapon : IUsesRemaining + private static void Shoot(PlayerMobile from, Mobile target, INinjaWeapon weapon) { - int NoFreeHandMessage { get; } - int EmptyWeaponMessage { get; } - int RecentlyUsedMessage { get; } - int FullWeaponMessage { get; } - int WrongAmmoMessage { get; } - Type AmmoType { get; } - int PoisonCharges { get; set; } - Poison Poison { get; set; } - int WeaponDamage { get; } - int WeaponMinRange { get; } - int WeaponMaxRange { get; } + if (from == target || !CanUseWeapon(from, weapon) || !from.CanBeHarmful(target)) + { + return; + } - void AttackAnimation(Mobile from, Mobile to); + if (weapon.WeaponMinRange == 0 || !from.InRange(target, weapon.WeaponMinRange)) + { + from.NinjaWepCooldown = true; + + from.Direction = from.GetDirectionTo(target); + + from.RevealingAction(); + + weapon.AttackAnimation(from, target); + + ConsumeUse(weapon); + + if (CombatCheck(from, target)) + { + Timer.StartTimer(TimeSpan.FromSeconds(1.0), () => OnHit(from, target, weapon)); + } + + Timer.StartTimer(TimeSpan.FromSeconds(2.5), () => from.NinjaWepCooldown = false); + } + else + { + from.SendLocalizedMessage(1063303); // Your target is too close! + } } - public static class NinjaWeapon + private static void Unload(Mobile from, INinjaWeapon weapon) { - private const int MaxUses = 10; - - public static void AttemptShoot(PlayerMobile from, INinjaWeapon weapon) + if (weapon.UsesRemaining > 0) { - if (CanUseWeapon(from, weapon)) + var ammo = weapon.AmmoType.CreateInstance(weapon.UsesRemaining); + + if (ammo is INinjaAmmo ninaAmmo) { - from.BeginTarget(weapon.WeaponMaxRange, false, TargetFlags.Harmful, OnTarget, weapon); + ninaAmmo.Poison = weapon.Poison; + ninaAmmo.PoisonCharges = weapon.PoisonCharges; } + + from.AddToBackpack(ammo); + + weapon.UsesRemaining = 0; + weapon.PoisonCharges = 0; + weapon.Poison = null; } + } - private static void Shoot(PlayerMobile from, Mobile target, INinjaWeapon weapon) + private static void Reload(PlayerMobile from, INinjaWeapon weapon, INinjaAmmo ammo) + { + if (weapon.UsesRemaining < MaxUses) { - if (from == target || !CanUseWeapon(from, weapon) || !from.CanBeHarmful(target)) + var need = Math.Min(MaxUses - weapon.UsesRemaining, ammo.UsesRemaining); + + if (need > 0) { - return; - } - - if (weapon.WeaponMinRange == 0 || !from.InRange(target, weapon.WeaponMinRange)) - { - from.NinjaWepCooldown = true; - - from.Direction = from.GetDirectionTo(target); - - from.RevealingAction(); - - weapon.AttackAnimation(from, target); - - ConsumeUse(weapon); - - if (CombatCheck(from, target)) + if (weapon.Poison != null && (ammo.Poison == null || weapon.Poison.Level > ammo.Poison.Level)) { - Timer.StartTimer(TimeSpan.FromSeconds(1.0), () => OnHit(from, target, weapon)); + from.SendLocalizedMessage(1070767); // Loaded projectile is stronger, unload it first } + else + { + if (weapon.UsesRemaining > 0) + { + if (weapon.Poison == null && ammo.Poison != null + || weapon.Poison != null && ammo.Poison != null && weapon.Poison.Level != ammo.Poison.Level) + { + Unload(from, weapon); + need = Math.Min(MaxUses, ammo.UsesRemaining); + } + } - Timer.StartTimer(TimeSpan.FromSeconds(2.5), () => from.NinjaWepCooldown = false); - } - else - { - from.SendLocalizedMessage(1063303); // Your target is too close! - } + var poisonneeded = Math.Min(MaxUses - weapon.PoisonCharges, ammo.PoisonCharges); + + weapon.UsesRemaining += need; + weapon.PoisonCharges += poisonneeded; + + if (weapon.PoisonCharges > 0) + { + weapon.Poison = ammo.Poison; + } + + ammo.PoisonCharges -= poisonneeded; + ammo.UsesRemaining -= need; + + if (ammo.UsesRemaining < 1) + { + ((Item)ammo).Delete(); + } + else if (ammo.PoisonCharges < 1) + { + ammo.Poison = null; + } + } + } // "else" here would mean they targeted "ammo" with 0 uses. undefined behavior. } - - private static void Unload(Mobile from, INinjaWeapon weapon) + else { - if (weapon.UsesRemaining > 0) + from.SendLocalizedMessage(weapon.FullWeaponMessage); + } + } + + private static void ConsumeUse(INinjaWeapon weapon) + { + if (weapon.UsesRemaining > 0) + { + weapon.UsesRemaining--; + + if (weapon.UsesRemaining < 1) { - var ammo = weapon.AmmoType.CreateInstance(weapon.UsesRemaining); - - if (ammo is INinjaAmmo ninaAmmo) - { - ninaAmmo.Poison = weapon.Poison; - ninaAmmo.PoisonCharges = weapon.PoisonCharges; - } - - from.AddToBackpack(ammo); - - weapon.UsesRemaining = 0; weapon.PoisonCharges = 0; weapon.Poison = null; } } + } - private static void Reload(PlayerMobile from, INinjaWeapon weapon, INinjaAmmo ammo) - { - if (weapon.UsesRemaining < MaxUses) - { - var need = Math.Min(MaxUses - weapon.UsesRemaining, ammo.UsesRemaining); - - if (need > 0) - { - if (weapon.Poison != null && (ammo.Poison == null || weapon.Poison.Level > ammo.Poison.Level)) - { - from.SendLocalizedMessage(1070767); // Loaded projectile is stronger, unload it first - } - else - { - if (weapon.UsesRemaining > 0) - { - if (weapon.Poison == null && ammo.Poison != null - || weapon.Poison != null && ammo.Poison != null && weapon.Poison.Level != ammo.Poison.Level) - { - Unload(from, weapon); - need = Math.Min(MaxUses, ammo.UsesRemaining); - } - } - - var poisonneeded = Math.Min(MaxUses - weapon.PoisonCharges, ammo.PoisonCharges); - - weapon.UsesRemaining += need; - weapon.PoisonCharges += poisonneeded; - - if (weapon.PoisonCharges > 0) - { - weapon.Poison = ammo.Poison; - } - - ammo.PoisonCharges -= poisonneeded; - ammo.UsesRemaining -= need; - - if (ammo.UsesRemaining < 1) - { - ((Item)ammo).Delete(); - } - else if (ammo.PoisonCharges < 1) - { - ammo.Poison = null; - } - } - } // "else" here would mean they targeted "ammo" with 0 uses. undefined behavior. - } - else - { - from.SendLocalizedMessage(weapon.FullWeaponMessage); - } - } - - private static void ConsumeUse(INinjaWeapon weapon) + private static bool CanUseWeapon(PlayerMobile from, INinjaWeapon weapon) + { + if (WeaponIsValid(weapon, from)) { if (weapon.UsesRemaining > 0) { - weapon.UsesRemaining--; - - if (weapon.UsesRemaining < 1) + if (!from.NinjaWepCooldown) { - weapon.PoisonCharges = 0; - weapon.Poison = null; - } - } - } - - private static bool CanUseWeapon(PlayerMobile from, INinjaWeapon weapon) - { - if (WeaponIsValid(weapon, from)) - { - if (weapon.UsesRemaining > 0) - { - if (!from.NinjaWepCooldown) + if (BasePotion.HasFreeHand(from)) { - if (BasePotion.HasFreeHand(from)) - { - return true; - } - - from.SendLocalizedMessage(weapon.NoFreeHandMessage); - } - else - { - from.SendLocalizedMessage(weapon.RecentlyUsedMessage); + return true; } + + from.SendLocalizedMessage(weapon.NoFreeHandMessage); } else { - from.SendLocalizedMessage(weapon.EmptyWeaponMessage); + from.SendLocalizedMessage(weapon.RecentlyUsedMessage); } } - - return false; - } - - private static bool CombatCheck(Mobile attacker, Mobile defender) /* mod'd from baseweapon */ - { - var defWeapon = defender.Weapon as BaseWeapon; - - var atkSkill = defender.Skills.Ninjitsu; - // Skill defSkill = defender.Skills[defWeapon.Skill]; - - var atSkillValue = attacker.Skills.Ninjitsu.Value; - var defSkillValue = defWeapon?.GetDefendSkillValue(attacker, defender) ?? 0.0; - - if (defSkillValue <= -20.0) + else { - defSkillValue = -19.9; - } - - double attackValue = AosAttributes.GetValue(attacker, AosAttribute.AttackChance); - - attackValue += DivineFurySpell.GetAttackBonus(attacker); - - if (AnimalForm.UnderTransformation(attacker, typeof(GreyWolf)) || - AnimalForm.UnderTransformation(attacker, typeof(BakeKitsune))) - { - attackValue += 20; - } - - if (HitLower.IsUnderAttackEffect(attacker)) - { - attackValue -= 25; - } - - if (attackValue > 45) - { - attackValue = 45; - } - - attackValue = (atSkillValue + 20.0) * (100 + attackValue); - - double defenseValue = AosAttributes.GetValue(defender, AosAttribute.DefendChance); - - defenseValue -= DivineFurySpell.GetDefendMalus(defender); - - if (HitLower.IsUnderDefenseEffect(defender)) - { - defenseValue -= 25; - } - - var refBonus = 0; - - if (Block.GetBonus(defender, ref refBonus)) - { - defenseValue += refBonus; - } - - if (Discordance.GetEffect(attacker, ref refBonus)) - { - defenseValue -= refBonus; - } - - if (defenseValue > 45) - { - defenseValue = 45; - } - - defenseValue = (defSkillValue + 20.0) * (100 + defenseValue); - - var chance = attackValue / (defenseValue * 2.0); - - if (chance < 0.02) - { - chance = 0.02; - } - - return attacker.CheckSkill(atkSkill.SkillName, chance); - } - - private static void OnHit(Mobile from, Mobile target, INinjaWeapon weapon) - { - if (!from.CanBeHarmful(target)) - { - return; - } - - from.DoHarmful(target); - - AOS.Damage(target, from, weapon.WeaponDamage, 100, 0, 0, 0, 0); - - if (weapon.Poison != null && weapon.PoisonCharges > 0) - { - if (EvilOmenSpell.EndEffect(target)) - { - target.ApplyPoison(from, Poison.GetPoison(weapon.Poison.Level + 1)); - } - else - { - target.ApplyPoison(from, weapon.Poison); - } - - weapon.PoisonCharges--; - - if (weapon.PoisonCharges < 1) - { - weapon.Poison = null; - } + from.SendLocalizedMessage(weapon.EmptyWeaponMessage); } } - private static void OnTarget(Mobile from, object targeted, INinjaWeapon weapon) + return false; + } + + private static bool CombatCheck(Mobile attacker, Mobile defender) /* mod'd from baseweapon */ + { + var defWeapon = defender.Weapon as BaseWeapon; + + var atkSkill = defender.Skills.Ninjitsu; + // Skill defSkill = defender.Skills[defWeapon.Skill]; + + var atSkillValue = attacker.Skills.Ninjitsu.Value; + var defSkillValue = defWeapon?.GetDefendSkillValue(attacker, defender) ?? 0.0; + + if (defSkillValue <= -20.0) { - if (from is PlayerMobile player && WeaponIsValid(weapon, from)) - { - if (targeted is Mobile mobile) - { - Shoot(player, mobile, weapon); - } - else if (targeted.GetType() == weapon.AmmoType) - { - Reload(player, weapon, (INinjaAmmo)targeted); - } - else - { - player.SendLocalizedMessage(weapon.WrongAmmoMessage); - } - } + defSkillValue = -19.9; } - private static bool WeaponIsValid(INinjaWeapon weapon, Mobile from) => - weapon is Item item && !item.Deleted && item.RootParent == from; + double attackValue = AosAttributes.GetValue(attacker, AosAttribute.AttackChance); - public class LoadEntry : ContextMenuEntry + attackValue += DivineFurySpell.GetAttackBonus(attacker); + + if (AnimalForm.UnderTransformation(attacker, typeof(GreyWolf)) || + AnimalForm.UnderTransformation(attacker, typeof(BakeKitsune))) { - private readonly INinjaWeapon weapon; - - public LoadEntry(INinjaWeapon wep, int entry) - : base(entry, 0) => - weapon = wep; - - public override void OnClick() - { - if (WeaponIsValid(weapon, Owner.From)) - { - Owner.From.BeginTarget(10, false, TargetFlags.Harmful, OnTarget, weapon); - } - } + attackValue += 20; } - public class UnloadEntry : ContextMenuEntry + if (HitLower.IsUnderAttackEffect(attacker)) { - private readonly INinjaWeapon weapon; + attackValue -= 25; + } - public UnloadEntry(INinjaWeapon wep, int entry) - : base(entry, 0) + if (attackValue > 45) + { + attackValue = 45; + } + + attackValue = (atSkillValue + 20.0) * (100 + attackValue); + + double defenseValue = AosAttributes.GetValue(defender, AosAttribute.DefendChance); + + defenseValue -= DivineFurySpell.GetDefendMalus(defender); + + if (HitLower.IsUnderDefenseEffect(defender)) + { + defenseValue -= 25; + } + + var refBonus = 0; + + if (Block.GetBonus(defender, ref refBonus)) + { + defenseValue += refBonus; + } + + if (Discordance.GetEffect(attacker, ref refBonus)) + { + defenseValue -= refBonus; + } + + if (defenseValue > 45) + { + defenseValue = 45; + } + + defenseValue = (defSkillValue + 20.0) * (100 + defenseValue); + + var chance = attackValue / (defenseValue * 2.0); + + if (chance < 0.02) + { + chance = 0.02; + } + + return attacker.CheckSkill(atkSkill.SkillName, chance); + } + + private static void OnHit(Mobile from, Mobile target, INinjaWeapon weapon) + { + if (!from.CanBeHarmful(target)) + { + return; + } + + from.DoHarmful(target); + + AOS.Damage(target, from, weapon.WeaponDamage, 100, 0, 0, 0, 0); + + if (weapon.Poison != null && weapon.PoisonCharges > 0) + { + if (EvilOmenSpell.EndEffect(target)) { - weapon = wep; - - Enabled = weapon.UsesRemaining > 0; + target.ApplyPoison(from, Poison.GetPoison(weapon.Poison.Level + 1)); + } + else + { + target.ApplyPoison(from, weapon.Poison); } - public override void OnClick() + weapon.PoisonCharges--; + + if (weapon.PoisonCharges < 1) { - if (WeaponIsValid(weapon, Owner.From)) - { - Unload(Owner.From, weapon); - } + weapon.Poison = null; } } } -} + + private static void OnTarget(Mobile from, object targeted, INinjaWeapon weapon) + { + if (from is PlayerMobile player && WeaponIsValid(weapon, from)) + { + if (targeted is Mobile mobile) + { + Shoot(player, mobile, weapon); + } + else if (targeted.GetType() == weapon.AmmoType) + { + Reload(player, weapon, (INinjaAmmo)targeted); + } + else + { + player.SendLocalizedMessage(weapon.WrongAmmoMessage); + } + } + } + + private static bool WeaponIsValid(INinjaWeapon weapon, Mobile from) => + weapon is Item item && !item.Deleted && item.RootParent == from; + + public class LoadEntry : ContextMenuEntry + { + private readonly INinjaWeapon weapon; + + public LoadEntry(INinjaWeapon wep, int entry) + : base(entry, 0) => + weapon = wep; + + public override void OnClick() + { + if (WeaponIsValid(weapon, Owner.From)) + { + Owner.From.BeginTarget(10, false, TargetFlags.Harmful, OnTarget, weapon); + } + } + } + + public class UnloadEntry : ContextMenuEntry + { + private readonly INinjaWeapon weapon; + + public UnloadEntry(INinjaWeapon wep, int entry) + : base(entry, 0) + { + weapon = wep; + + Enabled = weapon.UsesRemaining > 0; + } + + public override void OnClick() + { + if (WeaponIsValid(weapon, Owner.From)) + { + Unload(Owner.From, weapon); + } + } + } +} \ No newline at end of file diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/Shuriken.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/Shuriken.cs index 3dfd81b6e..7739d03d8 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/Shuriken.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/Shuriken.cs @@ -1,121 +1,63 @@ using System; +using ModernUO.Serialization; using Server.Engines.Craft; -namespace Server.Items +namespace Server.Items; + +[Flippable(0x27AC, 0x27F7)] +[SerializationGenerator(0, false)] +public partial class Shuriken : Item, ICraftable, INinjaAmmo { - [Flippable(0x27AC, 0x27F7)] - public class Shuriken : Item, ICraftable, INinjaAmmo + [InvalidateProperties] + [SerializableField(0)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private int _usesRemaining; + + [InvalidateProperties] + [SerializableField(1)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private Poison _poison; + + [InvalidateProperties] + [SerializableField(2)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private int _poisonCharges; + + [Constructible] + public Shuriken(int amount = 1) : base(0x27AC) { - private Poison m_Poison; - private int m_PoisonCharges; - private int m_UsesRemaining; + Weight = 1.0; + _usesRemaining = amount; + } - [Constructible] - public Shuriken(int amount = 1) : base(0x27AC) + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + if (quality == 2) { - Weight = 1.0; - - m_UsesRemaining = amount; + UsesRemaining *= 2; } - public Shuriken(Serial serial) : base(serial) + return quality; + } + + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } + + public override void GetProperties(IPropertyList list) + { + base.GetProperties(list); + + list.Add(1060584, _usesRemaining); // uses remaining: ~1_val~ + + if (_poison != null && _poisonCharges > 0) { - } - - public int OnCraft( - int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue - ) - { - if (quality == 2) - { - UsesRemaining *= 2; - } - - return quality; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison - { - get => m_Poison; - set - { - m_Poison = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonCharges - { - get => m_PoisonCharges; - set - { - m_PoisonCharges = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - - public override void GetProperties(IPropertyList list) - { - base.GetProperties(list); - - list.Add(1060584, m_UsesRemaining); // uses remaining: ~1_val~ - - if (m_Poison != null && m_PoisonCharges > 0) - { - list.Add(1062412 + m_Poison.Level, m_PoisonCharges); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_UsesRemaining); - - writer.Write(m_Poison); - writer.Write(m_PoisonCharges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_UsesRemaining = reader.ReadInt(); - - m_Poison = reader.ReadPoison(); - m_PoisonCharges = reader.ReadInt(); - - break; - } - } + list.Add(1062412 + _poison.Level, _poisonCharges); } } } diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/SmokeBomb.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/SmokeBomb.cs index 9405d915a..7ea8c07bc 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/SmokeBomb.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/SmokeBomb.cs @@ -1,72 +1,55 @@ +using ModernUO.Serialization; using Server.SkillHandlers; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class SmokeBomb : Item { - public class SmokeBomb : Item + [Constructible] + public SmokeBomb() : base(0x2808) { - [Constructible] - public SmokeBomb() : base(0x2808) + Stackable = Core.ML; + Weight = 1.0; + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) { - Stackable = Core.ML; - Weight = 1.0; + // The item must be in your backpack to use it. + from.SendLocalizedMessage(1060640); } - - public SmokeBomb(Serial serial) : base(serial) + else if (from.Skills.Ninjitsu.Value < 50.0) { + // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. + from.SendLocalizedMessage(1063013, "50\tNinjitsu"); } - - public override void OnDoubleClick(Mobile from) + else if (Core.TickCount - from.NextSkillTime < 0) { - if (!IsChildOf(from.Backpack)) - { - // The item must be in your backpack to use it. - from.SendLocalizedMessage(1060640); - } - else if (from.Skills.Ninjitsu.Value < 50.0) - { - // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. - from.SendLocalizedMessage(1063013, "50\tNinjitsu"); - } - else if (Core.TickCount - from.NextSkillTime < 0) - { - // You must wait a few seconds before you can use that item. - from.SendLocalizedMessage(1070772); - } - else if (from.Mana < 10) - { - // You don't have enough mana to do that. - from.SendLocalizedMessage(1049456); - } - else - { - Hiding.CombatOverride = true; - - if (from.UseSkill(SkillName.Hiding)) - { - from.Mana -= 10; - - from.FixedParticles(0x3709, 1, 30, 9904, 1108, 6, EffectLayer.RightFoot); - from.PlaySound(0x22F); - - Consume(); - } - - Hiding.CombatOverride = false; - } + // You must wait a few seconds before you can use that item. + from.SendLocalizedMessage(1070772); } - - public override void Serialize(IGenericWriter writer) + else if (from.Mana < 10) { - base.Serialize(writer); - - writer.Write(0); + // You don't have enough mana to do that. + from.SendLocalizedMessage(1049456); } - - public override void Deserialize(IGenericReader reader) + else { - base.Deserialize(reader); + Hiding.CombatOverride = true; - var version = reader.ReadInt(); + if (from.UseSkill(SkillName.Hiding)) + { + from.Mana -= 10; + + from.FixedParticles(0x3709, 1, 30, 9904, 1108, 6, EffectLayer.RightFoot); + from.PlaySound(0x22F); + + Consume(); + } + + Hiding.CombatOverride = false; } } } diff --git a/Projects/UOContent/Items/Skill Items/Specialized/GlassblowingBook.cs b/Projects/UOContent/Items/Skill Items/Specialized/GlassblowingBook.cs index 92c1d2ed2..4ce98103d 100644 --- a/Projects/UOContent/Items/Skill Items/Specialized/GlassblowingBook.cs +++ b/Projects/UOContent/Items/Skill Items/Specialized/GlassblowingBook.cs @@ -1,54 +1,36 @@ +using ModernUO.Serialization; using Server.Mobiles; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class GlassblowingBook : Item { - public class GlassblowingBook : Item + [Constructible] + public GlassblowingBook() : base(0xFF4) => Weight = 1.0; + + public override int LabelNumber => 1153528; // Crafting glass with Glassblowing + + public override void OnDoubleClick(Mobile from) { - [Constructible] - public GlassblowingBook() : base(0xFF4) => Weight = 1.0; - - public GlassblowingBook(Serial serial) : base(serial) + if (!IsChildOf(from.Backpack)) { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. } - - public override string DefaultName => "Crafting Glass With Glassblowing"; - - public override void Serialize(IGenericWriter writer) + else if (from is not PlayerMobile pm || from.Skills.Alchemy.Base < 100.0) { - base.Serialize(writer); - - writer.Write(0); // version + from.SendLocalizedMessage(1080042); // Only a Grandmaster Alchemist can learn from this book. } - - public override void Deserialize(IGenericReader reader) + else if (pm.Glassblowing) { - base.Deserialize(reader); - - var version = reader.ReadInt(); + from.SendLocalizedMessage(1080066); // You have already learned this information. } - - public override void OnDoubleClick(Mobile from) + else { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from is not PlayerMobile pm || from.Skills.Alchemy.Base < 100.0) - { - from.SendMessage("Only a Grandmaster Alchemist can learn from this book."); - } - else if (pm.Glassblowing) - { - from.SendMessage("You have already learned this information."); - } - else - { - pm.Glassblowing = true; - from.SendMessage( - "You have learned to make items from glass. You will need to find miners to mine find sand for you to make these items." - ); - Delete(); - } + pm.Glassblowing = true; + // You have learned to make items from glass. You will need to find miners to mine fine sand for you to make these items. + from.SendLocalizedMessage(1111702); + Delete(); } } } diff --git a/Projects/UOContent/Items/Skill Items/Specialized/MasonryBook.cs b/Projects/UOContent/Items/Skill Items/Specialized/MasonryBook.cs index a97f1b5a1..57425ad2a 100644 --- a/Projects/UOContent/Items/Skill Items/Specialized/MasonryBook.cs +++ b/Projects/UOContent/Items/Skill Items/Specialized/MasonryBook.cs @@ -1,54 +1,36 @@ +using ModernUO.Serialization; using Server.Mobiles; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class MasonryBook : Item { - public class MasonryBook : Item + [Constructible] + public MasonryBook() : base(0xFBE) => Weight = 1.0; + + public override int LabelNumber => 1153527; // Making valuables with Stonecrafting + + public override void OnDoubleClick(Mobile from) { - [Constructible] - public MasonryBook() : base(0xFBE) => Weight = 1.0; - - public MasonryBook(Serial serial) : base(serial) + if (!IsChildOf(from.Backpack)) { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. } - - public override string DefaultName => "Making Valuables With Stonecrafting"; - - public override void Serialize(IGenericWriter writer) + else if (from is not PlayerMobile pm || from.Skills.Carpentry.Base < 100.0) { - base.Serialize(writer); - - writer.Write(0); // version + from.SendLocalizedMessage(1080043); // Only a Grandmaster Carpenter can learn from this book. } - - public override void Deserialize(IGenericReader reader) + else if (pm.Masonry) { - base.Deserialize(reader); - - var version = reader.ReadInt(); + from.SendLocalizedMessage(1080066); // You have already learned this information. } - - public override void OnDoubleClick(Mobile from) + else { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from is not PlayerMobile pm || from.Skills.Carpentry.Base < 100.0) - { - from.SendMessage("Only a Grandmaster Carpenter can learn from this book."); - } - else if (pm.Masonry) - { - from.SendMessage("You have already learned this information."); - } - else - { - pm.Masonry = true; - from.SendMessage( - "You have learned to make items from stone. You will need miners to gather stones for you to make these items." - ); - Delete(); - } + pm.Masonry = true; + // You have learned to make items from stone. You will need miners to gather stones for you to make these items. + from.SendLocalizedMessage(1080044); + Delete(); } } } diff --git a/Projects/UOContent/Items/Skill Items/Specialized/Sand.cs b/Projects/UOContent/Items/Skill Items/Specialized/Sand.cs index db0d5b29e..5824f8bb3 100644 --- a/Projects/UOContent/Items/Skill Items/Specialized/Sand.cs +++ b/Projects/UOContent/Items/Skill Items/Specialized/Sand.cs @@ -1,40 +1,19 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[Flippable(0x11EA, 0x11EB)] +[SerializationGenerator(0, false)] +public partial class Sand : Item, ICommodity { - [Flippable(0x11EA, 0x11EB)] - public class Sand : Item, ICommodity + [Constructible] + public Sand(int amount = 1) : base(0x11EA) { - [Constructible] - public Sand(int amount = 1) : base(0x11EA) - { - Stackable = Core.ML; - Weight = 1.0; - } - - public Sand(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1044626; // sand - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (version == 0 && Name == "sand") - { - Name = null; - } - } + Stackable = Core.ML; + Weight = 1.0; } + + public override int LabelNumber => 1044626; // sand + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; } diff --git a/Projects/UOContent/Items/Skill Items/Specialized/SandMiningBook.cs b/Projects/UOContent/Items/Skill Items/Specialized/SandMiningBook.cs index dd2f6b773..ec18441ea 100644 --- a/Projects/UOContent/Items/Skill Items/Specialized/SandMiningBook.cs +++ b/Projects/UOContent/Items/Skill Items/Specialized/SandMiningBook.cs @@ -1,54 +1,36 @@ +using ModernUO.Serialization; using Server.Mobiles; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class SandMiningBook : Item { - public class SandMiningBook : Item + [Constructible] + public SandMiningBook() : base(0xFF4) => Weight = 1.0; + public override int LabelNumber => 1153531; // Find Glass-Quality Sand + + public override void OnDoubleClick(Mobile from) { - [Constructible] - public SandMiningBook() : base(0xFF4) => Weight = 1.0; - - public SandMiningBook(Serial serial) : base(serial) + if (!IsChildOf(from.Backpack)) { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. } - - public override string DefaultName => "Find Glass-Quality Sand"; - - public override void Serialize(IGenericWriter writer) + else if (from is not PlayerMobile pm || from.Skills.Mining.Base < 100.0) { - base.Serialize(writer); - - writer.Write(0); // version + // Only a Grandmaster Miner can learn from this book. + from.SendLocalizedMessage(1080041); } - - public override void Deserialize(IGenericReader reader) + else if (pm.SandMining) { - base.Deserialize(reader); - - var version = reader.ReadInt(); + from.SendLocalizedMessage(1080066); // You have already learned this information. } - - public override void OnDoubleClick(Mobile from) + else { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from is not PlayerMobile pm || from.Skills.Mining.Base < 100.0) - { - from.SendMessage("Only a Grandmaster Miner can learn from this book."); - } - else if (pm.SandMining) - { - from.SendMessage("You have already learned this information."); - } - else - { - pm.SandMining = true; - from.SendMessage( - "You have learned how to mine fine sand. Target sand areas when mining to look for fine sand." - ); - Delete(); - } + pm.SandMining = true; + // You have learned to make items from glass. You will need to find miners to mine fine sand for you to make these items. + from.SendLocalizedMessage(1080065); + Delete(); } } } diff --git a/Projects/UOContent/Items/Skill Items/Specialized/StoneMiningBook.cs b/Projects/UOContent/Items/Skill Items/Specialized/StoneMiningBook.cs index 9ee89fc85..5af88288b 100644 --- a/Projects/UOContent/Items/Skill Items/Specialized/StoneMiningBook.cs +++ b/Projects/UOContent/Items/Skill Items/Specialized/StoneMiningBook.cs @@ -1,54 +1,38 @@ +using ModernUO.Serialization; using Server.Mobiles; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class StoneMiningBook : Item { - public class StoneMiningBook : Item + [Constructible] + public StoneMiningBook() : base(0xFBE) => Weight = 1.0; + + public override int LabelNumber => 1153530; // Mining For Quality Stone + + public override void OnDoubleClick(Mobile from) { - [Constructible] - public StoneMiningBook() : base(0xFBE) => Weight = 1.0; + var pm = from as PlayerMobile; - public StoneMiningBook(Serial serial) : base(serial) + if (!IsChildOf(from.Backpack)) { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. } - - public override string DefaultName => "Mining For Quality Stone"; - - public override void Serialize(IGenericWriter writer) + else if (pm == null || from.Skills.Mining.Base < 100.0) { - base.Serialize(writer); - - writer.Write(0); // version + from.SendLocalizedMessage(1080041); // Only a Grandmaster Miner can learn from this book. } - - public override void Deserialize(IGenericReader reader) + else if (pm.StoneMining) { - base.Deserialize(reader); - - var version = reader.ReadInt(); + from.SendLocalizedMessage(1080066); // You have already learned this information. } - - public override void OnDoubleClick(Mobile from) + else { - var pm = from as PlayerMobile; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (pm == null || from.Skills.Mining.Base < 100.0) - { - from.SendMessage("Only a Grandmaster Miner can learn from this book."); - } - else if (pm.StoneMining) - { - pm.SendMessage("You have already learned this knowledge."); - } - else - { - pm.StoneMining = true; - pm.SendMessage("You have learned to mine for stones. Target mountains when mining to find stones."); - Delete(); - } + pm.StoneMining = true; + // You have learned to mine for stones. Target mountains when mining to find stones. + pm.SendLocalizedMessage(1080045); + Delete(); } } } diff --git a/Projects/UOContent/Migrations/Server.Items.BambooFlute.v0.json b/Projects/UOContent/Migrations/Server.Items.BambooFlute.v0.json new file mode 100644 index 000000000..cd4b3f597 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.BambooFlute.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.BambooFlute" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.BaseInstrument.v4.json b/Projects/UOContent/Migrations/Server.Items.BaseInstrument.v4.json new file mode 100644 index 000000000..76584d701 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.BaseInstrument.v4.json @@ -0,0 +1,69 @@ +{ + "version": 4, + "type": "Server.Items.BaseInstrument", + "properties": [ + { + "name": "ReplenishesCharges", + "type": "bool", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "LastReplenished", + "type": "System.DateTime", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Crafter", + "type": "string", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Quality", + "type": "Server.Items.InstrumentQuality", + "rule": "EnumMigrationRule" + }, + { + "name": "Slayer", + "type": "Server.Items.SlayerName", + "rule": "EnumMigrationRule" + }, + { + "name": "Slayer2", + "type": "Server.Items.SlayerName", + "rule": "EnumMigrationRule" + }, + { + "name": "UsesRemaining", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "SuccessSound", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "FailureSound", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.Drums.v0.json b/Projects/UOContent/Migrations/Server.Items.Drums.v0.json new file mode 100644 index 000000000..fc0f7b3e3 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.Drums.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.Drums" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.EggBomb.v0.json b/Projects/UOContent/Migrations/Server.Items.EggBomb.v0.json new file mode 100644 index 000000000..7770c398c --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.EggBomb.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.EggBomb" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.Fukiya.v0.json b/Projects/UOContent/Migrations/Server.Items.Fukiya.v0.json new file mode 100644 index 000000000..55e8357aa --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.Fukiya.v0.json @@ -0,0 +1,30 @@ +{ + "version": 0, + "type": "Server.Items.Fukiya", + "properties": [ + { + "name": "UsesRemaining", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Poison", + "type": "Server.Poison", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "Poison" + ] + }, + { + "name": "PoisonCharges", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.FukiyaDarts.v0.json b/Projects/UOContent/Migrations/Server.Items.FukiyaDarts.v0.json new file mode 100644 index 000000000..dcae5e29b --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.FukiyaDarts.v0.json @@ -0,0 +1,30 @@ +{ + "version": 0, + "type": "Server.Items.FukiyaDarts", + "properties": [ + { + "name": "UsesRemaining", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Poison", + "type": "Server.Poison", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "Poison" + ] + }, + { + "name": "PoisonCharges", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.GlassblowingBook.v0.json b/Projects/UOContent/Migrations/Server.Items.GlassblowingBook.v0.json new file mode 100644 index 000000000..57401176a --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.GlassblowingBook.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.GlassblowingBook" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.Harp.v0.json b/Projects/UOContent/Migrations/Server.Items.Harp.v0.json new file mode 100644 index 000000000..d023af2b9 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.Harp.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.Harp" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.LapHarp.v0.json b/Projects/UOContent/Migrations/Server.Items.LapHarp.v0.json new file mode 100644 index 000000000..7e960b7b1 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.LapHarp.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.LapHarp" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.LeatherNinjaBelt.v0.json b/Projects/UOContent/Migrations/Server.Items.LeatherNinjaBelt.v0.json new file mode 100644 index 000000000..3f21e21d7 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.LeatherNinjaBelt.v0.json @@ -0,0 +1,30 @@ +{ + "version": 0, + "type": "Server.Items.LeatherNinjaBelt", + "properties": [ + { + "name": "UsesRemaining", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Poison", + "type": "Server.Poison", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "Poison" + ] + }, + { + "name": "PoisonCharges", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.Lute.v0.json b/Projects/UOContent/Migrations/Server.Items.Lute.v0.json new file mode 100644 index 000000000..caf5c6ac7 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.Lute.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.Lute" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.MasonryBook.v0.json b/Projects/UOContent/Migrations/Server.Items.MasonryBook.v0.json new file mode 100644 index 000000000..250c2462b --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.MasonryBook.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.MasonryBook" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.Sand.v0.json b/Projects/UOContent/Migrations/Server.Items.Sand.v0.json new file mode 100644 index 000000000..f985439a3 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.Sand.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.Sand" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.SandMiningBook.v0.json b/Projects/UOContent/Migrations/Server.Items.SandMiningBook.v0.json new file mode 100644 index 000000000..9703a3804 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.SandMiningBook.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.SandMiningBook" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.Shuriken.v0.json b/Projects/UOContent/Migrations/Server.Items.Shuriken.v0.json new file mode 100644 index 000000000..4c790a4e8 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.Shuriken.v0.json @@ -0,0 +1,30 @@ +{ + "version": 0, + "type": "Server.Items.Shuriken", + "properties": [ + { + "name": "UsesRemaining", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Poison", + "type": "Server.Poison", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "Poison" + ] + }, + { + "name": "PoisonCharges", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.SmokeBomb.v0.json b/Projects/UOContent/Migrations/Server.Items.SmokeBomb.v0.json new file mode 100644 index 000000000..4b7bdb9ce --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.SmokeBomb.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.SmokeBomb" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.StoneMiningBook.v0.json b/Projects/UOContent/Migrations/Server.Items.StoneMiningBook.v0.json new file mode 100644 index 000000000..beed3eb65 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.StoneMiningBook.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.StoneMiningBook" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.Tambourine.v0.json b/Projects/UOContent/Migrations/Server.Items.Tambourine.v0.json new file mode 100644 index 000000000..90165e7f4 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.Tambourine.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.Tambourine" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.TambourineTassel.v0.json b/Projects/UOContent/Migrations/Server.Items.TambourineTassel.v0.json new file mode 100644 index 000000000..6c85e3093 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.TambourineTassel.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.TambourineTassel" +} \ No newline at end of file