From 6820efe0ca6ace0afed353fbab5f33441687ba0b Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Tue, 5 Sep 2023 19:20:03 -0700 Subject: [PATCH] fix: Codegens and fixes bugs with plant system (#1490) --- .../UOContent/Engines/ConPVP/DuelContext.cs | 2 +- .../Engines/Plants/MiscItems/FertileDirt.cs | 38 +- .../Engines/Plants/MiscItems/GreenThorns.cs | 1416 ++++++++--------- .../Engines/Plants/MiscItems/OrangePetals.cs | 186 +-- .../Engines/Plants/MiscItems/RedLeaves.cs | 128 +- .../Plants/MiscMobiles/GiantIceWorm.cs | 100 +- .../UOContent/Engines/Plants/PlantBowl.cs | 307 ++-- .../UOContent/Engines/Plants/PlantItem.cs | 1259 +++++++-------- .../UOContent/Engines/Plants/PlantSystem.cs | 406 ++--- Projects/UOContent/Engines/Plants/Seed.cs | 415 +++-- .../Server.Engines.Plants.PlantBowl.v0.json | 4 + .../Server.Engines.Plants.PlantItem.v3.json | 48 + .../Server.Engines.Plants.PlantSystem.v3.json | 176 ++ .../Server.Engines.Plants.Seed.v3.json | 24 + .../Server.Items.FertileDirt.v0.json | 4 + .../Server.Items.GreenThorns.v0.json | 4 + ...rver.Items.GreenThornsSHTeleporter.v0.json | 4 + .../Server.Items.OrangePetals.v0.json | 4 + .../Migrations/Server.Items.RedLeaves.v0.json | 4 + .../Server.Mobiles.GiantIceWorm.v0.json | 4 + 20 files changed, 2305 insertions(+), 2228 deletions(-) create mode 100644 Projects/UOContent/Migrations/Server.Engines.Plants.PlantBowl.v0.json create mode 100644 Projects/UOContent/Migrations/Server.Engines.Plants.PlantItem.v3.json create mode 100644 Projects/UOContent/Migrations/Server.Engines.Plants.PlantSystem.v3.json create mode 100644 Projects/UOContent/Migrations/Server.Engines.Plants.Seed.v3.json create mode 100644 Projects/UOContent/Migrations/Server.Items.FertileDirt.v0.json create mode 100644 Projects/UOContent/Migrations/Server.Items.GreenThorns.v0.json create mode 100644 Projects/UOContent/Migrations/Server.Items.GreenThornsSHTeleporter.v0.json create mode 100644 Projects/UOContent/Migrations/Server.Items.OrangePetals.v0.json create mode 100644 Projects/UOContent/Migrations/Server.Items.RedLeaves.v0.json create mode 100644 Projects/UOContent/Migrations/Server.Mobiles.GiantIceWorm.v0.json diff --git a/Projects/UOContent/Engines/ConPVP/DuelContext.cs b/Projects/UOContent/Engines/ConPVP/DuelContext.cs index fac77dace..60b8f9e54 100644 --- a/Projects/UOContent/Engines/ConPVP/DuelContext.cs +++ b/Projects/UOContent/Engines/ConPVP/DuelContext.cs @@ -1836,7 +1836,7 @@ namespace Server.Engines.ConPVP mob.RemoveStatMod("Holy Bless"); mob.RemoveStatMod("Holy Curse"); - OrangePetals.RemoveContext(mob); + OrangePetals.RemoveEffect(mob); mob.Paralyzed = false; mob.Hidden = false; diff --git a/Projects/UOContent/Engines/Plants/MiscItems/FertileDirt.cs b/Projects/UOContent/Engines/Plants/MiscItems/FertileDirt.cs index b3d6d1580..311eae3f6 100644 --- a/Projects/UOContent/Engines/Plants/MiscItems/FertileDirt.cs +++ b/Projects/UOContent/Engines/Plants/MiscItems/FertileDirt.cs @@ -1,31 +1,15 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class FertileDirt : Item { - public class FertileDirt : Item + [Constructible] + public FertileDirt(int amount = 1) : base(0xF81) { - [Constructible] - public FertileDirt(int amount = 1) : base(0xF81) - { - Stackable = true; - Weight = 1.0; - Amount = amount; - } - - public FertileDirt(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(); - } + Stackable = true; + Weight = 1.0; + Amount = amount; } } diff --git a/Projects/UOContent/Engines/Plants/MiscItems/GreenThorns.cs b/Projects/UOContent/Engines/Plants/MiscItems/GreenThorns.cs index f4449d0cb..aea8e4d4b 100644 --- a/Projects/UOContent/Engines/Plants/MiscItems/GreenThorns.cs +++ b/Projects/UOContent/Engines/Plants/MiscItems/GreenThorns.cs @@ -1,30 +1,58 @@ using System; +using ModernUO.Serialization; using Server.Mobiles; using Server.Targeting; using Server.Utilities; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class GreenThorns : Item { - public class GreenThorns : Item + [Constructible] + public GreenThorns(int amount = 1) : base(0xF42) { - [Constructible] - public GreenThorns(int amount = 1) : base(0xF42) + Stackable = true; + Weight = 1.0; + Hue = 0x42; + Amount = amount; + } + + public override int LabelNumber => 1060837; // green thorns + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) { - Stackable = true; - Weight = 1.0; - Hue = 0x42; - Amount = amount; + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; } - public GreenThorns(Serial serial) : base(serial) + if (!from.CanBeginAction()) { + // * You must wait a while before planting another thorn. * + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061908); + return; } - public override int LabelNumber => 1060837; // green thorns + from.Target = new InternalTarget(this); + from.SendLocalizedMessage(1061906); // Choose a spot to plant the thorn. + } - public override void OnDoubleClick(Mobile from) + private class InternalTarget : Target + { + private readonly GreenThorns _thorn; + + public InternalTarget(GreenThorns thorn) : base(3, true, TargetFlags.None) => _thorn = thorn; + + protected override void OnTarget(Mobile from, object targeted) { - if (!IsChildOf(from.Backpack)) + if (_thorn.Deleted) + { + return; + } + + if (!_thorn.IsChildOf(from.Backpack)) { from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. return; @@ -37,743 +65,683 @@ namespace Server.Items return; } - from.Target = new InternalTarget(this); - from.SendLocalizedMessage(1061906); // Choose a spot to plant the thorn. - } - - 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(); - } - - private class InternalTarget : Target - { - private readonly GreenThorns m_Thorn; - - public InternalTarget(GreenThorns thorn) : base(3, true, TargetFlags.None) => m_Thorn = thorn; - - protected override void OnTarget(Mobile from, object targeted) + if (from.Map != Map.Trammel && from.Map != Map.Felucca) { - if (m_Thorn.Deleted) - { - return; - } + from.LocalOverheadMessage( + MessageType.Regular, + 0x2B2, + true, + "No solen lairs exist on this facet. Try again in Trammel or Felucca." + ); + return; + } - if (!m_Thorn.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } + if (targeted is not LandTarget land) + { + // * You cannot plant a green thorn there! * + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061912); + } + else + { + var effect = GreenThornsEffect.Create(from, land); - if (!from.CanBeginAction()) + if (effect == null) { - // * You must wait a while before planting another thorn. * - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061908); - return; - } - - if (from.Map != Map.Trammel && from.Map != Map.Felucca) - { - from.LocalOverheadMessage( - MessageType.Regular, - 0x2B2, - true, - "No solen lairs exist on this facet. Try again in Trammel or Felucca." - ); - return; - } - - if (targeted is not LandTarget land) - { - // * You cannot plant a green thorn there! * - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061912); + // * You sense it would be useless to plant a green thorn there. * + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061913); } else { - var effect = GreenThornsEffect.Create(from, land); + _thorn.Consume(); - if (effect == null) - { - // * You sense it would be useless to plant a green thorn there. * - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061913); - } - else - { - m_Thorn.Consume(); + // * You push the strange green thorn into the ground * + from.LocalOverheadMessage(MessageType.Emote, 0x961, 1061914); - // * You push the strange green thorn into the ground * - from.LocalOverheadMessage(MessageType.Emote, 0x961, 1061914); + // * ~1_PLAYER_NAME~ pushes a strange green thorn into the ground. * + from.NonlocalOverheadMessage(MessageType.Emote, 0x961, 1061915, from.Name); - // * ~1_PLAYER_NAME~ pushes a strange green thorn into the ground. * - from.NonlocalOverheadMessage(MessageType.Emote, 0x961, 1061915, from.Name); + from.BeginAction(); + new EndActionTimer(from).Start(); - from.BeginAction(); - new EndActionTimer(from).Start(); - - effect.Start(); - } + effect.Start(); } } - - protected override void OnTargetOutOfRange(Mobile from, object targeted) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502825); // That location is too far away - } } - private class EndActionTimer : Timer + protected override void OnTargetOutOfRange(Mobile from, object targeted) { - private readonly Mobile m_From; - - public EndActionTimer(Mobile from) : base(TimeSpan.FromMinutes(3.0)) - { - m_From = from; - } - - protected override void OnTick() - { - m_From.EndAction(); - } + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502825); // That location is too far away } } - public abstract class GreenThornsEffect : Timer + private class EndActionTimer : Timer { - private static readonly TilesAndEffect[] m_Table = + private readonly Mobile _from; + + public EndActionTimer(Mobile from) : base(TimeSpan.FromMinutes(3.0)) { - new( - new[] - { - 0x71, 0x7C, - 0x82, 0xA7, - 0xDC, 0xE3, - 0xE8, 0xEB, - 0x141, 0x144, - 0x14C, 0x14F, - 0x169, 0x174, - 0x1DC, 0x1E7, - 0x1EC, 0x1EF, - 0x272, 0x275, - 0x27E, 0x281, - 0x2D0, 0x2D7, - 0x2E5, 0x2FF, - 0x303, 0x31F, - 0x32C, 0x32F, - 0x33D, 0x340, - 0x345, 0x34C, - 0x355, 0x358, - 0x367, 0x36E, - 0x377, 0x37A, - 0x38D, 0x390, - 0x395, 0x39C, - 0x3A5, 0x3A8, - 0x3F6, 0x405, - 0x547, 0x54E, - 0x553, 0x556, - 0x597, 0x59E, - 0x623, 0x63A, - 0x6F3, 0x6FA, - 0x777, 0x791, - 0x79A, 0x7A9, - 0x7AE, 0x7B1 - }, - typeof(DirtGreenThornsEffect) - ), - - new( - new[] - { - 0x9, 0x15, - 0x150, 0x15C - }, - typeof(FurrowsGreenThornsEffect) - ), - - new( - new[] - { - 0x9C4, 0x9EB, - 0x3D65, 0x3D65, - 0x3DC0, 0x3DD9, - 0x3DDB, 0x3DDC, - 0x3DDE, 0x3EF0, - 0x3FF6, 0x3FF6, - 0x3FFC, 0x3FFE - }, - typeof(SwampGreenThornsEffect) - ), - - new( - new[] - { - 0x10C, 0x10F, - 0x114, 0x117, - 0x119, 0x11D, - 0x179, 0x18A, - 0x385, 0x38C, - 0x391, 0x394, - 0x39D, 0x3A4, - 0x3A9, 0x3AC, - 0x5BF, 0x5D6, - 0x5DF, 0x5E2, - 0x745, 0x748, - 0x751, 0x758, - 0x75D, 0x760, - 0x76D, 0x773 - }, - typeof(SnowGreenThornsEffect) - ), - - new( - new[] - { - 0x16, 0x3A, - 0x44, 0x4B, - 0x11E, 0x121, - 0x126, 0x12D, - 0x192, 0x192, - 0x1A8, 0x1AB, - 0x1B9, 0x1D1, - 0x282, 0x285, - 0x28A, 0x291, - 0x335, 0x33C, - 0x341, 0x344, - 0x34D, 0x354, - 0x359, 0x35C, - 0x3B7, 0x3BE, - 0x3C7, 0x3CA, - 0x5A7, 0x5B2, - 0x64B, 0x652, - 0x657, 0x65A, - 0x663, 0x66A, - 0x66F, 0x672, - 0x7BD, 0x7D0 - }, - typeof(SandGreenThornsEffect) - ) - }; - - private int m_Step; - - public GreenThornsEffect(Point3D location, Map map, Mobile from) : base(TimeSpan.FromSeconds(2.5)) - { - Location = location; - Map = map; - From = from; - } - - public Point3D Location { get; } - - public Map Map { get; } - - public Mobile From { get; } - - public static GreenThornsEffect Create(Mobile from, LandTarget land) - { - if (!from.Map.CanSpawnMobile(land.Location)) - { - return null; - } - - var tileID = land.TileID; - - foreach (var taep in m_Table) - { - for (var i = 0; i < taep.Tiles.Length; i += 2) - { - if (tileID >= taep.Tiles[i] && tileID <= taep.Tiles[i + 1]) - { - return taep.Effect.CreateInstance(land.Location, from.Map, from); - } - } - } - - return null; + _from = from; } protected override void OnTick() { - var nextDelay = Play(m_Step++); - - if (nextDelay > TimeSpan.Zero) - { - Delay = nextDelay; - - Start(); - } - } - - protected abstract TimeSpan Play(int step); - - protected bool SpawnItem(Item item) - { - for (var i = 0; i < 5; i++) // Try 5 times - { - var x = Location.X + Utility.RandomMinMax(-1, 1); - var y = Location.Y + Utility.RandomMinMax(-1, 1); - var z = Map.GetAverageZ(x, y); - - if (Map.CanFit(x, y, Location.Z, 1)) - { - item.MoveToWorld(new Point3D(x, y, Location.Z), Map); - return true; - } - - if (Map.CanFit(x, y, z, 1)) - { - item.MoveToWorld(new Point3D(x, y, z), Map); - return true; - } - } - - return false; - } - - protected bool SpawnCreature(BaseCreature creature) - { - for (var i = 0; i < 5; i++) // Try 5 times - { - var x = Location.X + Utility.RandomMinMax(-1, 1); - var y = Location.Y + Utility.RandomMinMax(-1, 1); - var z = Map.GetAverageZ(x, y); - - if (Map.CanSpawnMobile(x, y, Location.Z)) - { - creature.MoveToWorld(new Point3D(x, y, Location.Z), Map); - creature.Combatant = From; - return true; - } - - if (Map.CanSpawnMobile(x, y, z)) - { - creature.MoveToWorld(new Point3D(x, y, z), Map); - creature.Combatant = From; - return true; - } - } - - return false; - } - - private class TilesAndEffect - { - public TilesAndEffect(int[] tiles, Type effect) - { - Tiles = tiles; - Effect = effect; - } - - public int[] Tiles { get; } - - public Type Effect { get; } - } - } - - public class DirtGreenThornsEffect : GreenThornsEffect - { - public DirtGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) - { - } - - protected override TimeSpan Play(int step) - { - switch (step) - { - case 0: - { - Effects.PlaySound(Location, Map, 0x106); - Effects.SendLocationParticles( - EffectItem.Create(Location, Map, EffectItem.DefaultDuration), - 0x3735, - 1, - 182, - 0xBE3 - ); - - return TimeSpan.FromSeconds(4.0); - } - case 1: - { - Effects.PlaySound(Location, Map, 0x222); - - return TimeSpan.FromSeconds(4.0); - } - case 2: - { - Effects.PlaySound(Location, Map, 0x21F); - - return TimeSpan.FromSeconds(5.0); - } - case 3: - { - var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); - - // * The ground erupts with chaotic growth! * - dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114432); - - Effects.PlaySound(Location, Map, 0x12D); - - SpawnReagents(); - SpawnReagents(); - - return TimeSpan.FromSeconds(2.0); - } - case 4: - { - Effects.PlaySound(Location, Map, 0x12D); - - SpawnReagents(); - SpawnReagents(); - - return TimeSpan.FromSeconds(2.0); - } - case 5: - { - Effects.PlaySound(Location, Map, 0x12D); - - SpawnReagents(); - SpawnReagents(); - - return TimeSpan.FromSeconds(3.0); - } - default: - { - Effects.PlaySound(Location, Map, 0x12D); - - SpawnReagents(); - SpawnReagents(); - - return TimeSpan.Zero; - } - } - } - - private void SpawnReagents() - { - Item reagents; - var amount = Utility.RandomMinMax(10, 25); - - reagents = Utility.Random(9) switch - { - 0 => new BlackPearl(amount), - 1 => new Bloodmoss(amount), - 2 => new Garlic(amount), - 3 => new Ginseng(amount), - 4 => new MandrakeRoot(amount), - 5 => new Nightshade(amount), - 6 => new SulfurousAsh(amount), - 7 => new SpidersSilk(amount), - _ => new FertileDirt(amount) - }; - - if (!SpawnItem(reagents)) - { - reagents.Delete(); - } - } - } - - public class FurrowsGreenThornsEffect : GreenThornsEffect - { - public FurrowsGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) - { - } - - protected override TimeSpan Play(int step) - { - switch (step) - { - case 0: - { - Effects.PlaySound(Location, Map, 0x106); - Effects.SendLocationParticles( - EffectItem.Create(Location, Map, EffectItem.DefaultDuration), - 0x3735, - 1, - 182, - 0xBE3 - ); - - return TimeSpan.FromSeconds(4.0); - } - case 1: - { - var hole = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(10.0)); - hole.ItemID = 0x913; - - Effects.PlaySound(Location, Map, 0x222); - - return TimeSpan.FromSeconds(4.0); - } - case 2: - { - Effects.PlaySound(Location, Map, 0x21F); - - return TimeSpan.FromSeconds(4.0); - } - default: - { - var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); - // * A magical bunny leaps out of its hole, disturbed by the thorn's effect! * - dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114428); - - BaseCreature spawn = new VorpalBunny(); - if (!SpawnCreature(spawn)) - { - spawn.Delete(); - } - - return TimeSpan.Zero; - } - } - } - } - - public class SwampGreenThornsEffect : GreenThornsEffect - { - public SwampGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) - { - } - - protected override TimeSpan Play(int step) - { - switch (step) - { - case 0: - { - Effects.PlaySound(Location, Map, 0x106); - Effects.SendLocationParticles( - EffectItem.Create(Location, Map, EffectItem.DefaultDuration), - 0x3735, - 1, - 182, - 0xBE3 - ); - - return TimeSpan.FromSeconds(4.0); - } - case 1: - { - Effects.PlaySound(Location, Map, 0x222); - - return TimeSpan.FromSeconds(4.0); - } - case 2: - { - Effects.PlaySound(Location, Map, 0x21F); - - return TimeSpan.FromSeconds(1.0); - } - default: - { - var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); - - // * Strange green tendrils rise from the ground, whipping wildly! * - dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114429); - Effects.PlaySound(Location, Map, 0x2B0); - - BaseCreature spawn = new WhippingVine(); - if (!SpawnCreature(spawn)) - { - spawn.Delete(); - } - - return TimeSpan.Zero; - } - } - } - } - - public class SnowGreenThornsEffect : GreenThornsEffect - { - public SnowGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) - { - } - - protected override TimeSpan Play(int step) - { - switch (step) - { - case 0: - { - Effects.PlaySound(Location, Map, 0x106); - Effects.SendLocationParticles( - EffectItem.Create(Location, Map, EffectItem.DefaultDuration), - 0x3735, - 1, - 182, - 0xBE3 - ); - - return TimeSpan.FromSeconds(4.0); - } - case 1: - { - Effects.PlaySound(Location, Map, 0x222); - - return TimeSpan.FromSeconds(4.0); - } - case 2: - { - Effects.PlaySound(Location, Map, 0x21F); - - return TimeSpan.FromSeconds(4.0); - } - default: - { - var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); - - // * Slithering ice serpents rise to the surface to investigate the disturbance! * - dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114430); - - BaseCreature spawn = new GiantIceWorm(); - if (!SpawnCreature(spawn)) - { - spawn.Delete(); - } - - for (var i = 0; i < 3; i++) - { - BaseCreature snake = new IceSnake(); - if (!SpawnCreature(snake)) - { - snake.Delete(); - } - } - - return TimeSpan.Zero; - } - } - } - } - - public class SandGreenThornsEffect : GreenThornsEffect - { - public SandGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) - { - } - - protected override TimeSpan Play(int step) - { - switch (step) - { - case 0: - { - Effects.PlaySound(Location, Map, 0x106); - Effects.SendLocationParticles( - EffectItem.Create(Location, Map, EffectItem.DefaultDuration), - 0x3735, - 1, - 182, - 0xBE3 - ); - - return TimeSpan.FromSeconds(4.0); - } - case 1: - { - Effects.PlaySound(Location, Map, 0x222); - - return TimeSpan.FromSeconds(4.0); - } - case 2: - { - Effects.PlaySound(Location, Map, 0x21F); - - return TimeSpan.FromSeconds(5.0); - } - default: - { - var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); - - // * The sand collapses, revealing a dark hole. * - dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114431); - - GreenThornsSHTeleporter.Create(Location, Map); - - return TimeSpan.Zero; - } - } - } - } - - public class GreenThornsSHTeleporter : Item - { - public static readonly Point3D Destination = new(5738, 1856, 0); - - private GreenThornsSHTeleporter() : base(0x913) - { - Movable = false; - Hue = 0x1; - } - - public GreenThornsSHTeleporter(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a hole"; - - public static void Create(Point3D location, Map map) - { - var tele = new GreenThornsSHTeleporter(); - - tele.MoveToWorld(location, map); - - new InternalTimer(tele).Start(); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(this, 3)) - { - BaseCreature.TeleportPets(from, Destination, Map); - - from.Location = Destination; - } - else - { - from.SendLocalizedMessage(1019045); // I can't reach that. - } - } - - 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(); - - Delete(); - } - - private class InternalTimer : Timer - { - private readonly GreenThornsSHTeleporter m_Teleporter; - - public InternalTimer(GreenThornsSHTeleporter teleporter) : base(TimeSpan.FromMinutes(1.0)) - { - m_Teleporter = teleporter; - } - - protected override void OnTick() - { - m_Teleporter.Delete(); - } + _from.EndAction(); + } + } +} + +public abstract class GreenThornsEffect : Timer +{ + private static readonly TilesAndEffect[] _table = + { + new( + new[] + { + 0x71, 0x7C, + 0x82, 0xA7, + 0xDC, 0xE3, + 0xE8, 0xEB, + 0x141, 0x144, + 0x14C, 0x14F, + 0x169, 0x174, + 0x1DC, 0x1E7, + 0x1EC, 0x1EF, + 0x272, 0x275, + 0x27E, 0x281, + 0x2D0, 0x2D7, + 0x2E5, 0x2FF, + 0x303, 0x31F, + 0x32C, 0x32F, + 0x33D, 0x340, + 0x345, 0x34C, + 0x355, 0x358, + 0x367, 0x36E, + 0x377, 0x37A, + 0x38D, 0x390, + 0x395, 0x39C, + 0x3A5, 0x3A8, + 0x3F6, 0x405, + 0x547, 0x54E, + 0x553, 0x556, + 0x597, 0x59E, + 0x623, 0x63A, + 0x6F3, 0x6FA, + 0x777, 0x791, + 0x79A, 0x7A9, + 0x7AE, 0x7B1 + }, + typeof(DirtGreenThornsEffect) + ), + + new( + new[] + { + 0x9, 0x15, + 0x150, 0x15C + }, + typeof(FurrowsGreenThornsEffect) + ), + + new( + new[] + { + 0x9C4, 0x9EB, + 0x3D65, 0x3D65, + 0x3DC0, 0x3DD9, + 0x3DDB, 0x3DDC, + 0x3DDE, 0x3EF0, + 0x3FF6, 0x3FF6, + 0x3FFC, 0x3FFE + }, + typeof(SwampGreenThornsEffect) + ), + + new( + new[] + { + 0x10C, 0x10F, + 0x114, 0x117, + 0x119, 0x11D, + 0x179, 0x18A, + 0x385, 0x38C, + 0x391, 0x394, + 0x39D, 0x3A4, + 0x3A9, 0x3AC, + 0x5BF, 0x5D6, + 0x5DF, 0x5E2, + 0x745, 0x748, + 0x751, 0x758, + 0x75D, 0x760, + 0x76D, 0x773 + }, + typeof(SnowGreenThornsEffect) + ), + + new( + new[] + { + 0x16, 0x3A, + 0x44, 0x4B, + 0x11E, 0x121, + 0x126, 0x12D, + 0x192, 0x192, + 0x1A8, 0x1AB, + 0x1B9, 0x1D1, + 0x282, 0x285, + 0x28A, 0x291, + 0x335, 0x33C, + 0x341, 0x344, + 0x34D, 0x354, + 0x359, 0x35C, + 0x3B7, 0x3BE, + 0x3C7, 0x3CA, + 0x5A7, 0x5B2, + 0x64B, 0x652, + 0x657, 0x65A, + 0x663, 0x66A, + 0x66F, 0x672, + 0x7BD, 0x7D0 + }, + typeof(SandGreenThornsEffect) + ) + }; + + private int _step; + + public GreenThornsEffect(Point3D location, Map map, Mobile from) : base(TimeSpan.FromSeconds(2.5)) + { + Location = location; + Map = map; + From = from; + } + + public Point3D Location { get; } + + public Map Map { get; } + + public Mobile From { get; } + + public static GreenThornsEffect Create(Mobile from, LandTarget land) + { + if (!from.Map.CanSpawnMobile(land.Location)) + { + return null; + } + + var tileID = land.TileID; + + foreach (var taep in _table) + { + for (var i = 0; i < taep.Tiles.Length; i += 2) + { + if (tileID >= taep.Tiles[i] && tileID <= taep.Tiles[i + 1]) + { + return taep.Effect.CreateInstance(land.Location, from.Map, from); + } + } + } + + return null; + } + + protected override void OnTick() + { + var nextDelay = Play(_step++); + + if (nextDelay > TimeSpan.Zero) + { + Delay = nextDelay; + + Start(); + } + } + + protected abstract TimeSpan Play(int step); + + protected bool SpawnItem(Item item) + { + for (var i = 0; i < 5; i++) // Try 5 times + { + var x = Location.X + Utility.RandomMinMax(-1, 1); + var y = Location.Y + Utility.RandomMinMax(-1, 1); + var z = Map.GetAverageZ(x, y); + + if (Map.CanFit(x, y, Location.Z, 1)) + { + item.MoveToWorld(new Point3D(x, y, Location.Z), Map); + return true; + } + + if (Map.CanFit(x, y, z, 1)) + { + item.MoveToWorld(new Point3D(x, y, z), Map); + return true; + } + } + + return false; + } + + protected bool SpawnCreature(BaseCreature creature) + { + for (var i = 0; i < 5; i++) // Try 5 times + { + var x = Location.X + Utility.RandomMinMax(-1, 1); + var y = Location.Y + Utility.RandomMinMax(-1, 1); + var z = Map.GetAverageZ(x, y); + + if (Map.CanSpawnMobile(x, y, Location.Z)) + { + creature.MoveToWorld(new Point3D(x, y, Location.Z), Map); + creature.Combatant = From; + return true; + } + + if (Map.CanSpawnMobile(x, y, z)) + { + creature.MoveToWorld(new Point3D(x, y, z), Map); + creature.Combatant = From; + return true; + } + } + + return false; + } + + private class TilesAndEffect + { + public TilesAndEffect(int[] tiles, Type effect) + { + Tiles = tiles; + Effect = effect; + } + + public int[] Tiles { get; } + + public Type Effect { get; } + } +} + +public class DirtGreenThornsEffect : GreenThornsEffect +{ + public DirtGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) + { + } + + protected override TimeSpan Play(int step) + { + switch (step) + { + case 0: + { + Effects.PlaySound(Location, Map, 0x106); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3735, + 1, + 182, + 0xBE3 + ); + + return TimeSpan.FromSeconds(4.0); + } + case 1: + { + Effects.PlaySound(Location, Map, 0x222); + + return TimeSpan.FromSeconds(4.0); + } + case 2: + { + Effects.PlaySound(Location, Map, 0x21F); + + return TimeSpan.FromSeconds(5.0); + } + case 3: + { + var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); + + // * The ground erupts with chaotic growth! * + dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114432); + + Effects.PlaySound(Location, Map, 0x12D); + + SpawnReagents(); + SpawnReagents(); + + return TimeSpan.FromSeconds(2.0); + } + case 4: + { + Effects.PlaySound(Location, Map, 0x12D); + + SpawnReagents(); + SpawnReagents(); + + return TimeSpan.FromSeconds(2.0); + } + case 5: + { + Effects.PlaySound(Location, Map, 0x12D); + + SpawnReagents(); + SpawnReagents(); + + return TimeSpan.FromSeconds(3.0); + } + default: + { + Effects.PlaySound(Location, Map, 0x12D); + + SpawnReagents(); + SpawnReagents(); + + return TimeSpan.Zero; + } + } + } + + private void SpawnReagents() + { + Item reagents; + var amount = Utility.RandomMinMax(10, 25); + + reagents = Utility.Random(9) switch + { + 0 => new BlackPearl(amount), + 1 => new Bloodmoss(amount), + 2 => new Garlic(amount), + 3 => new Ginseng(amount), + 4 => new MandrakeRoot(amount), + 5 => new Nightshade(amount), + 6 => new SulfurousAsh(amount), + 7 => new SpidersSilk(amount), + _ => new FertileDirt(amount) + }; + + if (!SpawnItem(reagents)) + { + reagents.Delete(); + } + } +} + +public class FurrowsGreenThornsEffect : GreenThornsEffect +{ + public FurrowsGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) + { + } + + protected override TimeSpan Play(int step) + { + switch (step) + { + case 0: + { + Effects.PlaySound(Location, Map, 0x106); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3735, + 1, + 182, + 0xBE3 + ); + + return TimeSpan.FromSeconds(4.0); + } + case 1: + { + var hole = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(10.0)); + hole.ItemID = 0x913; + + Effects.PlaySound(Location, Map, 0x222); + + return TimeSpan.FromSeconds(4.0); + } + case 2: + { + Effects.PlaySound(Location, Map, 0x21F); + + return TimeSpan.FromSeconds(4.0); + } + default: + { + var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); + // * A magical bunny leaps out of its hole, disturbed by the thorn's effect! * + dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114428); + + BaseCreature spawn = new VorpalBunny(); + if (!SpawnCreature(spawn)) + { + spawn.Delete(); + } + + return TimeSpan.Zero; + } + } + } +} + +public class SwampGreenThornsEffect : GreenThornsEffect +{ + public SwampGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) + { + } + + protected override TimeSpan Play(int step) + { + switch (step) + { + case 0: + { + Effects.PlaySound(Location, Map, 0x106); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3735, + 1, + 182, + 0xBE3 + ); + + return TimeSpan.FromSeconds(4.0); + } + case 1: + { + Effects.PlaySound(Location, Map, 0x222); + + return TimeSpan.FromSeconds(4.0); + } + case 2: + { + Effects.PlaySound(Location, Map, 0x21F); + + return TimeSpan.FromSeconds(1.0); + } + default: + { + var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); + + // * Strange green tendrils rise from the ground, whipping wildly! * + dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114429); + Effects.PlaySound(Location, Map, 0x2B0); + + BaseCreature spawn = new WhippingVine(); + if (!SpawnCreature(spawn)) + { + spawn.Delete(); + } + + return TimeSpan.Zero; + } + } + } +} + +public class SnowGreenThornsEffect : GreenThornsEffect +{ + public SnowGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) + { + } + + protected override TimeSpan Play(int step) + { + switch (step) + { + case 0: + { + Effects.PlaySound(Location, Map, 0x106); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3735, + 1, + 182, + 0xBE3 + ); + + return TimeSpan.FromSeconds(4.0); + } + case 1: + { + Effects.PlaySound(Location, Map, 0x222); + + return TimeSpan.FromSeconds(4.0); + } + case 2: + { + Effects.PlaySound(Location, Map, 0x21F); + + return TimeSpan.FromSeconds(4.0); + } + default: + { + var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); + + // * Slithering ice serpents rise to the surface to investigate the disturbance! * + dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114430); + + BaseCreature spawn = new GiantIceWorm(); + if (!SpawnCreature(spawn)) + { + spawn.Delete(); + } + + for (var i = 0; i < 3; i++) + { + BaseCreature snake = new IceSnake(); + if (!SpawnCreature(snake)) + { + snake.Delete(); + } + } + + return TimeSpan.Zero; + } + } + } +} + +public class SandGreenThornsEffect : GreenThornsEffect +{ + public SandGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) + { + } + + protected override TimeSpan Play(int step) + { + switch (step) + { + case 0: + { + Effects.PlaySound(Location, Map, 0x106); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3735, + 1, + 182, + 0xBE3 + ); + + return TimeSpan.FromSeconds(4.0); + } + case 1: + { + Effects.PlaySound(Location, Map, 0x222); + + return TimeSpan.FromSeconds(4.0); + } + case 2: + { + Effects.PlaySound(Location, Map, 0x21F); + + return TimeSpan.FromSeconds(5.0); + } + default: + { + var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); + + // * The sand collapses, revealing a dark hole. * + dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114431); + + GreenThornsSHTeleporter.Create(Location, Map); + + return TimeSpan.Zero; + } + } + } +} + +[SerializationGenerator(0, false)] +public partial class GreenThornsSHTeleporter : Item +{ + private static readonly Point3D Destination = new(5738, 1856, 0); + + private GreenThornsSHTeleporter() : base(0x913) + { + Movable = false; + Hue = 0x1; + } + + public override string DefaultName => "a hole"; + + public static void Create(Point3D location, Map map) + { + var tele = new GreenThornsSHTeleporter(); + + tele.MoveToWorld(location, map); + + new InternalTimer(tele).Start(); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(this, 3)) + { + BaseCreature.TeleportPets(from, Destination, Map); + + from.Location = Destination; + } + else + { + from.SendLocalizedMessage(1019045); // I can't reach that. + } + } + + [AfterDeserialization(false)] + private void AfterDeserialization() + { + Delete(); + } + + private class InternalTimer : Timer + { + private readonly GreenThornsSHTeleporter _teleporter; + + public InternalTimer(GreenThornsSHTeleporter teleporter) : base(TimeSpan.FromMinutes(1.0)) => + _teleporter = teleporter; + + protected override void OnTick() + { + _teleporter.Delete(); } } } diff --git a/Projects/UOContent/Engines/Plants/MiscItems/OrangePetals.cs b/Projects/UOContent/Engines/Plants/MiscItems/OrangePetals.cs index 8e1b2c8b9..6e98bfa0c 100644 --- a/Projects/UOContent/Engines/Plants/MiscItems/OrangePetals.cs +++ b/Projects/UOContent/Engines/Plants/MiscItems/OrangePetals.cs @@ -1,133 +1,89 @@ using System; using System.Collections.Generic; +using ModernUO.Serialization; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class OrangePetals : Item { - public class OrangePetals : Item + private static readonly Dictionary _table = + new(); + + [Constructible] + public OrangePetals(int amount = 1) : base(0x1021) { - private static readonly Dictionary m_Table = - new(); + Stackable = true; + Hue = 0x2B; + Amount = amount; + } - [Constructible] - public OrangePetals(int amount = 1) : base(0x1021) + public override int LabelNumber => 1053122; // orange petals + + public override double DefaultWeight => 0.1; + + public override bool CheckItemUse(Mobile from, Item item) + { + if (item != this) { - Stackable = true; - Hue = 0x2B; - Amount = amount; - } - - public OrangePetals(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1053122; // orange petals - - public override double DefaultWeight => 0.1; - - public override bool CheckItemUse(Mobile from, Item item) - { - if (item != this) - { - return base.CheckItemUse(from, item); - } - - if (from != RootParent) - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - return false; - } - return base.CheckItemUse(from, item); } - public override void OnDoubleClick(Mobile from) + if (from != RootParent) { - var context = GetContext(from); + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + return false; + } - if (context != null) + return base.CheckItemUse(from, item); + } + + public override void OnDoubleClick(Mobile from) + { + if (UnderEffect(from)) + { + // * You already feel resilient! You decide to save the petal for later * + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061904); + return; + } + + // * You eat the orange petal. You feel more resilient! * + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061905); + from.PlaySound(0x3B); + + Timer timer = new OrangePetalsTimer(from); + timer.Start(); + + _table[from] = timer; + + Consume(); + } + + public static void RemoveEffect(Mobile m) + { + if (_table.Remove(m, out var timer)) + { + timer.Stop(); + } + } + + public static bool UnderEffect(Mobile m) => _table.ContainsKey(m); + + private class OrangePetalsTimer : Timer + { + private readonly Mobile _mobile; + + public OrangePetalsTimer(Mobile from) : base(TimeSpan.FromMinutes(5.0)) => _mobile = from; + + protected override void OnTick() + { + if (!_mobile.Deleted) { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061904); - return; + // * You feel the effects of your poison resistance wearing off * + _mobile.LocalOverheadMessage(MessageType.Regular, 0x3F, 1053091); } - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061905); - from.PlaySound(0x3B); - - Timer timer = new OrangePetalsTimer(from); - timer.Start(); - - AddContext(from, new OrangePetalsContext(timer)); - - Consume(); - } - - private static void AddContext(Mobile m, OrangePetalsContext context) - { - m_Table[m] = context; - } - - public static void RemoveContext(Mobile m) - { - var context = GetContext(m); - - if (context != null) - { - RemoveContext(m, context); - } - } - - private static void RemoveContext(Mobile m, OrangePetalsContext context) - { - m_Table.Remove(m); - - context.Timer.Stop(); - } - - private static OrangePetalsContext GetContext(Mobile m) - { - m_Table.TryGetValue(m, out var context); - return context; - } - - public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); - - 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(); - } - - private class OrangePetalsTimer : Timer - { - private readonly Mobile m_Mobile; - - public OrangePetalsTimer(Mobile from) : base(TimeSpan.FromMinutes(5.0)) => m_Mobile = from; - - protected override void OnTick() - { - if (!m_Mobile.Deleted) - { - // * You feel the effects of your poison resistance wearing off * - m_Mobile.LocalOverheadMessage(MessageType.Regular, 0x3F, 1053091); - } - - RemoveContext(m_Mobile); - } - } - - private class OrangePetalsContext - { - public OrangePetalsContext(Timer timer) => Timer = timer; - - public Timer Timer { get; } + RemoveEffect(_mobile); } } } diff --git a/Projects/UOContent/Engines/Plants/MiscItems/RedLeaves.cs b/Projects/UOContent/Engines/Plants/MiscItems/RedLeaves.cs index 75d161148..7174fe409 100644 --- a/Projects/UOContent/Engines/Plants/MiscItems/RedLeaves.cs +++ b/Projects/UOContent/Engines/Plants/MiscItems/RedLeaves.cs @@ -1,94 +1,72 @@ +using ModernUO.Serialization; using Server.Targeting; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class RedLeaves : Item { - public class RedLeaves : Item + [Constructible] + public RedLeaves(int amount = 1) : base(0x1E85) { - [Constructible] - public RedLeaves(int amount = 1) : base(0x1E85) + Stackable = true; + Hue = 0x21; + Amount = amount; + } + + public override int LabelNumber => 1053123; // red leaves + + public override double DefaultWeight => 0.1; + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) { - Stackable = true; - Hue = 0x21; - Amount = amount; + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; } - public RedLeaves(Serial serial) : base(serial) + from.Target = new InternalTarget(this); + from.SendLocalizedMessage(1061907); // Choose a book you wish to seal with the wax from the red leaf. + } + + private class InternalTarget : Target + { + private readonly RedLeaves _redLeaves; + + public InternalTarget(RedLeaves redLeaves) : base(3, false, TargetFlags.None) => _redLeaves = redLeaves; + + protected override void OnTarget(Mobile from, object targeted) { - } + if (_redLeaves.Deleted) + { + return; + } - public override int LabelNumber => 1053123; // red leaves - - public override double DefaultWeight => 0.1; - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) + if (!_redLeaves.IsChildOf(from.Backpack)) { from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. return; } - from.Target = new InternalTarget(this); - from.SendLocalizedMessage(1061907); // Choose a book you wish to seal with the wax from the red leaf. - } - - 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(); - } - - private class InternalTarget : Target - { - private readonly RedLeaves m_RedLeaves; - - public InternalTarget(RedLeaves redLeaves) : base(3, false, TargetFlags.None) => m_RedLeaves = redLeaves; - - protected override void OnTarget(Mobile from, object targeted) + if (targeted is not Item item || !item.IsChildOf(from.Backpack)) { - if (m_RedLeaves.Deleted) - { - return; - } + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + } + else if (item is not BaseBook book) + { + item.LabelTo(from, 1061911); // You can only use red leaves to seal the ink into book pages! + } + else if (!book.Writable) + { + book.LabelTo(from, 1061909); // The ink in this book has already been sealed. + } + else + { + _redLeaves.Consume(); + book.Writable = false; - if (!m_RedLeaves.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } - - if (targeted is not Item item || !item.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - } - else if (item is not BaseBook) - { - item.LabelTo(from, 1061911); // You can only use red leaves to seal the ink into book pages! - } - else - { - var book = (BaseBook)item; - - if (!book.Writable) - { - book.LabelTo(from, 1061909); // The ink in this book has already been sealed. - } - else - { - m_RedLeaves.Consume(); - book.Writable = false; - - book.LabelTo(from, 1061910); // You seal the ink to the page using wax from the red leaf. - } - } + book.LabelTo(from, 1061910); // You seal the ink to the page using wax from the red leaf. } } } diff --git a/Projects/UOContent/Engines/Plants/MiscMobiles/GiantIceWorm.cs b/Projects/UOContent/Engines/Plants/MiscMobiles/GiantIceWorm.cs index 8ba3969f7..b6b743f94 100644 --- a/Projects/UOContent/Engines/Plants/MiscMobiles/GiantIceWorm.cs +++ b/Projects/UOContent/Engines/Plants/MiscMobiles/GiantIceWorm.cs @@ -1,71 +1,55 @@ -namespace Server.Mobiles +using ModernUO.Serialization; + +namespace Server.Mobiles; + +[SerializationGenerator(0, false)] +public partial class GiantIceWorm : BaseCreature { - public class GiantIceWorm : BaseCreature + [Constructible] + public GiantIceWorm() : base(AIType.AI_Melee) { - [Constructible] - public GiantIceWorm() : base(AIType.AI_Melee) - { - Body = 89; - BaseSoundID = 0xDC; + Body = 89; + BaseSoundID = 0xDC; - SetStr(216, 245); - SetDex(76, 100); - SetInt(66, 85); + SetStr(216, 245); + SetDex(76, 100); + SetInt(66, 85); - SetHits(130, 147); + SetHits(130, 147); - SetDamage(7, 17); + SetDamage(7, 17); - SetDamageType(ResistanceType.Physical, 10); - SetDamageType(ResistanceType.Cold, 90); + SetDamageType(ResistanceType.Physical, 10); + SetDamageType(ResistanceType.Cold, 90); - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 0); - SetResistance(ResistanceType.Cold, 80, 90); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 0); + SetResistance(ResistanceType.Cold, 80, 90); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.Poisoning, 75.1, 95.0); - SetSkill(SkillName.MagicResist, 45.1, 60.0); - SetSkill(SkillName.Tactics, 75.1, 80.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.Poisoning, 75.1, 95.0); + SetSkill(SkillName.MagicResist, 45.1, 60.0); + SetSkill(SkillName.Tactics, 75.1, 80.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 4500; - Karma = -4500; + Fame = 4500; + Karma = -4500; - VirtualArmor = 40; + VirtualArmor = 40; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 71.1; - } - - public GiantIceWorm(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a giant ice worm corpse"; - public override bool SubdueBeforeTame => true; - public override string DefaultName => "a giant ice worm"; - - public override Poison PoisonImmune => Poison.Greater; - - public override Poison HitPoison => Poison.Greater; - - public override FoodType FavoriteFood => FoodType.Meat; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - } + Tamable = true; + ControlSlots = 1; + MinTameSkill = 71.1; } + + public override string CorpseName => "a giant ice worm corpse"; + public override bool SubdueBeforeTame => true; + public override string DefaultName => "a giant ice worm"; + + public override Poison PoisonImmune => Poison.Greater; + + public override Poison HitPoison => Poison.Greater; + + public override FoodType FavoriteFood => FoodType.Meat; } diff --git a/Projects/UOContent/Engines/Plants/PlantBowl.cs b/Projects/UOContent/Engines/Plants/PlantBowl.cs index 7c57a0f41..65489d385 100644 --- a/Projects/UOContent/Engines/Plants/PlantBowl.cs +++ b/Projects/UOContent/Engines/Plants/PlantBowl.cs @@ -1,190 +1,155 @@ +using ModernUO.Serialization; using Server.Items; using Server.Targeting; -namespace Server.Engines.Plants +namespace Server.Engines.Plants; + +[SerializationGenerator(0, false)] +public partial class PlantBowl : Item { - public class PlantBowl : Item + private static readonly int[] _dirtPatchLandTiles = { - private static readonly int[] _dirtPatchLandTiles = - { - 0x9, 0x15, - 0x71, 0x7C, - 0x82, 0xA7, - 0xDC, 0xE3, - 0xE8, 0xEB, - 0x141, 0x144, - 0x14C, 0x15C, - 0x169, 0x174, - 0x1DC, 0x1EF, - 0x272, 0x275, - 0x27E, 0x281, - 0x2D0, 0x2D7, - 0x2E5, 0x2FF, - 0x303, 0x31F, - 0x32C, 0x32F, - 0x33D, 0x340, - 0x345, 0x34C, - 0x355, 0x358, - 0x367, 0x36E, - 0x377, 0x37A, - 0x38D, 0x390, - 0x395, 0x39C, - 0x3A5, 0x3A8, - 0x3F6, 0x405, - 0x547, 0x54E, - 0x553, 0x556, - 0x597, 0x59E, - 0x623, 0x63A, - 0x6F3, 0x6FA, - 0x777, 0x791, - 0x79A, 0x7A9, - 0x7AE, 0x7B1, - 0x98C, 0x99F, - 0x9AC, 0x9BF, - 0x5B27, 0x5B3E, - 0x71F4, 0x71FB, - 0x72C9, 0x72CA - }; + 0x9, 0x15, + 0x71, 0x7C, + 0x82, 0xA7, + 0xDC, 0xE3, + 0xE8, 0xEB, + 0x141, 0x144, + 0x14C, 0x15C, + 0x169, 0x174, + 0x1DC, 0x1EF, + 0x272, 0x275, + 0x27E, 0x281, + 0x2D0, 0x2D7, + 0x2E5, 0x2FF, + 0x303, 0x31F, + 0x32C, 0x32F, + 0x33D, 0x340, + 0x345, 0x34C, + 0x355, 0x358, + 0x367, 0x36E, + 0x377, 0x37A, + 0x38D, 0x390, + 0x395, 0x39C, + 0x3A5, 0x3A8, + 0x3F6, 0x405, + 0x547, 0x54E, + 0x553, 0x556, + 0x597, 0x59E, + 0x623, 0x63A, + 0x6F3, 0x6FA, + 0x777, 0x791, + 0x79A, 0x7A9, + 0x7AE, 0x7B1, + 0x98C, 0x99F, + 0x9AC, 0x9BF, + 0x5B27, 0x5B3E, + 0x71F4, 0x71FB, + 0x72C9, 0x72CA + }; - private static readonly int[] _dirtPatchStaticTiles = - { - 0x1B27, 0x1B3E, - 0x31F4, 0x31FB, - 0x32C9, 0x32CA - }; + private static readonly int[] _dirtPatchStaticTiles = + { + 0x1B27, 0x1B3E, + 0x31F4, 0x31FB, + 0x32C9, 0x32CA + }; - [Constructible] - public PlantBowl() : base(0x15FD) => Weight = 1.0; + [Constructible] + public PlantBowl() : base(0x15FD) => Weight = 1.0; - public PlantBowl(Serial serial) : base(serial) + public override int LabelNumber => 1060834; // a plant bowl + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; } - public override int LabelNumber => 1060834; // a plant bowl + from.Target = new InternalTarget(this); + from.SendLocalizedMessage(1061897); // Choose a patch of dirt to scoop up. + } - public override void OnDoubleClick(Mobile from) + public static bool IsDirtPatch(object obj) + { + int tileID; + int[] tiles; + + if (obj is Static staticObj && !staticObj.Movable) { - if (!IsChildOf(from.Backpack)) + tileID = staticObj.ItemID; + tiles = _dirtPatchStaticTiles; + } + else if (obj is StaticTarget staticTarget) + { + tileID = staticTarget.ItemID; + tiles = _dirtPatchStaticTiles; + } + else if (obj is LandTarget landTarget) + { + tileID = landTarget.TileID; + tiles = _dirtPatchLandTiles; + } + else + { + return false; + } + + var contains = false; + + for (var i = 0; !contains && i < tiles.Length; i += 2) + { + contains = tileID >= tiles[i] && tileID <= tiles[i + 1]; + } + + return contains; + } + + private class InternalTarget : Target + { + private readonly PlantBowl _plantBowl; + + public InternalTarget(PlantBowl plantBowl) : base(3, true, TargetFlags.None) => _plantBowl = plantBowl; + + protected override void OnTarget(Mobile from, object targeted) + { + if (_plantBowl.Deleted) + { + return; + } + + if (!_plantBowl.IsChildOf(from.Backpack)) { from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. return; } - from.Target = new InternalTarget(this); - from.SendLocalizedMessage(1061897); // Choose a patch of dirt to scoop up. - } - - 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(); - } - - public static bool IsDirtPatch(object obj) - { - int tileID; - int[] tiles; - - if (obj is Static staticObj && !staticObj.Movable) + if (targeted is FertileDirt dirt) { - tileID = staticObj.ItemID; - tiles = _dirtPatchStaticTiles; - } - else if (obj is StaticTarget staticTarget) - { - tileID = staticTarget.ItemID; - tiles = _dirtPatchStaticTiles; - } - else if (obj is LandTarget landTarget) - { - tileID = landTarget.TileID; - tiles = _dirtPatchLandTiles; - } - else - { - return false; - } + var _dirtNeeded = Core.ML ? 20 : 40; - var contains = false; - - for (var i = 0; !contains && i < tiles.Length; i += 2) - { - contains = tileID >= tiles[i] && tileID <= tiles[i + 1]; - } - - return contains; - } - - private class InternalTarget : Target - { - private readonly PlantBowl m_PlantBowl; - - public InternalTarget(PlantBowl plantBowl) : base(3, true, TargetFlags.None) => m_PlantBowl = plantBowl; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_PlantBowl.Deleted) - { - return; - } - - if (!m_PlantBowl.IsChildOf(from.Backpack)) + if (!dirt.IsChildOf(from.Backpack)) { from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; } - - if (targeted is FertileDirt dirt) + else if (dirt.Amount < _dirtNeeded) { - var _dirtNeeded = Core.ML ? 20 : 40; - - if (!dirt.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - } - else if (dirt.Amount < _dirtNeeded) - { - // You need more dirt to fill a plant bowl! - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061896); - } - else - { - var fullBowl = new PlantItem(true); - - if (from.PlaceInBackpack(fullBowl)) - { - dirt.Consume(_dirtNeeded); - m_PlantBowl.Delete(); - - // You fill the bowl with fresh dirt. - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061895); - } - else - { - fullBowl.Delete(); - - // There is no room in your backpack for a bowl full of dirt! - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061894); - } - } + // You need more dirt to fill a plant bowl! + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061896); } - else if (IsDirtPatch(targeted)) + else { - var fullBowl = new PlantItem(); + var fullBowl = new PlantItem(true); if (from.PlaceInBackpack(fullBowl)) { - m_PlantBowl.Delete(); + dirt.Consume(_dirtNeeded); + _plantBowl.Delete(); - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061895); // You fill the bowl with fresh dirt. + // You fill the bowl with fresh dirt. + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061895); } else { @@ -194,17 +159,35 @@ namespace Server.Engines.Plants from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061894); } } + } + else if (IsDirtPatch(targeted)) + { + var fullBowl = new PlantItem(); + + if (from.PlaceInBackpack(fullBowl)) + { + _plantBowl.Delete(); + + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061895); // You fill the bowl with fresh dirt. + } else { - // You'll want to gather fresh dirt in order to raise a healthy plant! - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061893); + fullBowl.Delete(); + + // There is no room in your backpack for a bowl full of dirt! + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061894); } } - - protected override void OnTargetOutOfRange(Mobile from, object targeted) + else { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502825); // That location is too far away + // You'll want to gather fresh dirt in order to raise a healthy plant! + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061893); } } + + protected override void OnTargetOutOfRange(Mobile from, object targeted) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502825); // That location is too far away + } } } diff --git a/Projects/UOContent/Engines/Plants/PlantItem.cs b/Projects/UOContent/Engines/Plants/PlantItem.cs index 9ea7af85c..a37917d72 100644 --- a/Projects/UOContent/Engines/Plants/PlantItem.cs +++ b/Projects/UOContent/Engines/Plants/PlantItem.cs @@ -1,733 +1,706 @@ using System.Collections.Generic; +using ModernUO.Serialization; using Server.ContextMenus; using Server.Gumps; using Server.Items; using Server.Multis; using Server.Network; -namespace Server.Engines.Plants -{ - public enum PlantStatus - { - BowlOfDirt = 0, - Seed = 1, - Sapling = 2, - Plant = 4, - FullGrownPlant = 7, - DecorativePlant = 10, - DeadTwigs = 11, +namespace Server.Engines.Plants; - Stage1 = 1, - Stage2 = 2, - Stage3 = 3, - Stage4 = 4, - Stage5 = 5, - Stage6 = 6, - Stage7 = 7, - Stage8 = 8, - Stage9 = 9 +public enum PlantStatus +{ + BowlOfDirt = 0, + Seed = 1, + Sapling = 2, + Plant = 4, + FullGrownPlant = 7, + DecorativePlant = 10, + DeadTwigs = 11, + + Stage1 = 1, + Stage2 = 2, + Stage3 = 3, + Stage4 = 4, + Stage5 = 5, + Stage6 = 6, + Stage7 = 7, + Stage8 = 8, + Stage9 = 9 +} + +[SerializationGenerator(3, false)] +public partial class PlantItem : Item, ISecurable +{ + [SerializableField(0)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private SecureLevel _level; + + [SerializableFieldSaveFlag(0)] + private bool ShouldSerializeSecureLevel() => (int)_level != 0; + + [SerializableField(5, setter: "private")] + private PlantSystem _plantSystem; + + [SerializableFieldSaveFlag(5)] + private bool ShouldSerializePlantSystem() => _plantStatus != PlantStatus.DecorativePlant; + + // For clients older than 7.0.12.0 + private ObjectPropertyList _oldClientPropertyList; + + [Constructible] + public PlantItem(bool fertileDirt = false) : base(0x1602) + { + Weight = 1.0; + + _plantStatus = PlantStatus.BowlOfDirt; + _plantSystem = new PlantSystem(this) + { + FertileDirt = fertileDirt + }; + + _level = SecureLevel.Owner; + + Plants.Add(this); } - public class PlantItem : Item, ISecurable + public ObjectPropertyList OldClientPropertyList { - private PlantHue m_PlantHue; - private PlantStatus m_PlantStatus; - private PlantType m_PlantType; - private bool m_ShowType; - - // For clients older than 7.0.12.0 - private ObjectPropertyList _oldClientPropertyList; - - [Constructible] - public PlantItem(bool fertileDirt = false) : base(0x1602) + get { - Weight = 1.0; - - m_PlantStatus = PlantStatus.BowlOfDirt; - PlantSystem = new PlantSystem(this, fertileDirt); - Level = SecureLevel.Owner; - - Plants.Add(this); + InitializePropertyList(_oldClientPropertyList ??= new ObjectPropertyList(this)); + return _oldClientPropertyList; } + } - public PlantItem(Serial serial) : base(serial) + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + [CommandProperty(AccessLevel.GameMaster)] + [SerializableProperty(1)] + public PlantStatus PlantStatus + { + get => _plantStatus; + set { - } - - public PlantSystem PlantSystem { get; private set; } - - public ObjectPropertyList OldClientPropertyList - { - get + if (_plantStatus == value || value is < PlantStatus.BowlOfDirt or > PlantStatus.DeadTwigs) { - InitializePropertyList(_oldClientPropertyList ??= new ObjectPropertyList(this)); - return _oldClientPropertyList; + return; } - } - public override bool ForceShowProperties => ObjectPropertyList.Enabled; + var ratio = PlantSystem != null ? (double)PlantSystem.Hits / PlantSystem.MaxHits : 1.0; - [CommandProperty(AccessLevel.GameMaster)] - public PlantStatus PlantStatus - { - get => m_PlantStatus; - set + _plantStatus = value; + + if (_plantStatus >= PlantStatus.DecorativePlant) { - if (m_PlantStatus == value || value is < PlantStatus.BowlOfDirt or > PlantStatus.DeadTwigs) - { - return; - } - - double ratio; - if (PlantSystem != null) - { - ratio = (double)PlantSystem.Hits / PlantSystem.MaxHits; - } - else - { - ratio = 1.0; - } - - m_PlantStatus = value; - - if (m_PlantStatus >= PlantStatus.DecorativePlant) - { - PlantSystem = null; - } - else - { - PlantSystem ??= new PlantSystem(this, false); - - var hits = (int)(PlantSystem.MaxHits * ratio); - - if (hits == 0 && m_PlantStatus > PlantStatus.BowlOfDirt) - { - PlantSystem.Hits = 1; - } - else - { - PlantSystem.Hits = hits; - } - } - - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public PlantType PlantType - { - get => m_PlantType; - set - { - m_PlantType = value; - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public PlantHue PlantHue - { - get => m_PlantHue; - set - { - m_PlantHue = value; - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ShowType - { - get => m_ShowType; - set - { - m_ShowType = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ValidGrowthLocation - { - get - { - if (IsLockedDown && RootParent == null) - { - return true; - } - - if (RootParent is not Mobile owner) - { - return false; - } - - return IsChildOf(owner.Backpack) || IsChildOf(owner.FindBankNoCreate()); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsGrowable => m_PlantStatus >= PlantStatus.BowlOfDirt && m_PlantStatus <= PlantStatus.Stage9; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsCrossable => PlantHueInfo.IsCrossable(PlantHue) && PlantTypeInfo.IsCrossable(PlantType); - - [CommandProperty(AccessLevel.GameMaster)] - public bool Reproduces => PlantHueInfo.CanReproduce(PlantHue) && PlantTypeInfo.CanReproduce(PlantType); - - public static List Plants { get; } = new(); - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public override void OnSingleClick(Mobile from) - { - if (m_PlantStatus >= PlantStatus.DeadTwigs) - { - LabelTo(from, LabelNumber); - } - else if (m_PlantStatus >= PlantStatus.DecorativePlant) - { - LabelTo(from, 1061924); // a decorative plant - } - else if (m_PlantStatus >= PlantStatus.FullGrownPlant) - { - LabelTo(from, PlantTypeInfo.GetInfo(m_PlantType).Name); + PlantSystem = null; } else { - LabelTo(from, 1029913); // plant bowl + PlantSystem ??= new PlantSystem(this); + + var hits = (int)(PlantSystem.MaxHits * ratio); + + if (hits == 0 && _plantStatus > PlantStatus.BowlOfDirt) + { + PlantSystem.Hits = 1; + } + else + { + PlantSystem.Hits = hits; + } } + + Update(); } + } - public override void GetContextMenuEntries(Mobile from, List list) + [SerializableFieldSaveFlag(1)] + private bool ShouldSerializePlantStatus() => _plantStatus != PlantStatus.BowlOfDirt; + + [SerializableProperty(2)] + [CommandProperty(AccessLevel.GameMaster)] + public PlantType PlantType + { + get => _plantType; + set { - base.GetContextMenuEntries(from, list); - SetSecureLevelEntry.AddTo(from, this, list); + _plantType = value; + Update(); } + } - public int GetLocalizedPlantStatus() + [SerializableFieldSaveFlag(2)] + private bool ShouldSerializePlantType() => (int)_plantType != 0; + + [SerializableProperty(3)] + [CommandProperty(AccessLevel.GameMaster)] + public PlantHue PlantHue + { + get => _plantHue; + set { - return m_PlantStatus switch - { - >= PlantStatus.Plant => 1060812, // plant - >= PlantStatus.Sapling => 1023305, // sapling - >= PlantStatus.Seed => 1060810, // seed - _ => 1026951 // dirt - }; + _plantHue = value; + Update(); } + } - public int GetLocalizedContainerType() => 1150435; + [SerializableFieldSaveFlag(3)] + private bool ShouldSerializePlantHue() => _plantHue != PlantHue.None; - private void Update() + [SerializableProperty(4)] + [CommandProperty(AccessLevel.GameMaster)] + public bool ShowType + { + get => _showType; + set { - if (m_PlantStatus >= PlantStatus.DeadTwigs) - { - ItemID = 0x1B9D; - Hue = PlantHueInfo.GetInfo(m_PlantHue).Hue; - } - else if (m_PlantStatus >= PlantStatus.FullGrownPlant) - { - ItemID = PlantTypeInfo.GetInfo(m_PlantType).ItemID; - Hue = PlantHueInfo.GetInfo(m_PlantHue).Hue; - } - else if (m_PlantStatus >= PlantStatus.Plant) - { - ItemID = 0x1600; - Hue = 0; - } - else - { - ItemID = 0x1602; - Hue = 0; - } - + _showType = value; InvalidateProperties(); + this.MarkDirty(); } + } - private void InitializePropertyList(ObjectPropertyList list) - { - GetProperties(list); - AppendChildProperties(list); - list.Terminate(); - } + [SerializableFieldSaveFlag(4)] + private bool ShouldSerializeShowType() => _showType; - // Overridden to support new and old client localization - public override void SendOPLPacketTo(NetState ns) + [CommandProperty(AccessLevel.GameMaster)] + public bool ValidGrowthLocation + { + get { - if (!ObjectPropertyList.Enabled) + if (IsLockedDown && RootParent == null) { - return; + return true; } - if (ns.Version < ClientVersion.Version70120) + if (RootParent is not Mobile owner) { - ns.SendOPLInfo(Serial, OldClientPropertyList.Hash); - return; + return false; } - ns.SendOPLInfo(this); + return IsChildOf(owner.Backpack) || IsChildOf(owner.FindBankNoCreate()); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsGrowable => _plantStatus >= PlantStatus.BowlOfDirt && _plantStatus <= PlantStatus.Stage9; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsCrossable => PlantHueInfo.IsCrossable(PlantHue) && PlantTypeInfo.IsCrossable(PlantType); + + [CommandProperty(AccessLevel.GameMaster)] + public bool Reproduces => PlantHueInfo.CanReproduce(PlantHue) && PlantTypeInfo.CanReproduce(PlantType); + + public static List Plants { get; } = new(); + + public override void OnSingleClick(Mobile from) + { + if (_plantStatus >= PlantStatus.DeadTwigs) + { + LabelTo(from, LabelNumber); + } + else if (_plantStatus >= PlantStatus.DecorativePlant) + { + LabelTo(from, 1061924); // a decorative plant + } + else if (_plantStatus >= PlantStatus.FullGrownPlant) + { + LabelTo(from, PlantTypeInfo.GetInfo(_plantType).Name); + } + else + { + LabelTo(from, 1029913); // plant bowl + } + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + SetSecureLevelEntry.AddTo(from, this, list); + } + + public int GetLocalizedPlantStatus() + { + return _plantStatus switch + { + >= PlantStatus.Plant => 1060812, // plant + >= PlantStatus.Sapling => 1023305, // sapling + >= PlantStatus.Seed => 1060810, // seed + _ => 1026951 // dirt + }; + } + + public int GetLocalizedContainerType() => 1150435; + + private void Update() + { + if (_plantStatus >= PlantStatus.DeadTwigs) + { + ItemID = 0x1B9D; + Hue = PlantHueInfo.GetInfo(_plantHue).Hue; + } + else if (_plantStatus >= PlantStatus.FullGrownPlant) + { + ItemID = PlantTypeInfo.GetInfo(_plantType).ItemID; + Hue = PlantHueInfo.GetInfo(_plantHue).Hue; + } + else if (_plantStatus >= PlantStatus.Plant) + { + ItemID = 0x1600; + Hue = 0; + } + else + { + ItemID = 0x1602; + Hue = 0; } - public override void SendPropertiesTo(NetState ns) - { - if (ns?.Version < ClientVersion.Version70120) - { - ns?.Send(OldClientPropertyList.Buffer); - return; - } + InvalidateProperties(); + this.MarkDirty(); + } - ns?.Send(PropertyList.Buffer); + private void InitializePropertyList(ObjectPropertyList list) + { + GetProperties(list); + AppendChildProperties(list); + list.Terminate(); + } + + // Overridden to support new and old client localization + public override void SendOPLPacketTo(NetState ns) + { + if (!ObjectPropertyList.Enabled) + { + return; } - public override void ClearProperties() + if (ns.Version < ClientVersion.Version70120) { - base.ClearProperties(); - _oldClientPropertyList = null; + ns.SendOPLInfo(Serial, OldClientPropertyList.Hash); + return; } - public override void InvalidateProperties() + ns.SendOPLInfo(this); + } + + public override void SendPropertiesTo(NetState ns) + { + if (ns?.Version < ClientVersion.Version70120) { - base.InvalidateProperties(); + ns?.Send(OldClientPropertyList.Buffer); + return; + } - if (!ObjectPropertyList.Enabled) + ns?.Send(PropertyList.Buffer); + } + + public override void ClearProperties() + { + base.ClearProperties(); + _oldClientPropertyList = null; + } + + public override void InvalidateProperties() + { + base.InvalidateProperties(); + + if (!ObjectPropertyList.Enabled) + { + return; + } + + if (Map != null && Map != Map.Internal && !World.Loading) + { + int? oldHash; + int newHash; + if (_oldClientPropertyList != null) { - return; - } - - if (Map != null && Map != Map.Internal && !World.Loading) - { - int? oldHash; - int newHash; - if (_oldClientPropertyList != null) - { - oldHash = _oldClientPropertyList.Hash; - _oldClientPropertyList.Reset(); - InitializePropertyList(_oldClientPropertyList); - newHash = _oldClientPropertyList.Hash; - } - else - { - oldHash = null; - newHash = OldClientPropertyList.Hash; - } - - if (oldHash != newHash) - { - Delta(ItemDelta.Properties); - } + oldHash = _oldClientPropertyList.Hash; + _oldClientPropertyList.Reset(); + InitializePropertyList(_oldClientPropertyList); + newHash = _oldClientPropertyList.Hash; } else { - ClearProperties(); + oldHash = null; + newHash = OldClientPropertyList.Hash; + } + + if (oldHash != newHash) + { + Delta(ItemDelta.Properties); } } - - public override void OnAosSingleClick(Mobile from) + else { - var ns = from?.NetState; + ClearProperties(); + } + } - if (ns == null) - { - return; - } + public override void OnAosSingleClick(Mobile from) + { + var ns = from?.NetState; - var opl = ns.Version < ClientVersion.Version70120 ? OldClientPropertyList : PropertyList; - - if (opl.Header > 0) - { - from.NetState.SendMessageLocalized( - Serial, - ItemID, - MessageType.Label, - 0x3B2, - 3, - opl.Header, - Name, - opl.HeaderArgs - ); - } + if (ns == null) + { + return; } - public override void GetProperties(IPropertyList list) + var opl = ns.Version < ClientVersion.Version70120 ? OldClientPropertyList : PropertyList; + + if (opl.Header > 0) { - if (m_PlantStatus >= PlantStatus.DeadTwigs) + from.NetState.SendMessageLocalized( + Serial, + ItemID, + MessageType.Label, + 0x3B2, + 3, + opl.Header, + Name, + opl.HeaderArgs + ); + } + } + + public override void GetProperties(IPropertyList list) + { + if (_plantStatus >= PlantStatus.DeadTwigs) + { + base.GetProperties(list); + return; + } + + var typeInfo = PlantTypeInfo.GetInfo(_plantType); + var hueInfo = PlantHueInfo.GetInfo(_plantHue); + + if (_plantStatus >= PlantStatus.DecorativePlant) + { + list.Add(typeInfo.GetPlantLabelDecorative(hueInfo), $"{hueInfo.Name:#}\t{typeInfo.Name:#}"); + return; + } + + var container = GetLocalizedContainerType(); + var dirt = PlantSystem.GetLocalizedDirtStatus(); + var health = PlantSystem.GetLocalizedHealth(); + var plantStatus = GetLocalizedPlantStatus(); + + if (_plantStatus < PlantStatus.Seed) + { + // Clients above 7.0.12.0 use the regular PropertyList + if (list != _oldClientPropertyList) { - base.GetProperties(list); - return; + // a ~1_val~ of ~2_val~ dirt + list.Add(1060830, $"{container:#}\t{dirt:#}"); + } + else + { + // a ~1_val~ of ~2_val~ dirt + list.Add(1060830, $"{dirt:#}"); } - var typeInfo = PlantTypeInfo.GetInfo(m_PlantType); - var hueInfo = PlantHueInfo.GetInfo(m_PlantHue); + return; + } - if (m_PlantStatus >= PlantStatus.DecorativePlant) - { - list.Add(typeInfo.GetPlantLabelDecorative(hueInfo), $"{hueInfo.Name:#}\t{typeInfo.Name:#}"); - return; - } + if (_plantStatus >= PlantStatus.FullGrownPlant) + { + list.Add( + typeInfo.GetPlantLabelFullGrown(hueInfo), + $"{health:#}\t{hueInfo.Name:#}\t{typeInfo.Name:#}" + ); + return; + } - var container = GetLocalizedContainerType(); - var dirt = PlantSystem.GetLocalizedDirtStatus(); - var health = PlantSystem.GetLocalizedHealth(); - var plantStatus = GetLocalizedPlantStatus(); + if (_showType) + { + var plantNumber = _plantStatus == PlantStatus.Plant + ? typeInfo.GetPlantLabelPlant(hueInfo) + : typeInfo.GetPlantLabelSeed(hueInfo); - if (m_PlantStatus < PlantStatus.Seed) - { - // Clients above 7.0.12.0 use the regular PropertyList - if (list != _oldClientPropertyList) - { - // a ~1_val~ of ~2_val~ dirt - list.Add(1060830, $"{container:#}\t{dirt:#}"); - } - else - { - // a ~1_val~ of ~2_val~ dirt - list.Add(1060830, $"{dirt:#}"); - } - - return; - } - - if (m_PlantStatus >= PlantStatus.FullGrownPlant) + if (list != _oldClientPropertyList) { list.Add( - typeInfo.GetPlantLabelFullGrown(hueInfo), - $"{health:#}\t{hueInfo.Name:#}\t{typeInfo.Name:#}" + plantNumber, + $"{container:#}\t{dirt:#}\t{health:#}\t{hueInfo.Name:#}\t{typeInfo.Name:#}\t{plantStatus:#}" ); - return; - } - - if (m_ShowType) - { - var plantNumber = m_PlantStatus == PlantStatus.Plant - ? typeInfo.GetPlantLabelPlant(hueInfo) - : typeInfo.GetPlantLabelSeed(hueInfo); - - if (list != _oldClientPropertyList) - { - list.Add( - plantNumber, - $"{container:#}\t{dirt:#}\t{health:#}\t{hueInfo.Name:#}\t{typeInfo.Name:#}\t{plantStatus:#}" - ); - } - else - { - list.Add( - plantNumber, - $"{dirt:#}\t{health:#}\t{hueInfo.Name:#}\t{typeInfo.Name:#}\t{plantStatus:#}" - ); - } } else { - var category = typeInfo.PlantCategory == PlantCategory.Default ? hueInfo.Name : (int)typeInfo.PlantCategory; - var plantNumber = hueInfo.IsBright() ? 1060832 : 1060831; - if (list != _oldClientPropertyList) - { - list.Add(plantNumber, $"{container:#}\t{dirt:#}\t{health:#}\t{category:#}\t{plantStatus:#}"); - } - else - { - list.Add(plantNumber, $"{dirt:#}\t{health:#}\t{category:#}\t{plantStatus:#}"); - } + list.Add( + plantNumber, + $"{dirt:#}\t{health:#}\t{hueInfo.Name:#}\t{typeInfo.Name:#}\t{plantStatus:#}" + ); } } - - public bool IsUsableBy(Mobile from) => - IsChildOf(from.Backpack) || IsChildOf(from.FindBankNoCreate()) || IsLockedDown && IsAccessibleTo(from) || - RootParent is Item root && root.IsSecure && root.IsAccessibleTo(from); - - public override void OnDoubleClick(Mobile from) + else { - if (m_PlantStatus >= PlantStatus.DecorativePlant) + var category = typeInfo.PlantCategory == PlantCategory.Default ? hueInfo.Name : (int)typeInfo.PlantCategory; + var plantNumber = hueInfo.IsBright() ? 1060832 : 1060831; + if (list != _oldClientPropertyList) { - return; - } - - var loc = GetWorldLocation(); - - if (!from.InLOS(loc) || !from.InRange(loc, 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1019045); // I can't reach that. - return; - } - - if (!IsUsableBy(from)) - { - LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. - return; - } - - from.SendGump(new MainPlantGump(this)); - } - - public void PlantSeed(Mobile from, Seed seed) - { - if (m_PlantStatus >= PlantStatus.FullGrownPlant) - { - LabelTo(from, 1061919); // You must use a seed on some prepared soil! - } - else if (!IsUsableBy(from)) - { - LabelTo(from, 1061921); // The bowl of dirt must be in your pack, or you must lock it down. - } - else if (m_PlantStatus != PlantStatus.BowlOfDirt) - { - // This bowl of dirt already has a ~1_val~ in it! - from.SendLocalizedMessage(1080389, $"#{GetLocalizedPlantStatus()}"); - } - else if (PlantSystem.Water < 2) - { - LabelTo(from, 1061920); // The dirt needs to be softened first. + list.Add(plantNumber, $"{container:#}\t{dirt:#}\t{health:#}\t{category:#}\t{plantStatus:#}"); } else { - m_PlantType = seed.PlantType; - m_PlantHue = seed.PlantHue; - m_ShowType = seed.ShowType; - - seed.Consume(); - - PlantStatus = PlantStatus.Seed; - - PlantSystem.Reset(false); - - LabelTo(from, 1061922); // You plant the seed in the bowl of dirt. + list.Add(plantNumber, $"{dirt:#}\t{health:#}\t{category:#}\t{plantStatus:#}"); } } - - public void Die() - { - if (m_PlantStatus >= PlantStatus.FullGrownPlant) - { - PlantStatus = PlantStatus.DeadTwigs; - } - else - { - PlantStatus = PlantStatus.BowlOfDirt; - PlantSystem.Reset(true); - } - } - - public void Pour(Mobile from, Item item) - { - if (m_PlantStatus >= PlantStatus.DeadTwigs) - { - return; - } - - if (m_PlantStatus == PlantStatus.DecorativePlant) - { - LabelTo(from, 1053049); // This is a decorative plant, it does not need watering! - return; - } - - if (!IsUsableBy(from)) - { - LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. - return; - } - - if (item is BaseBeverage beverage) - { - if (beverage.IsEmpty || !beverage.Pourable || beverage.Content != BeverageType.Water) - { - LabelTo(from, 1053069); // You can't use that on a plant! - return; - } - - if (!beverage.ValidateUse(from, true)) - { - return; - } - - beverage.Quantity--; - PlantSystem.Water++; - - from.PlaySound(0x4E); - LabelTo(from, 1061858); // You soften the dirt with water. - } - else if (item is BasePotion potion) - { - if (ApplyPotion(potion.PotionEffect, false, out var message)) - { - potion.Consume(); - from.PlaySound(0x240); - from.AddToBackpack(new Bottle()); - } - - LabelTo(from, message); - } - else if (item is PotionKeg keg) - { - if (keg.Held <= 0) - { - LabelTo(from, 1053069); // You can't use that on a plant! - return; - } - - if (ApplyPotion(keg.Type, false, out var message)) - { - keg.Held--; - from.PlaySound(0x240); - } - - LabelTo(from, message); - } - else - { - LabelTo(from, 1053069); // You can't use that on a plant! - } - } - - public bool ApplyPotion(PotionEffect effect, bool testOnly, out int message) - { - if (m_PlantStatus >= PlantStatus.DecorativePlant) - { - message = 1053049; // This is a decorative plant, it does not need watering! - return false; - } - - if (m_PlantStatus == PlantStatus.BowlOfDirt) - { - message = 1053066; // You should only pour potions on a plant or seed! - return false; - } - - var full = false; - - if (effect is PotionEffect.PoisonGreater or PotionEffect.PoisonDeadly) - { - if (PlantSystem.IsFullPoisonPotion) - { - full = true; - } - else if (!testOnly) - { - PlantSystem.PoisonPotion++; - } - } - else if (effect == PotionEffect.CureGreater) - { - if (PlantSystem.IsFullCurePotion) - { - full = true; - } - else if (!testOnly) - { - PlantSystem.CurePotion++; - } - } - else if (effect == PotionEffect.HealGreater) - { - if (PlantSystem.IsFullHealPotion) - { - full = true; - } - else if (!testOnly) - { - PlantSystem.HealPotion++; - } - } - else if (effect == PotionEffect.StrengthGreater) - { - if (PlantSystem.IsFullStrengthPotion) - { - full = true; - } - else if (!testOnly) - { - PlantSystem.StrengthPotion++; - } - } - else if (effect is PotionEffect.PoisonLesser or PotionEffect.Poison or PotionEffect.CureLesser or PotionEffect.Cure or PotionEffect.HealLesser or PotionEffect.Heal or PotionEffect.Strength) - { - message = 1053068; // This potion is not powerful enough to use on a plant! - return false; - } - else - { - message = 1053069; // You can't use that on a plant! - return false; - } - - if (full) - { - message = 1053065; // The plant is already soaked with this type of potion! - return false; - } - - message = 1053067; // You pour the potion over the plant. - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write((int)Level); - - writer.Write((int)m_PlantStatus); - writer.Write((int)m_PlantType); - writer.Write((int)m_PlantHue); - writer.Write(m_ShowType); - - if (m_PlantStatus < PlantStatus.DecorativePlant) - { - PlantSystem.Save(writer); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 2: - case 1: - { - Level = (SecureLevel)reader.ReadInt(); - goto case 0; - } - case 0: - { - if (version < 1) - { - Level = SecureLevel.CoOwners; - } - - m_PlantStatus = (PlantStatus)reader.ReadInt(); - m_PlantType = (PlantType)reader.ReadInt(); - m_PlantHue = (PlantHue)reader.ReadInt(); - m_ShowType = reader.ReadBool(); - - if (m_PlantStatus < PlantStatus.DecorativePlant) - { - PlantSystem = new PlantSystem(this, reader); - } - - if (version < 2 && PlantHueInfo.IsCrossable(m_PlantHue)) - { - m_PlantHue |= PlantHue.Reproduces; - } - - break; - } - } - - Plants.Add(this); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - Plants.Remove(this); - } + } + + public bool IsUsableBy(Mobile from) => + IsChildOf(from.Backpack) || IsChildOf(from.FindBankNoCreate()) || IsLockedDown && IsAccessibleTo(from) || + RootParent is Item root && root.IsSecure && root.IsAccessibleTo(from); + + public override void OnDoubleClick(Mobile from) + { + if (_plantStatus >= PlantStatus.DecorativePlant) + { + return; + } + + var loc = GetWorldLocation(); + + if (!from.InLOS(loc) || !from.InRange(loc, 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1019045); // I can't reach that. + return; + } + + if (!IsUsableBy(from)) + { + LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. + return; + } + + from.SendGump(new MainPlantGump(this)); + } + + public void PlantSeed(Mobile from, Seed seed) + { + if (_plantStatus >= PlantStatus.FullGrownPlant) + { + LabelTo(from, 1061919); // You must use a seed on some prepared soil! + } + else if (!IsUsableBy(from)) + { + LabelTo(from, 1061921); // The bowl of dirt must be in your pack, or you must lock it down. + } + else if (_plantStatus != PlantStatus.BowlOfDirt) + { + // This bowl of dirt already has a ~1_val~ in it! + from.SendLocalizedMessage(1080389, $"#{GetLocalizedPlantStatus()}"); + } + else if (PlantSystem.Water < 2) + { + LabelTo(from, 1061920); // The dirt needs to be softened first. + } + else + { + PlantType = seed.PlantType; + PlantHue = seed.PlantHue; + ShowType = seed.ShowType; + + seed.Consume(); + + PlantStatus = PlantStatus.Seed; + + PlantSystem.Reset(false); + + LabelTo(from, 1061922); // You plant the seed in the bowl of dirt. + } + } + + public void Die() + { + if (_plantStatus >= PlantStatus.FullGrownPlant) + { + PlantStatus = PlantStatus.DeadTwigs; + } + else + { + PlantStatus = PlantStatus.BowlOfDirt; + PlantSystem.Reset(true); + } + } + + public void Pour(Mobile from, Item item) + { + if (_plantStatus >= PlantStatus.DeadTwigs) + { + return; + } + + if (_plantStatus == PlantStatus.DecorativePlant) + { + LabelTo(from, 1053049); // This is a decorative plant, it does not need watering! + return; + } + + if (!IsUsableBy(from)) + { + LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. + return; + } + + if (item is BaseBeverage beverage) + { + if (beverage.IsEmpty || !beverage.Pourable || beverage.Content != BeverageType.Water) + { + LabelTo(from, 1053069); // You can't use that on a plant! + return; + } + + if (!beverage.ValidateUse(from, true)) + { + return; + } + + beverage.Quantity--; + PlantSystem.Water++; + + from.PlaySound(0x4E); + LabelTo(from, 1061858); // You soften the dirt with water. + } + else if (item is BasePotion potion) + { + if (ApplyPotion(potion.PotionEffect, false, out var message)) + { + potion.Consume(); + from.PlaySound(0x240); + from.AddToBackpack(new Bottle()); + } + + LabelTo(from, message); + } + else if (item is PotionKeg keg) + { + if (keg.Held <= 0) + { + LabelTo(from, 1053069); // You can't use that on a plant! + return; + } + + if (ApplyPotion(keg.Type, false, out var message)) + { + keg.Held--; + from.PlaySound(0x240); + } + + LabelTo(from, message); + } + else + { + LabelTo(from, 1053069); // You can't use that on a plant! + } + } + + public bool ApplyPotion(PotionEffect effect, bool testOnly, out int message) + { + if (_plantStatus >= PlantStatus.DecorativePlant) + { + message = 1053049; // This is a decorative plant, it does not need watering! + return false; + } + + if (_plantStatus == PlantStatus.BowlOfDirt) + { + message = 1053066; // You should only pour potions on a plant or seed! + return false; + } + + var full = false; + + if (effect is PotionEffect.PoisonGreater or PotionEffect.PoisonDeadly) + { + if (PlantSystem.IsFullPoisonPotion) + { + full = true; + } + else if (!testOnly) + { + PlantSystem.PoisonPotion++; + } + } + else if (effect == PotionEffect.CureGreater) + { + if (PlantSystem.IsFullCurePotion) + { + full = true; + } + else if (!testOnly) + { + PlantSystem.CurePotion++; + } + } + else if (effect == PotionEffect.HealGreater) + { + if (PlantSystem.IsFullHealPotion) + { + full = true; + } + else if (!testOnly) + { + PlantSystem.HealPotion++; + } + } + else if (effect == PotionEffect.StrengthGreater) + { + if (PlantSystem.IsFullStrengthPotion) + { + full = true; + } + else if (!testOnly) + { + PlantSystem.StrengthPotion++; + } + } + else if (effect is PotionEffect.PoisonLesser or PotionEffect.Poison or PotionEffect.CureLesser or PotionEffect.Cure or PotionEffect.HealLesser or PotionEffect.Heal or PotionEffect.Strength) + { + message = 1053068; // This potion is not powerful enough to use on a plant! + return false; + } + else + { + message = 1053069; // You can't use that on a plant! + return false; + } + + if (full) + { + message = 1053065; // The plant is already soaked with this type of potion! + return false; + } + + message = 1053067; // You pour the potion over the plant. + return true; + } + + private void Deserialize(IGenericReader reader, int version) + { + _level = (SecureLevel)reader.ReadInt(); + _plantStatus = (PlantStatus)reader.ReadInt(); + _plantType = (PlantType)reader.ReadInt(); + _plantHue = (PlantHue)reader.ReadInt(); + _showType = reader.ReadBool(); + + if (_plantStatus < PlantStatus.DecorativePlant) + { + _plantSystem = new PlantSystem(this); + _plantSystem.Deserialize(reader); + } + } + + [AfterDeserialization] + private void AfterDeserialization() + { + Plants.Add(this); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + Plants.Remove(this); } } diff --git a/Projects/UOContent/Engines/Plants/PlantSystem.cs b/Projects/UOContent/Engines/Plants/PlantSystem.cs index 813cbaeac..719ca1e93 100644 --- a/Projects/UOContent/Engines/Plants/PlantSystem.cs +++ b/Projects/UOContent/Engines/Plants/PlantSystem.cs @@ -1,4 +1,5 @@ using System; +using ModernUO.Serialization; using Server.Misc; namespace Server.Engines.Plants @@ -21,298 +22,350 @@ namespace Server.Engines.Plants DoubleGrown } - public class PlantSystem + [SerializationGenerator(3, false)] + public partial class PlantSystem { public static readonly TimeSpan CheckDelay = TimeSpan.FromHours(23.0); - private int m_AvailableResources; - private int m_AvailableSeeds; - private int m_CurePotion; - private int m_Disease; - private int m_Fungus; - private int m_HealPotion; + [DirtyTrackingEntity] + private PlantItem _plant; - private int m_Hits; - private int m_Infestation; - private int m_LeftResources; - private int m_LeftSeeds; - private int m_Poison; - private int m_PoisonPotion; - private PlantHue m_SeedHue; + [SerializableField(0)] + private bool _fertileDirt; - private PlantType m_SeedType; - private int m_StrengthPotion; + [SerializableFieldSaveFlag(0)] + private bool ShouldSerializeFertileDirt() => _fertileDirt; - private int m_Water; + [SerializableField(1)] + private DateTime _nextGrowth; - public PlantSystem(PlantItem plant, bool fertileDirt) + [SerializableField(2, setter: "private")] + private PlantGrowthIndicator _growthIndicator; + + [SerializableFieldSaveFlag(2)] + private bool ShouldSerializeGrowthIndicator() => _growthIndicator != PlantGrowthIndicator.None; + + [SerializableField(13)] + private bool _pollinated; + + [SerializableFieldSaveFlag(13)] + private bool ShouldSerializePollinated() => _pollinated; + + public PlantSystem(PlantItem plant) { - Plant = plant; - FertileDirt = fertileDirt; + _plant = plant; - NextGrowth = Core.Now + CheckDelay; - GrowthIndicator = PlantGrowthIndicator.None; - m_Hits = MaxHits; - m_LeftSeeds = 8; - m_LeftResources = 8; + _nextGrowth = Core.Now + CheckDelay; + _growthIndicator = PlantGrowthIndicator.None; + _hits = MaxHits; + _leftSeeds = 8; + _leftResources = 8; } - public PlantSystem(PlantItem plant, IGenericReader reader) + private void Deserialize(IGenericReader reader, int version) { - Plant = plant; - - var version = reader.ReadInt(); - - FertileDirt = reader.ReadBool(); - - if (version >= 1) - { - NextGrowth = reader.ReadDateTime(); - } - else - { - NextGrowth = reader.ReadDeltaTime(); - } + _fertileDirt = reader.ReadBool(); + NextGrowth = reader.ReadDateTime(); GrowthIndicator = (PlantGrowthIndicator)reader.ReadInt(); - m_Water = reader.ReadInt(); + _water = reader.ReadInt(); - m_Hits = reader.ReadInt(); - m_Infestation = reader.ReadInt(); - m_Fungus = reader.ReadInt(); - m_Poison = reader.ReadInt(); - m_Disease = reader.ReadInt(); - m_PoisonPotion = reader.ReadInt(); - m_CurePotion = reader.ReadInt(); - m_HealPotion = reader.ReadInt(); - m_StrengthPotion = reader.ReadInt(); + _hits = reader.ReadInt(); + _infestation = reader.ReadInt(); + _fungus = reader.ReadInt(); + _poison = reader.ReadInt(); + _disease = reader.ReadInt(); + _poisonPotion = reader.ReadInt(); + _curePotion = reader.ReadInt(); + _healPotion = reader.ReadInt(); + _strengthPotion = reader.ReadInt(); Pollinated = reader.ReadBool(); - m_SeedType = (PlantType)reader.ReadInt(); - m_SeedHue = (PlantHue)reader.ReadInt(); - m_AvailableSeeds = reader.ReadInt(); - m_LeftSeeds = reader.ReadInt(); + _seedType = (PlantType)reader.ReadInt(); + _seedHue = (PlantHue)reader.ReadInt(); + _availableSeeds = reader.ReadInt(); + _leftSeeds = reader.ReadInt(); - m_AvailableResources = reader.ReadInt(); - m_LeftResources = reader.ReadInt(); - - if (version < 2 && PlantHueInfo.IsCrossable(m_SeedHue)) - { - m_SeedHue |= PlantHue.Reproduces; - } + _availableResources = reader.ReadInt(); + _leftResources = reader.ReadInt(); } - public PlantItem Plant { get; } + public PlantItem Plant => _plant; - public bool FertileDirt { get; set; } - - public DateTime NextGrowth { get; private set; } - - public PlantGrowthIndicator GrowthIndicator { get; private set; } - - public bool IsFullWater => m_Water >= 4; + public bool IsFullWater => _water >= 4; + [SerializableProperty(3)] public int Water { - get => m_Water; + get => _water; set { - m_Water = Math.Clamp(value, 0, 4); + _water = Math.Clamp(value, 0, 4); Plant.InvalidateProperties(); + MarkDirty(); } } + [SerializableFieldSaveFlag(3)] + private bool ShouldSerializeWater() => _water != 0; + + [SerializableProperty(4)] public int Hits { - get => m_Hits; + get => _hits; set { - if (m_Hits == value) + if (_hits == value) { return; } - m_Hits = Math.Clamp(value, 0, MaxHits); + _hits = Math.Clamp(value, 0, MaxHits); - if (m_Hits == 0) + if (_hits == 0) { Plant.Die(); } Plant.InvalidateProperties(); + MarkDirty(); } } + [SerializableFieldSaveFlag(4)] + private bool ShouldSerializeHits() => _hits != 0; + public int MaxHits => 10 + (int)Plant.PlantStatus * 2; public PlantHealth Health { - get + get => (_hits * 100 / MaxHits) switch { - var perc = m_Hits * 100 / MaxHits; + < 33 => PlantHealth.Dying, + < 66 => PlantHealth.Wilted, + < 100 => PlantHealth.Healthy, + _ => PlantHealth.Vibrant + }; + } - if (perc < 33) - { - return PlantHealth.Dying; - } - - if (perc < 66) - { - return PlantHealth.Wilted; - } - - return perc < 100 ? PlantHealth.Healthy : PlantHealth.Vibrant; + [SerializableProperty(5)] + public int Infestation + { + get => _infestation; + set + { + _infestation = Math.Clamp(value, 0, 2); + MarkDirty(); } } - public int Infestation - { - get => m_Infestation; - set => m_Infestation = Math.Clamp(value, 0, 2); - } + [SerializableFieldSaveFlag(5)] + private bool ShouldSerializeInfestation() => _infestation != 0; + [SerializableProperty(6)] public int Fungus { - get => m_Fungus; - set => m_Fungus = Math.Clamp(value, 0, 2); + get => _fungus; + set + { + _fungus = Math.Clamp(value, 0, 2); + MarkDirty(); + } } + [SerializableFieldSaveFlag(6)] + private bool ShouldSerializeFungus() => _fungus != 0; + + [SerializableProperty(7)] public int Poison { - get => m_Poison; - set => m_Poison = Math.Clamp(value, 0, 2); + get => _poison; + set + { + _poison = Math.Clamp(value, 0, 2); + MarkDirty(); + } } + [SerializableFieldSaveFlag(7)] + private bool ShouldSerializePoison() => _poison != 0; + + [SerializableProperty(8)] public int Disease { - get => m_Disease; - set => m_Disease = Math.Clamp(value, 0, 2); + get => _disease; + set + { + _disease = Math.Clamp(value, 0, 2); + MarkDirty(); + } } - public bool IsFullPoisonPotion => m_PoisonPotion >= 2; + [SerializableFieldSaveFlag(8)] + private bool ShouldSerializeDisease() => _disease != 0; + public bool IsFullPoisonPotion => _poisonPotion >= 2; + + [SerializableProperty(9)] public int PoisonPotion { - get => m_PoisonPotion; - set => m_PoisonPotion = Math.Clamp(value, 0, 2); + get => _poisonPotion; + set + { + _poisonPotion = Math.Clamp(value, 0, 2); + MarkDirty(); + } } - public bool IsFullCurePotion => m_CurePotion >= 2; + [SerializableFieldSaveFlag(9)] + private bool ShouldSerializePoisonPotion() => _poisonPotion != 0; + public bool IsFullCurePotion => _curePotion >= 2; + + [SerializableProperty(10)] public int CurePotion { - get => m_CurePotion; - set => m_CurePotion = Math.Clamp(value, 0, 2); + get => _curePotion; + set + { + _curePotion = Math.Clamp(value, 0, 2); + MarkDirty(); + } } - public bool IsFullHealPotion => m_HealPotion >= 2; + [SerializableFieldSaveFlag(10)] + private bool ShouldSerializeCurePotion() => _curePotion != 0; + public bool IsFullHealPotion => _healPotion >= 2; + + [SerializableProperty(11)] public int HealPotion { - get => m_HealPotion; - set => m_HealPotion = Math.Clamp(value, 0, 2); + get => _healPotion; + set + { + _healPotion = Math.Clamp(value, 0, 2); + MarkDirty(); + } } - public bool IsFullStrengthPotion => m_StrengthPotion >= 2; + [SerializableFieldSaveFlag(11)] + private bool ShouldSerializeHealPotion() => _healPotion != 0; + public bool IsFullStrengthPotion => _strengthPotion >= 2; + + [SerializableProperty(12)] public int StrengthPotion { - get => m_StrengthPotion; - set => m_StrengthPotion = Math.Clamp(value, 0, 2); + get => _strengthPotion; + set + { + _strengthPotion = Math.Clamp(value, 0, 2); + MarkDirty(); + } } + [SerializableFieldSaveFlag(12)] + private bool ShouldSerializeStrengthPotion() => _strengthPotion != 0; + public bool HasMaladies => Infestation > 0 || Fungus > 0 || Poison > 0 || Disease > 0 || Water != 2; public bool PollenProducing => Plant.IsCrossable && Plant.PlantStatus >= PlantStatus.FullGrownPlant; - public bool Pollinated { get; set; } - + [SerializableProperty(14)] public PlantType SeedType { - get => Pollinated ? m_SeedType : Plant.PlantType; - set => m_SeedType = value; + get => Pollinated ? _seedType : Plant.PlantType; + set + { + _seedType = value; + MarkDirty(); + } } + [SerializableFieldSaveFlag(14)] + private bool ShouldSerializeSeedType() => _pollinated; + + [SerializableProperty(15)] public PlantHue SeedHue { - get => Pollinated ? m_SeedHue : Plant.PlantHue; - set => m_SeedHue = value; + get => Pollinated ? _seedHue : Plant.PlantHue; + set + { + _seedHue = value; + MarkDirty(); + } } + [SerializableFieldSaveFlag(15)] + private bool ShouldSerializeSeedHue() => _pollinated; + + [SerializableProperty(16)] public int AvailableSeeds { - get => m_AvailableSeeds; - set - { - if (value >= 0) - { - m_AvailableSeeds = value; - } - } + get => _availableSeeds; + set => _availableSeeds = Math.Max(value, 0); } + [SerializableFieldSaveFlag(16)] + private bool ShouldSerializeAvailableSeeds() => _availableSeeds != 0; + + [SerializableProperty(17)] public int LeftSeeds { - get => m_LeftSeeds; - set - { - if (value >= 0) - { - m_LeftSeeds = value; - } - } + get => _leftSeeds; + set => _leftSeeds = Math.Max(value, 0); } + [SerializableFieldSaveFlag(17)] + private bool ShouldSerializeLeftSeeds() => _leftSeeds != 0; + + [SerializableProperty(18)] public int AvailableResources { - get => m_AvailableResources; - set - { - if (value >= 0) - { - m_AvailableResources = value; - } - } + get => _availableResources; + set => _availableResources = Math.Max(value, 0); } + [SerializableFieldSaveFlag(18)] + private bool ShouldSerializeAvailableResources() => _availableResources != 0; + + [SerializableProperty(19)] public int LeftResources { - get => m_LeftResources; - set - { - if (value >= 0) - { - m_LeftResources = value; - } - } + get => _leftResources; + set => _leftResources = Math.Max(value, 0); } + [SerializableFieldSaveFlag(19)] + private bool ShouldSerializeLeftResources() => _leftResources != 0; + public void Reset(bool potions) { NextGrowth = Core.Now + CheckDelay; GrowthIndicator = PlantGrowthIndicator.None; Hits = MaxHits; - m_Infestation = 0; - m_Fungus = 0; - m_Poison = 0; - m_Disease = 0; + Infestation = 0; + Fungus = 0; + Poison = 0; + Disease = 0; if (potions) { - m_PoisonPotion = 0; - m_CurePotion = 0; - m_HealPotion = 0; - m_StrengthPotion = 0; + PoisonPotion = 0; + CurePotion = 0; + HealPotion = 0; + StrengthPotion = 0; } Pollinated = false; - m_AvailableSeeds = 0; - m_LeftSeeds = 8; + AvailableSeeds = 0; + LeftSeeds = 8; - m_AvailableResources = 0; - m_LeftResources = 8; + AvailableResources = 0; + LeftResources = 8; } public int GetLocalizedDirtStatus() => @@ -634,36 +687,5 @@ namespace Server.Engines.Plants StrengthPotion = 0; } - - public void Save(IGenericWriter writer) - { - writer.Write(2); // version - - writer.Write(FertileDirt); - - writer.Write(NextGrowth); - writer.Write((int)GrowthIndicator); - - writer.Write(m_Water); - - writer.Write(m_Hits); - writer.Write(m_Infestation); - writer.Write(m_Fungus); - writer.Write(m_Poison); - writer.Write(m_Disease); - writer.Write(m_PoisonPotion); - writer.Write(m_CurePotion); - writer.Write(m_HealPotion); - writer.Write(m_StrengthPotion); - - writer.Write(Pollinated); - writer.Write((int)m_SeedType); - writer.Write((int)m_SeedHue); - writer.Write(m_AvailableSeeds); - writer.Write(m_LeftSeeds); - - writer.Write(m_AvailableResources); - writer.Write(m_LeftResources); - } } } diff --git a/Projects/UOContent/Engines/Plants/Seed.cs b/Projects/UOContent/Engines/Plants/Seed.cs index bee1228a8..9822da7f6 100644 --- a/Projects/UOContent/Engines/Plants/Seed.cs +++ b/Projects/UOContent/Engines/Plants/Seed.cs @@ -1,271 +1,224 @@ +using ModernUO.Serialization; using Server.Targeting; -namespace Server.Engines.Plants +namespace Server.Engines.Plants; + +[SerializationGenerator(3, false)] +public partial class Seed : Item { - public class Seed : Item + [InvalidateProperties] + [SerializableField(0)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private PlantType _plantType; + + [InvalidateProperties] + [SerializableField(2)] + [SerializedCommandProperty(AccessLevel.GameMaster)] + private bool _showType; + + [Constructible] + public Seed() : this(PlantTypeInfo.RandomFirstGeneration(), PlantHueInfo.RandomFirstGeneration()) { - private PlantHue m_PlantHue; - private PlantType m_PlantType; - private bool m_ShowType; + } - [Constructible] - public Seed() : this(PlantTypeInfo.RandomFirstGeneration(), PlantHueInfo.RandomFirstGeneration()) + [Constructible] + public Seed(PlantType plantType, PlantHue plantHue, bool showType = false) : base(0xDCF) + { + Weight = 1.0; + Stackable = Core.SA; + + _plantType = plantType; + _plantHue = plantHue; + _showType = showType; + + Hue = PlantHueInfo.GetInfo(plantHue).Hue; + } + + [CommandProperty(AccessLevel.GameMaster)] + [SerializableProperty(1)] + public PlantHue PlantHue + { + get => _plantHue; + set { + _plantHue = value; + Hue = PlantHueInfo.GetInfo(value).Hue; + InvalidateProperties(); + this.MarkDirty(); + } + } + + public override int LabelNumber => 1060810; // seed + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + public static Seed RandomBonsaiSeed() => RandomBonsaiSeed(0.5); + + public static Seed RandomBonsaiSeed(double increaseRatio) => new( + PlantTypeInfo.RandomBonsai(increaseRatio), + PlantHue.Plain + ); + + public static Seed RandomPeculiarSeed(int group) + { + return group switch + { + 1 => new Seed(PlantTypeInfo.RandomPeculiarGroupOne(), PlantHue.Plain), + 2 => new Seed(PlantTypeInfo.RandomPeculiarGroupTwo(), PlantHue.Plain), + 3 => new Seed(PlantTypeInfo.RandomPeculiarGroupThree(), PlantHue.Plain), + _ => new Seed(PlantTypeInfo.RandomPeculiarGroupFour(), PlantHue.Plain) + }; + } + + private int GetLabel(out string args) + { + var typeInfo = PlantTypeInfo.GetInfo(_plantType); + var hueInfo = PlantHueInfo.GetInfo(_plantHue); + + int title; + + if (_showType || typeInfo.PlantCategory == PlantCategory.Default) + { + title = hueInfo.Name; + } + else + { + title = (int)typeInfo.PlantCategory; } - [Constructible] - public Seed(PlantType plantType, PlantHue plantHue, bool showType = false) : base(0xDCF) + if (Amount == 1) { - Weight = 1.0; - Stackable = Core.SA; + if (_showType) + { + args = $"#{title}\t#{typeInfo.Name}"; + return typeInfo.GetSeedLabel(hueInfo); + } - m_PlantType = plantType; - m_PlantHue = plantHue; - m_ShowType = showType; - - Hue = PlantHueInfo.GetInfo(plantHue).Hue; + args = $"#{title}"; + return hueInfo.IsBright() ? 1060839 : 1060838; // [bright] ~1_val~ seed } - public Seed(Serial serial) : base(serial) + if (_showType) { + args = $"{Amount}\t#{title}\t#{typeInfo.Name}"; + return typeInfo.GetSeedLabelPlural(hueInfo); } - [CommandProperty(AccessLevel.GameMaster)] - public PlantType PlantType + args = $"{Amount}\t#{title}"; + return hueInfo.IsBright() ? 1113491 : 1113490; // ~1_amount~ [bright] ~2_val~ seeds + } + + public override void AddNameProperty(IPropertyList list) + { + var typeInfo = PlantTypeInfo.GetInfo(_plantType); + var hueInfo = PlantHueInfo.GetInfo(_plantHue); + + int title; + + if (_showType || typeInfo.PlantCategory == PlantCategory.Default) { - get => m_PlantType; - set - { - m_PlantType = value; - InvalidateProperties(); - } + title = hueInfo.Name; + } + else + { + title = (int)typeInfo.PlantCategory; } - [CommandProperty(AccessLevel.GameMaster)] - public PlantHue PlantHue + if (Amount == 1) { - get => m_PlantHue; - set + if (_showType) { - m_PlantHue = value; - Hue = PlantHueInfo.GetInfo(value).Hue; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ShowType - { - get => m_ShowType; - set - { - m_ShowType = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => 1060810; // seed - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public static Seed RandomBonsaiSeed() => RandomBonsaiSeed(0.5); - - public static Seed RandomBonsaiSeed(double increaseRatio) => new( - PlantTypeInfo.RandomBonsai(increaseRatio), - PlantHue.Plain - ); - - public static Seed RandomPeculiarSeed(int group) - { - return group switch - { - 1 => new Seed(PlantTypeInfo.RandomPeculiarGroupOne(), PlantHue.Plain), - 2 => new Seed(PlantTypeInfo.RandomPeculiarGroupTwo(), PlantHue.Plain), - 3 => new Seed(PlantTypeInfo.RandomPeculiarGroupThree(), PlantHue.Plain), - _ => new Seed(PlantTypeInfo.RandomPeculiarGroupFour(), PlantHue.Plain) - }; - } - - private int GetLabel(out string args) - { - var typeInfo = PlantTypeInfo.GetInfo(m_PlantType); - var hueInfo = PlantHueInfo.GetInfo(m_PlantHue); - - int title; - - if (m_ShowType || typeInfo.PlantCategory == PlantCategory.Default) - { - title = hueInfo.Name; - } - else - { - title = (int)typeInfo.PlantCategory; - } - - if (Amount == 1) - { - if (m_ShowType) - { - args = $"#{title}\t#{typeInfo.Name}"; - return typeInfo.GetSeedLabel(hueInfo); - } - - args = $"#{title}"; - return hueInfo.IsBright() ? 1060839 : 1060838; // [bright] ~1_val~ seed - } - - if (m_ShowType) - { - args = $"{Amount}\t#{title}\t#{typeInfo.Name}"; - return typeInfo.GetSeedLabelPlural(hueInfo); - } - - args = $"{Amount}\t#{title}"; - return hueInfo.IsBright() ? 1113491 : 1113490; // ~1_amount~ [bright] ~2_val~ seeds - } - - public override void AddNameProperty(IPropertyList list) - { - var typeInfo = PlantTypeInfo.GetInfo(m_PlantType); - var hueInfo = PlantHueInfo.GetInfo(m_PlantHue); - - int title; - - if (m_ShowType || typeInfo.PlantCategory == PlantCategory.Default) - { - title = hueInfo.Name; - } - else - { - title = (int)typeInfo.PlantCategory; - } - - if (Amount == 1) - { - if (m_ShowType) - { - list.Add(typeInfo.GetSeedLabel(hueInfo), $"{title:#}\t{typeInfo.Name:#}"); - return; - } - - list.Add(hueInfo.IsBright() ? 1060839 : 1060838, $"{title:#}"); + list.Add(typeInfo.GetSeedLabel(hueInfo), $"{title:#}\t{typeInfo.Name:#}"); return; } - if (m_ShowType) + list.Add(hueInfo.IsBright() ? 1060839 : 1060838, $"{title:#}"); + return; + } + + if (_showType) + { + list.Add(typeInfo.GetSeedLabelPlural(hueInfo), $"{Amount}\t{title:#}\t{typeInfo.Name:#}"); + return; + } + + list.Add(hueInfo.IsBright() ? 1113491 : 1113490, $"{Amount}\t{title:#}"); + } + + public override void OnSingleClick(Mobile from) + { + LabelTo(from, GetLabel(out var args), args); + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; + } + + from.Target = new InternalTarget(this); + LabelTo(from, 1061916); // Choose a bowl of dirt to plant this seed in. + } + + public override bool StackWith(Mobile from, Item dropped, bool playSound) => + dropped is Seed other && other.PlantType == _plantType && other.PlantHue == _plantHue && + other.ShowType == _showType && base.StackWith(from, other, playSound); + + public override void OnAfterDuped(Item newItem) + { + if (newItem is not Seed newSeed) + { + return; + } + + newSeed.PlantType = _plantType; + newSeed.PlantHue = _plantHue; + newSeed.ShowType = _showType; + } + + private void Deserialize(IGenericReader reader, int version) + { + _plantType = (PlantType)reader.ReadInt(); + _plantHue = (PlantHue)reader.ReadInt(); + _showType = reader.ReadBool(); + } + + private class InternalTarget : Target + { + private readonly Seed _seed; + + public InternalTarget(Seed seed) : base(-1, false, TargetFlags.None) + { + _seed = seed; + CheckLOS = false; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (_seed.Deleted) { - list.Add(typeInfo.GetSeedLabelPlural(hueInfo), $"{Amount}\t{title:#}\t{typeInfo.Name:#}"); return; } - list.Add(hueInfo.IsBright() ? 1113491 : 1113490, $"{Amount}\t{title:#}"); - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, GetLabel(out var args), args); - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) + if (!_seed.IsChildOf(from.Backpack)) { from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. return; } - from.Target = new InternalTarget(this); - LabelTo(from, 1061916); // Choose a bowl of dirt to plant this seed in. - } - - public override bool StackWith(Mobile from, Item dropped, bool playSound) => - dropped is Seed other && other.PlantType == m_PlantType && other.PlantHue == m_PlantHue && - other.ShowType == m_ShowType && base.StackWith(from, other, playSound); - - public override void OnAfterDuped(Item newItem) - { - if (newItem is not Seed newSeed) + if (targeted is PlantItem plant) { - return; + plant.PlantSeed(from, _seed); } - - newSeed.PlantType = m_PlantType; - newSeed.PlantHue = m_PlantHue; - newSeed.ShowType = m_ShowType; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write((int)m_PlantType); - writer.Write((int)m_PlantHue); - writer.Write(m_ShowType); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - m_PlantType = (PlantType)reader.ReadInt(); - m_PlantHue = (PlantHue)reader.ReadInt(); - m_ShowType = reader.ReadBool(); - - if (Weight != 1.0) + else if (targeted is Item item) { - Weight = 1.0; + item.LabelTo(from, 1061919); // You must use a seed on a bowl of dirt! } - - if (version < 1) + else { - Stackable = Core.SA; - } - - if (version < 2 && PlantHueInfo.IsCrossable(m_PlantHue)) - { - m_PlantHue |= PlantHue.Reproduces; - } - } - - private class InternalTarget : Target - { - private readonly Seed m_Seed; - - public InternalTarget(Seed seed) : base(-1, false, TargetFlags.None) - { - m_Seed = seed; - CheckLOS = false; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Seed.Deleted) - { - return; - } - - if (!m_Seed.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } - - if (targeted is PlantItem plant) - { - plant.PlantSeed(from, m_Seed); - } - else if (targeted is Item item) - { - item.LabelTo(from, 1061919); // You must use a seed on a bowl of dirt! - } - else - { - from.SendLocalizedMessage(1061919); // You must use a seed on a bowl of dirt! - } + from.SendLocalizedMessage(1061919); // You must use a seed on a bowl of dirt! } } } diff --git a/Projects/UOContent/Migrations/Server.Engines.Plants.PlantBowl.v0.json b/Projects/UOContent/Migrations/Server.Engines.Plants.PlantBowl.v0.json new file mode 100644 index 000000000..700de3984 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Engines.Plants.PlantBowl.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Engines.Plants.PlantBowl" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Engines.Plants.PlantItem.v3.json b/Projects/UOContent/Migrations/Server.Engines.Plants.PlantItem.v3.json new file mode 100644 index 000000000..20c8df027 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Engines.Plants.PlantItem.v3.json @@ -0,0 +1,48 @@ +{ + "version": 3, + "type": "Server.Engines.Plants.PlantItem", + "properties": [ + { + "name": "Level", + "type": "Server.Multis.SecureLevel", + "usesSaveFlag": true, + "rule": "EnumMigrationRule" + }, + { + "name": "PlantStatus", + "type": "Server.Engines.Plants.PlantStatus", + "usesSaveFlag": true, + "rule": "EnumMigrationRule" + }, + { + "name": "PlantType", + "type": "Server.Engines.Plants.PlantType", + "usesSaveFlag": true, + "rule": "EnumMigrationRule" + }, + { + "name": "PlantHue", + "type": "Server.Engines.Plants.PlantHue", + "usesSaveFlag": true, + "rule": "EnumMigrationRule" + }, + { + "name": "ShowType", + "type": "bool", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "PlantSystem", + "type": "Server.Engines.Plants.PlantSystem", + "usesSaveFlag": true, + "rule": "RawSerializableMigrationRule", + "ruleArguments": [ + "DeserializationRequiresParent" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Engines.Plants.PlantSystem.v3.json b/Projects/UOContent/Migrations/Server.Engines.Plants.PlantSystem.v3.json new file mode 100644 index 000000000..be1b3ceb5 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Engines.Plants.PlantSystem.v3.json @@ -0,0 +1,176 @@ +{ + "version": 3, + "type": "Server.Engines.Plants.PlantSystem", + "properties": [ + { + "name": "FertileDirt", + "type": "bool", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "NextGrowth", + "type": "System.DateTime", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "GrowthIndicator", + "type": "Server.Engines.Plants.PlantGrowthIndicator", + "usesSaveFlag": true, + "rule": "EnumMigrationRule" + }, + { + "name": "Water", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Hits", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Infestation", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Fungus", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Poison", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Disease", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "PoisonPotion", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "CurePotion", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "HealPotion", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "StrengthPotion", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Pollinated", + "type": "bool", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "SeedType", + "type": "Server.Engines.Plants.PlantType", + "usesSaveFlag": true, + "rule": "EnumMigrationRule" + }, + { + "name": "SeedHue", + "type": "Server.Engines.Plants.PlantHue", + "usesSaveFlag": true, + "rule": "EnumMigrationRule" + }, + { + "name": "AvailableSeeds", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "LeftSeeds", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "AvailableResources", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "LeftResources", + "type": "int", + "usesSaveFlag": true, + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Engines.Plants.Seed.v3.json b/Projects/UOContent/Migrations/Server.Engines.Plants.Seed.v3.json new file mode 100644 index 000000000..976d56724 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Engines.Plants.Seed.v3.json @@ -0,0 +1,24 @@ +{ + "version": 3, + "type": "Server.Engines.Plants.Seed", + "properties": [ + { + "name": "PlantType", + "type": "Server.Engines.Plants.PlantType", + "rule": "EnumMigrationRule" + }, + { + "name": "PlantHue", + "type": "Server.Engines.Plants.PlantHue", + "rule": "EnumMigrationRule" + }, + { + "name": "ShowType", + "type": "bool", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.FertileDirt.v0.json b/Projects/UOContent/Migrations/Server.Items.FertileDirt.v0.json new file mode 100644 index 000000000..804329c0e --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.FertileDirt.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.FertileDirt" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.GreenThorns.v0.json b/Projects/UOContent/Migrations/Server.Items.GreenThorns.v0.json new file mode 100644 index 000000000..06056aab2 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.GreenThorns.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.GreenThorns" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.GreenThornsSHTeleporter.v0.json b/Projects/UOContent/Migrations/Server.Items.GreenThornsSHTeleporter.v0.json new file mode 100644 index 000000000..5a41a9c70 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.GreenThornsSHTeleporter.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.GreenThornsSHTeleporter" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.OrangePetals.v0.json b/Projects/UOContent/Migrations/Server.Items.OrangePetals.v0.json new file mode 100644 index 000000000..7f092cc5d --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.OrangePetals.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.OrangePetals" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.RedLeaves.v0.json b/Projects/UOContent/Migrations/Server.Items.RedLeaves.v0.json new file mode 100644 index 000000000..743ab6900 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.RedLeaves.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.RedLeaves" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Mobiles.GiantIceWorm.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.GiantIceWorm.v0.json new file mode 100644 index 000000000..48fa5e238 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Mobiles.GiantIceWorm.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Mobiles.GiantIceWorm" +} \ No newline at end of file