From 717dbd4e1a57e85f00e2a62e26424422ee0cf5d7 Mon Sep 17 00:00:00 2001 From: WarrentyExpired Date: Wed, 15 Jul 2026 18:36:11 -0400 Subject: [PATCH] #W# Add a new kind of towncrier the HintCrier. --- Data/Spawns/towns.map | 2 + Scripts/Commands/BroadcastCrier.cs | 32 ++++++ Scripts/Mobiles/Towns/HintCrier.cs | 149 +++++++++++++++++++++++++++ Scripts/Mobiles/Towns/LordBritish.cs | 84 +++++++++++++++ 4 files changed, 267 insertions(+) create mode 100644 Scripts/Commands/BroadcastCrier.cs create mode 100644 Scripts/Mobiles/Towns/HintCrier.cs create mode 100644 Scripts/Mobiles/Towns/LordBritish.cs diff --git a/Data/Spawns/towns.map b/Data/Spawns/towns.map index a279a2d..e6dc1c3 100644 --- a/Data/Spawns/towns.map +++ b/Data/Spawns/towns.map @@ -114,6 +114,8 @@ *|Guard||||||1853|1572|0|1|0|0|4|4|1|1|0|0|0|0|0 *|Guard||||||1702|1607|0|1|0|0|4|4|1|1|0|0|0|0|0 *|Guard||||||2158|1583|0|1|0|0|4|4|1|1|0|0|0|0|0 +*|LordBritish||||||2029|1475|10|1|5|10|5|0|1|1|0|0|0|0|0 +*|HintCrier||||||2029|1584|0|1|1|1|0|0|1|1|0|0|0|0|0 ## BUCS DEN *|weaver||||||2637|2256|10|1|0|0|2|2|1|1|0|0|0|0|0 *|weaponsmith||||||2687|2241|0|1|0|0|0|0|1|1|0|0|0|0|0 diff --git a/Scripts/Commands/BroadcastCrier.cs b/Scripts/Commands/BroadcastCrier.cs new file mode 100644 index 0000000..7bd41ed --- /dev/null +++ b/Scripts/Commands/BroadcastCrier.cs @@ -0,0 +1,32 @@ +using System; +using Server; +using Server.Commands; +using Server.Mobiles; // Needed to access HintCrier + +namespace Server.Scripts.Commands +{ + public class BroadcastCrierCommand + { + public static void Initialize() + { + // Registers the command so only GameMasters or higher can use it + CommandSystem.Register( "BroadcastCrier", AccessLevel.GameMaster, new CommandEventHandler( BroadcastCrier_OnCommand ) ); + } + + [Usage( "BroadcastCrier " )] + [Description( "Forces all HintCriers to shout a custom message to test the AnnounceEvent method." )] + public static void BroadcastCrier_OnCommand( CommandEventArgs e ) + { + // Make sure the GM actually typed a message + if ( string.IsNullOrWhiteSpace( e.ArgString ) ) + { + e.Mobile.SendMessage( "Usage: [BroadcastCrier " ); + return; + } + + // Pass whatever the GM typed directly into our static AnnounceEvent method + HintCrier.AnnounceEvent( e.ArgString ); + e.Mobile.SendMessage( "Event announced to all Hint Criers." ); + } + } +} diff --git a/Scripts/Mobiles/Towns/HintCrier.cs b/Scripts/Mobiles/Towns/HintCrier.cs new file mode 100644 index 0000000..27380a6 --- /dev/null +++ b/Scripts/Mobiles/Towns/HintCrier.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using Server; +using Server.Items; +using Server.Network; + +namespace Server.Mobiles +{ + public class HintCrier : BaseCreature + { + private static List m_Instances = new List(); + public static List Instances { get { return m_Instances; } } + + // The timer that handles ambient shouting + private Timer m_AutoShoutTimer; + + public static void AnnounceEvent( string message ) + { + foreach ( HintCrier crier in m_Instances ) + { + crier.PublicOverheadMessage( MessageType.Regular, 0x2B, false, message ); + } + } + + private static string[] m_Hints = new string[] + { + "I hear a pure dexterous warrior strikes 10% harder than the rest...", + "They say exceptional weapons have the ability to deal more damage.", + "Rumor has it that some armors have invisible limits to evasion...", + "Walk near the crops and they just might harvest themselves..." + }; + + [Constructable] + public HintCrier() : base( AIType.AI_Vendor, FightMode.None, 10, 1, 0.2, 0.4 ) + { + m_Instances.Add( this ); + + Title = "the town crier"; + Hue = Utility.RandomSkinHue(); + Invulnerable = true; + CantWalk = true; + SpeechHue = 0x31; + WhisperHue = 0x31; + YellHue = 0x31; + + if ( Utility.RandomBool() ) + { + Body = 0x191; + Name = NameList.RandomName( "female" ); + } + else + { + Body = 0x190; + Name = NameList.RandomName( "male" ); + } + + AddItem( new FancyShirt( Utility.RandomBlueHue() ) ); + AddItem( new Kilt( Utility.RandomGreenHue() ) ); + AddItem( new FeatheredHat( Utility.RandomGreenHue() ) ); + AddItem( new ThighBoots() ); + Utility.AssignRandomHair( this ); + + StartTimer(); + } + + public HintCrier( Serial serial ) : base( serial ) + { + m_Instances.Add( this ); + } + + // Starts a looping timer that shouts a hint every 3 to 5 minutes + private void StartTimer() + { + if ( m_AutoShoutTimer == null ) + { + m_AutoShoutTimer = Timer.DelayCall( TimeSpan.FromSeconds( 15.0 ), TimeSpan.FromSeconds( 30.0 ), new TimerCallback( AutoShout_Callback ) ); + } + } + + // Cleans up the timer if the NPC is deleted + private void StopTimer() + { + if ( m_AutoShoutTimer != null ) + { + m_AutoShoutTimer.Stop(); + m_AutoShoutTimer = null; + } + } + + private void AutoShout_Callback() + { + // Only shout if there is a player within 15 tiles to save server resources + bool playerNearby = false; + foreach ( Mobile m in GetMobilesInRange( 15 ) ) + { + if ( m.Player ) + { + playerNearby = true; + break; + } + } + + if ( playerNearby ) + { + string hint = m_Hints[Utility.Random( m_Hints.Length )]; + PublicOverheadMessage( MessageType.Regular, 0x2B, false, hint ); + } + } + + public override bool HandlesOnSpeech( Mobile from ) + { + return ( from.Alive && InRange( from, 12 ) ); + } + + public override void OnSpeech( SpeechEventArgs e ) + { + string speech = e.Speech.ToLower(); + + if ( (e.HasKeyword( 0x30 ) || speech.Contains("hint") || speech.Contains("rumor") || speech.Contains("secret")) && e.Mobile.Alive && InRange( e.Mobile, 12 ) ) + { + Direction = GetDirectionTo( e.Mobile ); + string hint = m_Hints[Utility.Random( m_Hints.Length )]; + PublicOverheadMessage( MessageType.Regular, 0x2B, false, hint ); + } + } + + public override void OnDelete() + { + StopTimer(); + m_Instances.Remove( this ); + base.OnDelete(); + } + + public override void Serialize( GenericWriter writer ) + { + base.Serialize( writer ); + writer.Write( (int) 0 ); // version + } + + public override void Deserialize( GenericReader reader ) + { + base.Deserialize( reader ); + int version = reader.ReadInt(); + + // Restart the timer when the server reboots and loads the NPC + StartTimer(); + } + } +} diff --git a/Scripts/Mobiles/Towns/LordBritish.cs b/Scripts/Mobiles/Towns/LordBritish.cs new file mode 100644 index 0000000..fc2ab92 --- /dev/null +++ b/Scripts/Mobiles/Towns/LordBritish.cs @@ -0,0 +1,84 @@ +using System; +using Server; +using Server.Items; + +namespace Server.Mobiles +{ + public class LordBritish : BaseCreature + { + [Constructable] + public LordBritish() : base( AIType.AI_Vendor, FightMode.None, 10, 1, 0.2, 0.4 ) + { + Name = "Lord British"; + Title = "the Sovereign of Britannia"; + Body = 400; // Human Male body type + HairItemID = 0x203B; + HairHue = 0x44E; + FacialHairItemID = 0x204B; + FacialHairHue = 0x44E; + Hue = 0x83EA; // Standard human skin tone + SpeechHue = 0x3B2; // Royal yellow/gold text when he speaks + + // Make him invulnerable (Set to false if you want players to try and kill him!) + //Blessed = true; + + // Base Stats + SetStr( 100 ); + SetDex( 100 ); + SetInt( 100 ); + + // Base Skills + SetSkill( SkillName.MagicResist, 100.0 ); + SetSkill( SkillName.Swords, 100.0 ); + SetSkill( SkillName.Tactics, 100.0 ); + + + + // Custom colored plate armor (1150 is a bright white/silver hue) + Item chest = new PlateChest(); + chest.Hue = 1150; + AddItem( chest ); + + Item legs = new PlateLegs(); + legs.Hue = 1150; + AddItem( legs ); + + Item arms = new PlateArms(); + arms.Hue = 1150; + AddItem( arms ); + + Item gloves = new PlateGloves(); + gloves.Hue = 1150; + AddItem( gloves ); + + Item gorget = new PlateGorget(); + gorget.Hue = 1150; + AddItem( gorget ); + + // A royal red cloak + Item cloak = new Cloak(); + cloak.Hue = 32; + AddItem( cloak ); + + AddItem( new ThighBoots() ); + } + + public LordBritish( Serial serial ) : base( serial ) + { + } + + public override void Serialize( GenericWriter writer ) + { + base.Serialize( writer ); + + writer.Write( (int) 0 ); // version + } + + public override void Deserialize( GenericReader reader ) + { + base.Deserialize( reader ); + + int version = reader.ReadInt(); + } + } +}