diff --git a/Info/MyChanges.txt b/Info/MyChanges.txt index bb44a35fc..a78ebddbc 100644 --- a/Info/MyChanges.txt +++ b/Info/MyChanges.txt @@ -32,6 +32,7 @@ Command - [IS - Import Spawn "[IS Data/Spawns/Dungeon/Shame.json" - [EAS - ExportAllSpawners will export all spawners on the current map to Data/Spawns/Exported/.json + - [ECN - Exports all the CitizenNodes on the current map. - [DOTD - Tells you what the current Dungeon of the Day is - [BuildWorld - Opens a new buldworld gump - [bandself - Applies a bandage to the player. Checks for bandages in the players pack diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/CitizenNode.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/CitizenNode.cs index 1166099ea..16cd83837 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/CitizenNode.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/CitizenNode.cs @@ -8,6 +8,7 @@ namespace Server.Items { public enum CitizenNodeType { + Butcher, Smith, Smelter, MeetingSpot @@ -99,6 +100,11 @@ namespace Server.Items _workstation = new CampfireHit(); SpawnMeetingSpotCitizens(); break; + case CitizenNodeType.Butcher: + var butcherMeat = new ButcherHit(); + _workstation = butcherMeat; + AddWorker(new TradesmanButcher(), butcherMeat.GetWorkerPlacement(Location)); + break; } if (_workstation != null) diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/CitizensRef.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/CitizensRef.cs index d3ede61e3..7912497a3 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/CitizensRef.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/CitizensRef.cs @@ -27,9 +27,6 @@ namespace Server.Items public void Respawn() { - // Proxy spawners do not handle their own respawns. - // When the monster dies, the proxy deletes itself, - // and the parent Master Spawner drops a new proxy. } public bool IsInSpawnBounds(Point3D loc) diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/HumanCitizen.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/HumanCitizen.cs index 21319df1c..f2f9943d4 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/HumanCitizen.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/HumanCitizen.cs @@ -39,7 +39,6 @@ namespace Server.Mobiles "They say the magical energies are shifting around {activedungeon} today." }; - // Add your custom titles here! private static readonly string[] _FemaleTitles = new string[] { "the citizen", "the wanderer", "the peasant", @@ -55,7 +54,7 @@ namespace Server.Mobiles [Constructible] public Citizen() : base(AIType.AI_Animal, FightMode.None) { - SetSpeed(0.2, 0.4); + //SetSpeed(0.2, 0.4); Hue = Race.Human.RandomSkinHue(); SpeechHue = 48; //Blessed = true; @@ -142,7 +141,7 @@ namespace Server.Mobiles Utility.AssignRandomFacialHair(this); } - _NextChatter = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 15)); + _NextChatter = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(0, 10)); } public override void OnThink() @@ -193,7 +192,7 @@ namespace Server.Mobiles Say(line); } - _NextChatter = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60)); + _NextChatter = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(10, 15)); } } diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/MonsterCitizen.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/MonsterCitizen.cs index 6f6f8a9bc..acd93e90d 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/MonsterCitizen.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/MonsterCitizen.cs @@ -54,16 +54,14 @@ namespace Server.Mobiles if (playerNearby) { - // Fetch the correct lines based on their current body type string[] lines = GetChatterLines(); Say(lines[Utility.Random(lines.Length)]); } - _NextChatter = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60)); + _NextChatter = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(10, 15)); } } - // --- NEW: Helper method to organize dialogue by body ID --- private string[] GetChatterLines() { switch ((int)Body) diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/ButcherMeat.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/ButcherMeat.cs new file mode 100644 index 000000000..4dda3242f --- /dev/null +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/ButcherMeat.cs @@ -0,0 +1,69 @@ +using System; +using Server; +using ModernUO.Serialization; + +namespace Server.Items +{ + [SerializationGenerator(0, false)] + public partial class ButcherHit : Item + { + private static readonly int[] _MeatGraphics = new int[] + { + 0x1871, // Meat faces south + 0x1872, // Meat faces east + 0x1873, // Meat faces south + 0x1874 // Meat faces east + }; + + [Constructible] + public ButcherHit() : base(0x1874) + { + ItemID = _MeatGraphics[Utility.Random(_MeatGraphics.Length)]; + Name = "meat"; + Movable = false; + } + + [Constructible] + public ButcherHit(int itemID) : base(itemID) + { + Name = "meat"; + Movable = false; + } + + public (Point3D loc, Direction dir) GetWorkerPlacement(Point3D baseLoc) + { + switch (ItemID) + { + case 0x1871: + return (new Point3D(baseLoc.X, baseLoc.Y + 1, baseLoc.Z), Direction.North); + case 0x1872: + return (new Point3D(baseLoc.X + 1, baseLoc.Y, baseLoc.Z), Direction.East); + case 0x1873: + return (new Point3D(baseLoc.X, baseLoc.Y + 1, baseLoc.Z), Direction.North); + case 0x1874: + return (new Point3D(baseLoc.X + 1, baseLoc.Y, baseLoc.Z), Direction.East); + + + default: + if (Utility.RandomBool()) + { + return (new Point3D(baseLoc.X - 1, baseLoc.Y, baseLoc.Z), Direction.East); + } + return (new Point3D(baseLoc.X, baseLoc.Y - 1, baseLoc.Z), Direction.South); + } + } + + public void Strike(Mobile from) + { + if (from == null || from.Deleted) return; + + from.Direction = from.GetDirectionTo(Location); + from.Animate(11, 5, 1, true, false, 0); + from.PlaySound(0x13F); + } + + public ButcherHit(Serial serial) : base(serial) + { + } + } +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/SmelterForge.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/SmelterForge.cs index 25911872a..299e57bb5 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/SmelterForge.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/SmelterForge.cs @@ -21,26 +21,21 @@ namespace Server.Items { if (from == null || from.Deleted) return; - // Snap the NPC to face the forge directly from.Direction = from.GetDirectionTo(Location); - // Play the blunt swing animation from.Animate(11, 5, 1, true, false, 0); if (_smeltedItem == null || _smeltedItem.Deleted) { - // Create Ore on the first strike _smeltedItem = new Item(0x19B8); _smeltedItem.Movable = false; _smeltedItem.Name = "smelting ore"; - // Elevate it so it sits on top of the forge _smeltedItem.MoveToWorld(new Point3D(X, Y, Z + 5), Map); from.PlaySound(0x2B); // Metal clink } else { - // Toggle between Ore and Ingots if (_smeltedItem.ItemID == 0x19B8) { _smeltedItem.ItemID = 0x1BF3; @@ -56,7 +51,6 @@ namespace Server.Items } } - // Cleanup: If a GM deletes the forge, delete the visual ore public override void OnDelete() { if (_smeltedItem != null && !_smeltedItem.Deleted) @@ -66,7 +60,6 @@ namespace Server.Items base.OnDelete(); } - // QoL: If a GM moves the forge, bring the visual ore with it public override void OnLocationChange(Point3D oldLocation) { base.OnLocationChange(oldLocation); diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/SmithAnvil.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/SmithAnvil.cs index 6e83ed677..5805408ca 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/SmithAnvil.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/SmithAnvil.cs @@ -7,11 +7,9 @@ namespace Server.Items [SerializationGenerator(0, false)] public partial class AnvilHit : Item { - // Tells ModernUO to automatically save our forged item reference during server saves [SerializableField(0)] private Item _ForgedItem; - // A registry of item graphics to cycle through on the anvil private static readonly int[] _ForgedGraphics = { 0x1BEF, // Iron Ingot @@ -35,32 +33,25 @@ namespace Server.Items { if (from == null || from.Deleted) return; - // Snap the NPC to face the anvil directly from.Direction = from.GetDirectionTo(Location); - // Action 11 is the human animation for swinging a 1-handed blunt weapon from.Animate(11, 5, 1, true, false, 0); from.PlaySound(0x2A); - // Handle the visual forged item on top of the anvil if (_ForgedItem == null || _ForgedItem.Deleted) { - // Create it on the first strike _ForgedItem = new Item(_ForgedGraphics[Utility.Random(_ForgedGraphics.Length)]); _ForgedItem.Movable = false; _ForgedItem.Name = "a forged item"; - // Elevate it by 5 Z-levels so it sits on top of the anvil mesh _ForgedItem.MoveToWorld(new Point3D(X, Y, Z + 5), Map); } else { - // Cycle to a new random graphic with each subsequent strike _ForgedItem.ItemID = _ForgedGraphics[Utility.Random(_ForgedGraphics.Length)]; } } - // Cleanup: If a GM deletes the anvil, delete the forged weapon too public override void OnDelete() { if (_ForgedItem != null && !_ForgedItem.Deleted) @@ -70,7 +61,6 @@ namespace Server.Items base.OnDelete(); } - // QoL: If a GM moves the anvil, bring the forged weapon with it public override void OnLocationChange(Point3D oldLocation) { base.OnLocationChange(oldLocation); diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmanButcher.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmanButcher.cs new file mode 100644 index 000000000..03596dcf3 --- /dev/null +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmanButcher.cs @@ -0,0 +1,77 @@ +using System; +using Server; +using Server.Items; +using ModernUO.Serialization; + +namespace Server.Mobiles +{ + [SerializationGenerator(0, false)] + public partial class TradesmanButcher : TradesmanCitizen + { + private DateTime _NextWork; + private ButcherHit _MyMeat; + + [Constructible] + public TradesmanButcher() + { + Title = "the butcher"; + CantWalk = true; + + _NextWork = DateTime.UtcNow + TimeSpan.FromSeconds(2); + } + + public override void DressTradesman() + { + AddItem(new LongPants(Utility.RandomNeutralHue())); + AddItem(new Boots()); + + AddItem(new FullApron(Utility.RandomList(0x906, 0x8A5, 0x89A))); + + Item cleaver = new Cleaver(); + cleaver.Movable = false; + AddItem(cleaver); + } + + public override void SayRandomChatter() + { + string[] lines = { + "This should last a while.", + "AhHh! Hit bone again.", + "Thankless work, but someone has to do it.", + "Need some quality ribs?" + }; + Say(lines[Utility.Random(lines.Length)]); + } + + public override void OnThink() + { + base.OnThink(); + + if (DateTime.UtcNow >= _NextWork) + { + if (_MyMeat == null || _MyMeat.Deleted) + { + foreach (Item item in GetItemsInRange(1)) + { + if (item is ButcherHit meat) + { + _MyMeat = meat; + break; + } + } + } + + if (_MyMeat != null && !_MyMeat.Deleted) + { + _MyMeat.Strike(this); + } + + _NextWork = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); + } + } + + public TradesmanButcher(Serial serial) : base(serial) + { + } + } +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmanSmelter.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmanSmelter.cs index 114468c56..e3892da87 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmanSmelter.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmanSmelter.cs @@ -25,10 +25,8 @@ namespace Server.Mobiles AddItem(new ShortPants(Utility.RandomNeutralHue())); AddItem(new Boots()); - // Full apron for heat protection AddItem(new FullApron(Utility.RandomList(0x906, 0x8A5, 0x89A))); - // Tongs instead of a hammer Item hammer = new SmithHammer(); hammer.Movable = false; AddItem(hammer); @@ -68,7 +66,6 @@ namespace Server.Mobiles _myForge.Smelt(this); } - // Randomize the pause between smelts _nextWork = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(3, 6)); } } diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmenCitizen.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmenCitizen.cs index 9bf86b61e..9595b0697 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmenCitizen.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/Tradesmen/TradesmenCitizen.cs @@ -43,7 +43,7 @@ namespace Server.Mobiles DressTradesman(); - CantWalk = false; // Allow them to wander + CantWalk = false; _NextChatter = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(10, 25)); }