diff --git a/Distribution/Data/names.json b/Distribution/Data/names.json index 7486d3e6d..d909e50fe 100644 --- a/Distribution/Data/names.json +++ b/Distribution/Data/names.json @@ -606,5 +606,11 @@ "Naranoth", "Lauralare", "Olthonis", "Roth", "Camalanth", "Spath", "Halzanth", "Hrontr", "Takhansa", "Santega", "Lant", "Weth" ] + }, + { + "type": "ghost", + "names": [ + "Omen", "the Lost", "Aldous", "Alistair", "Eleanor", "Gideon", "the Pale" + ] } ] diff --git a/Distribution/Data/signs.cfg b/Distribution/Data/signs.cfg index 5d9e60978..c478f9475 100644 --- a/Distribution/Data/signs.cfg +++ b/Distribution/Data/signs.cfg @@ -1,3 +1,4 @@ +#MirePort 2 3025 358 1241 -1 Mireport Architect 2 2981 350 1276 0 Mireport Tailors 2 2983 353 1286 0 Mireport Tinkers @@ -16,3 +17,10 @@ 2 2997 425 1336 0 Mireport Shipwrights 2 2994 415 1341 0 Mireport Mapmakers 2 3059 412 1350 1 Mireport Fishermen +#Stonehllow +2 2996 758 1212 -5 Stonehollow Inn and Tavern +2 2986 821 1228 -4 Stonehollow Blacksmith +2 3007 733 1248 -4 Stonehollow Weaponsmith +2 3054 805 1262 -4 Stonehollow Miners House +2 2987 745 1289 -4 Stonehollow Healers +2 3024 800 1300 -4 Stonehollow House diff --git a/Info/NeedsFinished.txt b/Info/NeedsFinished.txt index 7fe51bd39..d13caad45 100644 --- a/Info/NeedsFinished.txt +++ b/Info/NeedsFinished.txt @@ -25,7 +25,7 @@ Dungeon Bosses - Duneon Arenas Region Skills - +Signs PortalSpawners - Need to spawn (regon spawner?) - Need to add more mobs. diff --git a/Projects/UOContent/Engines/Spawners/DynamicSpawner/Citizens.cs b/Projects/UOContent/Engines/Spawners/DynamicSpawner/Citizens.cs index e597f0407..af57113a1 100644 --- a/Projects/UOContent/Engines/Spawners/DynamicSpawner/Citizens.cs +++ b/Projects/UOContent/Engines/Spawners/DynamicSpawner/Citizens.cs @@ -59,7 +59,7 @@ namespace Server.Custom.CitizenSpawns } } - private static readonly Type[] Citizens = new Type[] { typeof(Citizen) }; + private static readonly Type[] Citizens = new Type[] { typeof(Citizen), typeof(MonsterCitizen) }; public static Terrain GetTerrain(Map map, Point3D location, int x, int y) { diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/FriendlyMonster.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/FriendlyMonster.cs deleted file mode 100644 index 120449b98..000000000 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/FriendlyMonster.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using Server; -using Server.Mobiles; -using ModernUO.Serialization; - -namespace Server.Mobiles -{ - [SerializationGenerator(0, false)] - public partial class FriendlyTownMonster : BaseCreature - { - private DateTime _NextChatter; - public override bool InitialInnocent => true; - - [Constructible] - public FriendlyTownMonster() : base(AIType.AI_Animal, FightMode.None) - { - Name = NameList.RandomName("orc"); - Title = "the civilized"; - Body = Utility.RandomList(17, 1075, 1072); - BaseSoundID = 0x45A; - - Karma = 1000; - Fame = 1000; - _NextChatter = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(10, 20)); - } - - public override void OnThink() - { - base.OnThink(); - if (Deleted) return; - - if (DateTime.UtcNow > _NextChatter) - { - bool playerNearby = false; - foreach (Mobile m in GetMobilesInRange(8)) - { - if (m != null && m.Player && m.Alive) - { - playerNearby = true; - break; - } - } - - if (playerNearby) - { - string[] lines = { - "*grunts amicably*", - "Me like town. No heroes trying to stab me.", - "Guards no chase me here.", - "You have shiny coins for trading?" - }; - Say(lines[Utility.Random(lines.Length)]); - } - - _NextChatter = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60)); - } - } - - public override bool IsHarmfulCriminal(Mobile target) => true; - - public FriendlyTownMonster(Serial serial) : base(serial) - { - } - } -} diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/GatheringMonster.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/GatheringMonster.cs index 79bda0ef5..e2f6a4b98 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/GatheringMonster.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/GatheringMonster.cs @@ -3,7 +3,7 @@ using Server; namespace Server.Mobiles { - public class GatheringMonster : FriendlyTownMonster + public class GatheringMonster : MonsterCitizen { private Direction _GatherDirection; diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/HumanCitizen.cs similarity index 100% rename from Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens.cs rename to Projects/UOContent/Mobiles/Townfolk/Citizens/HumanCitizen.cs diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/MonsterCitizen.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/MonsterCitizen.cs new file mode 100644 index 000000000..76e6d3204 --- /dev/null +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/MonsterCitizen.cs @@ -0,0 +1,122 @@ +using System; +using Server; +using Server.Mobiles; +using ModernUO.Serialization; + +namespace Server.Mobiles +{ + [SerializationGenerator(0, false)] + public partial class MonsterCitizen : BaseCreature + { + private DateTime _NextChatter; + public override bool InitialInnocent => true; + + private static readonly (int Body, string NameList, int SoundID)[] MonsterProfiles = + { + (17, "orc", 0x45A), // Orc + (1077, "ratman", 437), // Ratman + (35, "lizardman", 417), // Lizardman 1 + (36, "lizardman", 417), // Lizardman 2 + (4, "gargoyle vendor", 372), // Gargoyle + (7, "orc", 0x45A), // Orc Captain + (26, "ghost", 0x482) // Civilized Shade + }; + + [Constructible] + public MonsterCitizen() : base(AIType.AI_Animal, FightMode.None) + { + Title = "the civilized"; + var profile = MonsterProfiles[Utility.Random(MonsterProfiles.Length)]; + Body = profile.Body; + Name = NameList.RandomName(profile.NameList); + BaseSoundID = profile.SoundID; + Karma = 1000; + Fame = 1000; + _NextChatter = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(10, 20)); + } + + public override void OnThink() + { + base.OnThink(); + if (Deleted) return; + + if (DateTime.UtcNow > _NextChatter) + { + bool playerNearby = false; + foreach (Mobile m in GetMobilesInRange(8)) + { + if (m != null && m.Player && m.Alive) + { + playerNearby = true; + break; + } + } + + 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)); + } + } + + // --- NEW: Helper method to organize dialogue by body ID --- + private string[] GetChatterLines() + { + switch ((int)Body) + { + case 17: // Orc + case 7: // Orc Captain + return new string[] { + "*grunts amicably*", + "Me like town. No heroes trying to stab me.", + "Guards no chase me here.", + "You have shiny coins for trading?" + }; + case 1077: // Ratman + return new string[] { + "*sniffs the air*", + "Squeak! The cheese here is much better.", + "Shiny things... you have shiny things?", + "No traps in this town, yes-yes." + }; + case 35: // Lizardman 1 + case 36: // Lizardman 2 + return new string[] { + "*hisses softly*", + "Sun feels warm on scales here.", + "Swamp is cold. Town is good.", + "Sssstay a while." + }; + case 4: // Gargoyle + return new string[] { + "To seek knowledge is the path of wisdom.", + "The humans here are... tolerable.", + "Order must be maintained.", + "Do you require my assistance?" + }; + case 26: // Ghost + return new string[] { + "*wails softly*", + "So cold... but peaceful.", + "Do you remember the old days?", + "I just watch the living scurry about." + }; + default: + return new string[] { + "Lovely weather we're having today.", + "Just another quiet day in town." + }; + } + } + + public override bool IsHarmfulCriminal(Mobile target) => true; + + public MonsterCitizen(Serial serial) : base(serial) + { + } + } +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/TownGatheringSpot.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/TownGatheringSpot.cs index 5aafadf09..2e46e8160 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/TownGatheringSpot.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/TownGatheringSpot.cs @@ -50,10 +50,10 @@ namespace Server.Items } _Attendees.Clear(); - Mobile east = new GatheringCitizen(); - Mobile south = new GatheringCitizen(); - Mobile west = new GatheringMonster(); - Mobile north = new GatheringMonster(); + Mobile east = RandomAttendee(); + Mobile south = RandomAttendee(); + Mobile west = RandomAttendee(); + Mobile north = RandomAttendee(); PlaceAndFace(east, Location.X + 3, Location.Y, Location.Z, Direction.West); PlaceAndFace(west, Location.X - 3, Location.Y, Location.Z, Direction.East); @@ -61,6 +61,18 @@ namespace Server.Items PlaceAndFace(north, Location.X, Location.Y - 3, Location.Z, Direction.South); } + private Mobile RandomAttendee() + { + if (Utility.RandomBool()) + { + return new GatheringCitizen(); + } + else + { + return new GatheringMonster(); + } + } + private void PlaceAndFace(Mobile m, int x, int y, int z, Direction facing) { m.MoveToWorld(new Point3D(x, y, z), Map);