diff --git a/Scripts/Items/Misc/Teleporter.cs b/Scripts/Items/Misc/Teleporter.cs index 530621d33..53d94e19d 100644 --- a/Scripts/Items/Misc/Teleporter.cs +++ b/Scripts/Items/Misc/Teleporter.cs @@ -18,90 +18,93 @@ namespace Server.Items private int m_SoundID; private TimeSpan m_Delay; - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool SourceEffect { - get{ return m_SourceEffect; } - set{ m_SourceEffect = value; InvalidateProperties(); } + get { return m_SourceEffect; } + set { m_SourceEffect = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool DestEffect { - get{ return m_DestEffect; } - set{ m_DestEffect = value; InvalidateProperties(); } + get { return m_DestEffect; } + set { m_DestEffect = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public int SoundID { - get{ return m_SoundID; } - set{ m_SoundID = value; InvalidateProperties(); } + get { return m_SoundID; } + set { m_SoundID = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public TimeSpan Delay { - get{ return m_Delay; } - set{ m_Delay = value; InvalidateProperties(); } + get { return m_Delay; } + set { m_Delay = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool Active { get { return m_Active; } set { m_Active = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public Point3D PointDest { get { return m_PointDest; } set { m_PointDest = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public Map MapDest { get { return m_MapDest; } set { m_MapDest = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool Creatures { get { return m_Creatures; } set { m_Creatures = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool CombatCheck { get { return m_CombatCheck; } set { m_CombatCheck = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool CriminalCheck { get { return m_CriminalCheck; } set { m_CriminalCheck = value; InvalidateProperties(); } } - public override int LabelNumber{ get{ return 1026095; } } // teleporter + public override int LabelNumber { get { return 1026095; } } // teleporter [Constructable] - public Teleporter() : this( new Point3D( 0, 0, 0 ), null, false ) + public Teleporter() + : this(new Point3D(0, 0, 0), null, false) { } [Constructable] - public Teleporter( Point3D pointDest, Map mapDest ) : this( pointDest, mapDest, false ) + public Teleporter(Point3D pointDest, Map mapDest) + : this(pointDest, mapDest, false) { } [Constructable] - public Teleporter( Point3D pointDest, Map mapDest, bool creatures ) : base( 0x1BC3 ) + public Teleporter(Point3D pointDest, Map mapDest, bool creatures) + : base(0x1BC3) { Movable = false; Visible = false; @@ -115,176 +118,177 @@ namespace Server.Items m_CriminalCheck = false; } - public override void GetProperties( ObjectPropertyList list ) + public override void GetProperties(ObjectPropertyList list) { - base.GetProperties( list ); + base.GetProperties(list); - if ( m_Active ) - list.Add( 1060742 ); // active + if (m_Active) + list.Add(1060742); // active else - list.Add( 1060743 ); // inactive + list.Add(1060743); // inactive - if ( m_MapDest != null ) - list.Add( 1060658, "Map\t{0}", m_MapDest ); + if (m_MapDest != null) + list.Add(1060658, "Map\t{0}", m_MapDest); - if ( m_PointDest != Point3D.Zero ) - list.Add( 1060659, "Coords\t{0}", m_PointDest ); + if (m_PointDest != Point3D.Zero) + list.Add(1060659, "Coords\t{0}", m_PointDest); - list.Add( 1060660, "Creatures\t{0}", m_Creatures ? "Yes" : "No" ); + list.Add(1060660, "Creatures\t{0}", m_Creatures ? "Yes" : "No"); } - public override void OnSingleClick( Mobile from ) + public override void OnSingleClick(Mobile from) { - base.OnSingleClick( from ); + base.OnSingleClick(from); - if ( m_Active ) + if (m_Active) { - if ( m_MapDest != null && m_PointDest != Point3D.Zero ) - LabelTo( from, "{0} [{1}]", m_PointDest, m_MapDest ); - else if ( m_MapDest != null ) - LabelTo( from, "[{0}]", m_MapDest ); - else if ( m_PointDest != Point3D.Zero ) - LabelTo( from, m_PointDest.ToString() ); + if (m_MapDest != null && m_PointDest != Point3D.Zero) + LabelTo(from, "{0} [{1}]", m_PointDest, m_MapDest); + else if (m_MapDest != null) + LabelTo(from, "[{0}]", m_MapDest); + else if (m_PointDest != Point3D.Zero) + LabelTo(from, m_PointDest.ToString()); } else { - LabelTo( from, "(inactive)" ); + LabelTo(from, "(inactive)"); } } - public virtual bool CanTeleport( Mobile m ) + public virtual bool CanTeleport(Mobile m) { - if ( !m_Creatures && !m.Player ) + if (!m_Creatures && !m.Player) { return false; } - else if ( m_CriminalCheck && m.Criminal ) + else if (m_CriminalCheck && m.Criminal) { - m.SendLocalizedMessage( 1005561, "", 0x22 ); // Thou'rt a criminal and cannot escape so easily. + m.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. return false; } - else if ( m_CombatCheck && SpellHelper.CheckCombat( m ) ) + else if (m_CombatCheck && SpellHelper.CheckCombat(m)) { - m.SendLocalizedMessage( 1005564, "", 0x22 ); // Wouldst thou flee during the heat of battle?? + m.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? return false; } return true; } - public virtual void StartTeleport( Mobile m ) + public virtual void StartTeleport(Mobile m) { - if ( m_Delay == TimeSpan.Zero ) - DoTeleport( m ); + if (m_Delay == TimeSpan.Zero) + DoTeleport(m); else - Timer.DelayCall( m_Delay, DoTeleport, m ); + Timer.DelayCall(m_Delay, DoTeleport, m); } - public virtual void DoTeleport( Mobile m ) + public virtual void DoTeleport(Mobile m) { Map map = m_MapDest; - if ( map == null || map == Map.Internal ) + if (map == null || map == Map.Internal) map = m.Map; Point3D p = m_PointDest; - if ( p == Point3D.Zero ) + if (p == Point3D.Zero) p = m.Location; - Server.Mobiles.BaseCreature.TeleportPets( m, p, map ); + Server.Mobiles.BaseCreature.TeleportPets(m, p, map); - bool sendEffect = ( !m.Hidden || m.AccessLevel == AccessLevel.Player ); + bool sendEffect = (!m.Hidden || m.AccessLevel == AccessLevel.Player); - if ( m_SourceEffect && sendEffect ) - Effects.SendLocationEffect( m.Location, m.Map, 0x3728, 10, 10 ); + if (m_SourceEffect && sendEffect) + Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10, 10); - m.MoveToWorld( p, map ); + m.MoveToWorld(p, map); - if ( m_DestEffect && sendEffect ) - Effects.SendLocationEffect( m.Location, m.Map, 0x3728, 10, 10 ); + if (m_DestEffect && sendEffect) + Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10, 10); - if ( m_SoundID > 0 && sendEffect ) - Effects.PlaySound( m.Location, m.Map, m_SoundID ); + if (m_SoundID > 0 && sendEffect) + Effects.PlaySound(m.Location, m.Map, m_SoundID); } - public override bool OnMoveOver( Mobile m ) + public override bool OnMoveOver(Mobile m) { - if ( m_Active && CanTeleport( m ) ) + if (m_Active && CanTeleport(m)) { - StartTeleport( m ); + StartTeleport(m); return false; } return true; } - public Teleporter( Serial serial ) : base( serial ) + public Teleporter(Serial serial) + : base(serial) { } - public override void Serialize( GenericWriter writer ) + public override void Serialize(GenericWriter writer) { - base.Serialize( writer ); + base.Serialize(writer); - writer.Write( (int) 4 ); // version + writer.Write((int)4); // version - writer.Write( (bool) m_CriminalCheck ); - writer.Write( (bool) m_CombatCheck ); + writer.Write((bool)m_CriminalCheck); + writer.Write((bool)m_CombatCheck); - writer.Write( (bool) m_SourceEffect ); - writer.Write( (bool) m_DestEffect ); - writer.Write( (TimeSpan) m_Delay ); - writer.WriteEncodedInt( (int) m_SoundID ); + writer.Write((bool)m_SourceEffect); + writer.Write((bool)m_DestEffect); + writer.Write((TimeSpan)m_Delay); + writer.WriteEncodedInt((int)m_SoundID); - writer.Write( m_Creatures ); + writer.Write(m_Creatures); - writer.Write( m_Active ); - writer.Write( m_PointDest ); - writer.Write( m_MapDest ); + writer.Write(m_Active); + writer.Write(m_PointDest); + writer.Write(m_MapDest); } - public override void Deserialize( GenericReader reader ) + public override void Deserialize(GenericReader reader) { - base.Deserialize( reader ); + base.Deserialize(reader); int version = reader.ReadInt(); - switch ( version ) + switch (version) { case 4: - { - m_CriminalCheck = reader.ReadBool(); - goto case 3; - } + { + m_CriminalCheck = reader.ReadBool(); + goto case 3; + } case 3: - { - m_CombatCheck = reader.ReadBool(); - goto case 2; - } + { + m_CombatCheck = reader.ReadBool(); + goto case 2; + } case 2: - { - m_SourceEffect = reader.ReadBool(); - m_DestEffect = reader.ReadBool(); - m_Delay = reader.ReadTimeSpan(); - m_SoundID = reader.ReadEncodedInt(); + { + m_SourceEffect = reader.ReadBool(); + m_DestEffect = reader.ReadBool(); + m_Delay = reader.ReadTimeSpan(); + m_SoundID = reader.ReadEncodedInt(); - goto case 1; - } + goto case 1; + } case 1: - { - m_Creatures = reader.ReadBool(); + { + m_Creatures = reader.ReadBool(); - goto case 0; - } + goto case 0; + } case 0: - { - m_Active = reader.ReadBool(); - m_PointDest = reader.ReadPoint3D(); - m_MapDest = reader.ReadMap(); + { + m_Active = reader.ReadBool(); + m_PointDest = reader.ReadPoint3D(); + m_MapDest = reader.ReadMap(); - break; - } + break; + } } } } @@ -296,56 +300,56 @@ namespace Server.Items private string m_MessageString; private int m_MessageNumber; - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public SkillName Skill { - get{ return m_Skill; } - set{ m_Skill = value; InvalidateProperties(); } + get { return m_Skill; } + set { m_Skill = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public double Required { - get{ return m_Required; } - set{ m_Required = value; InvalidateProperties(); } + get { return m_Required; } + set { m_Required = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public string MessageString { - get{ return m_MessageString; } - set{ m_MessageString = value; InvalidateProperties(); } + get { return m_MessageString; } + set { m_MessageString = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public int MessageNumber { - get{ return m_MessageNumber; } - set{ m_MessageNumber = value; InvalidateProperties(); } + get { return m_MessageNumber; } + set { m_MessageNumber = value; InvalidateProperties(); } } - private void EndMessageLock( object state ) + private void EndMessageLock(object state) { - ((Mobile)state).EndAction( this ); + ((Mobile)state).EndAction(this); } - public override bool CanTeleport( Mobile m ) + public override bool CanTeleport(Mobile m) { - if ( !base.CanTeleport( m ) ) + if (!base.CanTeleport(m)) return false; Skill sk = m.Skills[m_Skill]; - if ( sk == null || sk.Base < m_Required ) + if (sk == null || sk.Base < m_Required) { - if ( m.BeginAction( this ) ) + if (m.BeginAction(this)) { - if ( m_MessageString != null ) - m.Send( new UnicodeMessage( Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", null, m_MessageString ) ); - else if ( m_MessageNumber != 0 ) - m.Send( new MessageLocalized( Serial, ItemID, MessageType.Regular, 0x3B2, 3, m_MessageNumber, null, "" ) ); + if (m_MessageString != null) + m.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", null, m_MessageString)); + else if (m_MessageNumber != 0) + m.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, m_MessageNumber, null, "")); - Timer.DelayCall( TimeSpan.FromSeconds( 5.0 ), new TimerStateCallback( EndMessageLock ), m ); + Timer.DelayCall(TimeSpan.FromSeconds(5.0), new TimerStateCallback(EndMessageLock), m); } return false; @@ -354,24 +358,24 @@ namespace Server.Items return true; } - public override void GetProperties( ObjectPropertyList list ) + public override void GetProperties(ObjectPropertyList list) { - base.GetProperties( list ); + base.GetProperties(list); int skillIndex = (int)m_Skill; string skillName; - if ( skillIndex >= 0 && skillIndex < SkillInfo.Table.Length ) + if (skillIndex >= 0 && skillIndex < SkillInfo.Table.Length) skillName = SkillInfo.Table[skillIndex].Name; else skillName = "(Invalid)"; - list.Add( 1060661, "{0}\t{1:F1}", skillName, m_Required ); + list.Add(1060661, "{0}\t{1:F1}", skillName, m_Required); - if ( m_MessageString != null ) - list.Add( 1060662, "Message\t{0}", m_MessageString ); - else if ( m_MessageNumber != 0 ) - list.Add( 1060662, "Message\t#{0}", m_MessageNumber ); + if (m_MessageString != null) + list.Add(1060662, "Message\t{0}", m_MessageString); + else if (m_MessageNumber != 0) + list.Add(1060662, "Message\t#{0}", m_MessageNumber); } [Constructable] @@ -379,39 +383,40 @@ namespace Server.Items { } - public SkillTeleporter( Serial serial ) : base( serial ) + public SkillTeleporter(Serial serial) + : base(serial) { } - public override void Serialize( GenericWriter writer ) + public override void Serialize(GenericWriter writer) { - base.Serialize( writer ); + base.Serialize(writer); - writer.Write( (int) 0 ); // version + writer.Write((int)0); // version - writer.Write( (int) m_Skill ); - writer.Write( (double) m_Required ); - writer.Write( (string) m_MessageString ); - writer.Write( (int) m_MessageNumber ); + writer.Write((int)m_Skill); + writer.Write((double)m_Required); + writer.Write((string)m_MessageString); + writer.Write((int)m_MessageNumber); } - public override void Deserialize( GenericReader reader ) + public override void Deserialize(GenericReader reader) { - base.Deserialize( reader ); + base.Deserialize(reader); int version = reader.ReadInt(); - switch ( version ) + switch (version) { case 0: - { - m_Skill = (SkillName)reader.ReadInt(); - m_Required = reader.ReadDouble(); - m_MessageString = reader.ReadString(); - m_MessageNumber = reader.ReadInt(); + { + m_Skill = (SkillName)reader.ReadInt(); + m_Required = reader.ReadDouble(); + m_MessageString = reader.ReadString(); + m_MessageNumber = reader.ReadInt(); - break; - } + break; + } } } } @@ -422,77 +427,77 @@ namespace Server.Items private int m_Keyword; private int m_Range; - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public string Substring { - get{ return m_Substring; } - set{ m_Substring = value; InvalidateProperties(); } + get { return m_Substring; } + set { m_Substring = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public int Keyword { - get{ return m_Keyword; } - set{ m_Keyword = value; InvalidateProperties(); } + get { return m_Keyword; } + set { m_Keyword = value; InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public int Range { - get{ return m_Range; } - set{ m_Range = value; InvalidateProperties(); } + get { return m_Range; } + set { m_Range = value; InvalidateProperties(); } } - public override bool HandlesOnSpeech{ get{ return true; } } + public override bool HandlesOnSpeech { get { return true; } } - public override void OnSpeech( SpeechEventArgs e ) + public override void OnSpeech(SpeechEventArgs e) { - if ( !e.Handled && Active ) + if (!e.Handled && Active) { Mobile m = e.Mobile; - if ( !m.InRange( GetWorldLocation(), m_Range ) ) + if (!m.InRange(GetWorldLocation(), m_Range)) return; bool isMatch = false; - if ( m_Keyword >= 0 && e.HasKeyword( m_Keyword ) ) + if (m_Keyword >= 0 && e.HasKeyword(m_Keyword)) isMatch = true; - else if ( m_Substring != null && e.Speech.ToLower().IndexOf( m_Substring.ToLower() ) >= 0 ) + else if (m_Substring != null && e.Speech.ToLower().IndexOf(m_Substring.ToLower()) >= 0) isMatch = true; - if ( !isMatch || !CanTeleport( m ) ) + if (!isMatch || !CanTeleport(m)) return; e.Handled = true; - StartTeleport( m ); + StartTeleport(m); } } - public override void DoTeleport( Mobile m ) + public override void DoTeleport(Mobile m) { - if ( !m.InRange( GetWorldLocation(), m_Range ) || m.Map != Map ) + if (!m.InRange(GetWorldLocation(), m_Range) || m.Map != Map) return; - base.DoTeleport( m ); + base.DoTeleport(m); } - public override bool OnMoveOver( Mobile m ) + public override bool OnMoveOver(Mobile m) { return true; } - public override void GetProperties( ObjectPropertyList list ) + public override void GetProperties(ObjectPropertyList list) { - base.GetProperties( list ); + base.GetProperties(list); - list.Add( 1060661, "Range\t{0}", m_Range ); + list.Add(1060661, "Range\t{0}", m_Range); - if ( m_Keyword >= 0 ) - list.Add( 1060662, "Keyword\t{0}", m_Keyword ); + if (m_Keyword >= 0) + list.Add(1060662, "Keyword\t{0}", m_Keyword); - if ( m_Substring != null ) - list.Add( 1060663, "Substring\t{0}", m_Substring ); + if (m_Substring != null) + list.Add(1060663, "Substring\t{0}", m_Substring); } [Constructable] @@ -502,37 +507,38 @@ namespace Server.Items m_Substring = null; } - public KeywordTeleporter( Serial serial ) : base( serial ) + public KeywordTeleporter(Serial serial) + : base(serial) { } - public override void Serialize( GenericWriter writer ) + public override void Serialize(GenericWriter writer) { - base.Serialize( writer ); + base.Serialize(writer); - writer.Write( (int) 0 ); // version + writer.Write((int)0); // version - writer.Write( m_Substring ); - writer.Write( m_Keyword ); - writer.Write( m_Range ); + writer.Write(m_Substring); + writer.Write(m_Keyword); + writer.Write(m_Range); } - public override void Deserialize( GenericReader reader ) + public override void Deserialize(GenericReader reader) { - base.Deserialize( reader ); + base.Deserialize(reader); int version = reader.ReadInt(); - switch ( version ) + switch (version) { case 0: - { - m_Substring = reader.ReadString(); - m_Keyword = reader.ReadInt(); - m_Range = reader.ReadInt(); + { + m_Substring = reader.ReadString(); + m_Keyword = reader.ReadInt(); + m_Range = reader.ReadInt(); - break; - } + break; + } } } } @@ -545,19 +551,19 @@ namespace Server.Items { m_Table = new Dictionary(); - EventSink.Logout += new LogoutEventHandler( EventSink_Logout ); + EventSink.Logout += new LogoutEventHandler(EventSink_Logout); } - public static void EventSink_Logout( LogoutEventArgs e ) + public static void EventSink_Logout(LogoutEventArgs e) { Mobile from = e.Mobile; TeleportingInfo info; - if ( from == null || !m_Table.TryGetValue( from, out info ) ) + if (from == null || !m_Table.TryGetValue(from, out info)) return; info.Timer.Stop(); - m_Table.Remove( from ); + m_Table.Remove(from); } private int m_StartNumber; @@ -566,35 +572,35 @@ namespace Server.Items private string m_ProgressMessage; private bool m_ShowTimeRemaining; - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public int StartNumber { get { return m_StartNumber; } set { m_StartNumber = value; } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public string StartMessage { get { return m_StartMessage; } set { m_StartMessage = value; } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public int ProgressNumber { get { return m_ProgressNumber; } set { m_ProgressNumber = value; } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public string ProgressMessage { get { return m_ProgressMessage; } set { m_ProgressMessage = value; } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool ShowTimeRemaining { get { return m_ShowTimeRemaining; } @@ -606,47 +612,47 @@ namespace Server.Items { } - public static string FormatTime( TimeSpan ts ) + public static string FormatTime(TimeSpan ts) { - if ( ts.TotalHours >= 1 ) + if (ts.TotalHours >= 1) { - int h = (int)Math.Round( ts.TotalHours ); - return String.Format( "{0} hour{1}", h, ( h == 1 ) ? "" : "s" ); + int h = (int)Math.Round(ts.TotalHours); + return String.Format("{0} hour{1}", h, (h == 1) ? "" : "s"); } - else if ( ts.TotalMinutes >= 1 ) + else if (ts.TotalMinutes >= 1) { - int m = (int)Math.Round( ts.TotalMinutes ); - return String.Format( "{0} minute{1}", m, ( m == 1 ) ? "" : "s" ); + int m = (int)Math.Round(ts.TotalMinutes); + return String.Format("{0} minute{1}", m, (m == 1) ? "" : "s"); } - int s = Math.Max( (int)Math.Round( ts.TotalSeconds ), 0 ); - return String.Format( "{0} second{1}", s, ( s == 1 ) ? "" : "s" ); + int s = Math.Max((int)Math.Round(ts.TotalSeconds), 0); + return String.Format("{0} second{1}", s, (s == 1) ? "" : "s"); } - private void EndLock( Mobile m ) + private void EndLock(Mobile m) { - m.EndAction( this ); + m.EndAction(this); } - public override void StartTeleport( Mobile m ) + public override void StartTeleport(Mobile m) { TeleportingInfo info; - if ( m_Table.TryGetValue( m, out info ) ) + if (m_Table.TryGetValue(m, out info)) { - if ( info.Teleporter == this ) + if (info.Teleporter == this) { - if ( m.BeginAction( this ) ) + if (m.BeginAction(this)) { - if ( m_ProgressMessage != null ) - m.SendMessage( m_ProgressMessage ); - else if ( m_ProgressNumber != 0 ) - m.SendLocalizedMessage( m_ProgressNumber ); + if (m_ProgressMessage != null) + m.SendMessage(m_ProgressMessage); + else if (m_ProgressNumber != 0) + m.SendLocalizedMessage(m_ProgressNumber); - if ( m_ShowTimeRemaining ) - m.SendMessage( "Time remaining: {0}", FormatTime( m_Table[m].Timer.Next - DateTime.Now ) ); + if (m_ShowTimeRemaining) + m.SendMessage("Time remaining: {0}", FormatTime(m_Table[m].Timer.Next - DateTime.Now)); - Timer.DelayCall( TimeSpan.FromSeconds( 5 ), EndLock, m ); + Timer.DelayCall(TimeSpan.FromSeconds(5), EndLock, m); } return; @@ -657,44 +663,45 @@ namespace Server.Items } } - if ( m_StartMessage != null ) - m.SendMessage( m_StartMessage ); - else if ( m_StartNumber != 0 ) - m.SendLocalizedMessage( m_StartNumber ); + if (m_StartMessage != null) + m.SendMessage(m_StartMessage); + else if (m_StartNumber != 0) + m.SendLocalizedMessage(m_StartNumber); - if ( Delay == TimeSpan.Zero ) - DoTeleport( m ); + if (Delay == TimeSpan.Zero) + DoTeleport(m); else - m_Table[m] = new TeleportingInfo( this, Timer.DelayCall( Delay, DoTeleport, m ) ); + m_Table[m] = new TeleportingInfo(this, Timer.DelayCall(Delay, DoTeleport, m)); } - public override void DoTeleport( Mobile m ) + public override void DoTeleport(Mobile m) { - m_Table.Remove( m ); + m_Table.Remove(m); - base.DoTeleport( m ); + base.DoTeleport(m); } - public WaitTeleporter( Serial serial ) : base( serial ) + public WaitTeleporter(Serial serial) + : base(serial) { } - public override void Serialize( GenericWriter writer ) + public override void Serialize(GenericWriter writer) { - base.Serialize( writer ); + base.Serialize(writer); - writer.Write( (int) 0 ); // version + writer.Write((int)0); // version - writer.Write( m_StartNumber ); - writer.Write( m_StartMessage ); - writer.Write( m_ProgressNumber ); - writer.Write( m_ProgressMessage ); - writer.Write( m_ShowTimeRemaining ); + writer.Write(m_StartNumber); + writer.Write(m_StartMessage); + writer.Write(m_ProgressNumber); + writer.Write(m_ProgressMessage); + writer.Write(m_ShowTimeRemaining); } - public override void Deserialize( GenericReader reader ) + public override void Deserialize(GenericReader reader) { - base.Deserialize( reader ); + base.Deserialize(reader); int version = reader.ReadInt(); @@ -713,7 +720,7 @@ namespace Server.Items public WaitTeleporter Teleporter { get { return m_Teleporter; } } public Timer Timer { get { return m_Timer; } } - public TeleportingInfo( WaitTeleporter tele, Timer t ) + public TeleportingInfo(WaitTeleporter tele, Timer t) { m_Teleporter = tele; m_Timer = t; @@ -726,7 +733,7 @@ namespace Server.Items private TimeSpan m_TimeoutDelay; private Dictionary m_Teleporting; - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public TimeSpan TimeoutDelay { get { return m_TimeoutDelay; } @@ -735,93 +742,93 @@ namespace Server.Items [Constructable] public TimeoutTeleporter() - : this( new Point3D( 0, 0, 0 ), null, false ) + : this(new Point3D(0, 0, 0), null, false) { } [Constructable] - public TimeoutTeleporter( Point3D pointDest, Map mapDest ) - : this( pointDest, mapDest, false ) + public TimeoutTeleporter(Point3D pointDest, Map mapDest) + : this(pointDest, mapDest, false) { } [Constructable] - public TimeoutTeleporter( Point3D pointDest, Map mapDest, bool creatures ) - : base( pointDest, mapDest, creatures ) + public TimeoutTeleporter(Point3D pointDest, Map mapDest, bool creatures) + : base(pointDest, mapDest, creatures) { m_Teleporting = new Dictionary(); } - public void StartTimer( Mobile m ) + public void StartTimer(Mobile m) { - StartTimer( m, m_TimeoutDelay ); + StartTimer(m, m_TimeoutDelay); } - private void StartTimer( Mobile m, TimeSpan delay ) + private void StartTimer(Mobile m, TimeSpan delay) { Timer t; - if ( m_Teleporting.TryGetValue( m, out t ) ) + if (m_Teleporting.TryGetValue(m, out t)) t.Stop(); - m_Teleporting[m] = Timer.DelayCall( delay, StartTeleport, m ); + m_Teleporting[m] = Timer.DelayCall(delay, StartTeleport, m); } - public void StopTimer( Mobile m ) + public void StopTimer(Mobile m) { Timer t; - if ( m_Teleporting.TryGetValue( m, out t ) ) + if (m_Teleporting.TryGetValue(m, out t)) { t.Stop(); - m_Teleporting.Remove( m ); + m_Teleporting.Remove(m); } } - public override void DoTeleport( Mobile m ) + public override void DoTeleport(Mobile m) { - m_Teleporting.Remove( m ); + m_Teleporting.Remove(m); - base.DoTeleport( m ); + base.DoTeleport(m); } - public override bool OnMoveOver( Mobile m ) + public override bool OnMoveOver(Mobile m) { - if ( Active ) + if (Active) { - if ( !CanTeleport( m ) ) + if (!CanTeleport(m)) return false; - StartTimer( m ); + StartTimer(m); } return true; } - public TimeoutTeleporter( Serial serial ) - : base( serial ) + public TimeoutTeleporter(Serial serial) + : base(serial) { } - public override void Serialize( GenericWriter writer ) + public override void Serialize(GenericWriter writer) { - base.Serialize( writer ); + base.Serialize(writer); - writer.Write( (int) 0 ); // version + writer.Write((int)0); // version - writer.Write( m_TimeoutDelay ); - writer.Write( m_Teleporting.Count ); + writer.Write(m_TimeoutDelay); + writer.Write(m_Teleporting.Count); - foreach ( KeyValuePair kvp in m_Teleporting ) + foreach (KeyValuePair kvp in m_Teleporting) { - writer.Write( kvp.Key ); - writer.Write( kvp.Value.Next ); + writer.Write(kvp.Key); + writer.Write(kvp.Value.Next); } } - public override void Deserialize( GenericReader reader ) + public override void Deserialize(GenericReader reader) { - base.Deserialize( reader ); + base.Deserialize(reader); int version = reader.ReadInt(); @@ -830,12 +837,12 @@ namespace Server.Items int count = reader.ReadInt(); - for ( int i = 0; i < count; ++i ) + for (int i = 0; i < count; ++i) { Mobile m = reader.ReadMobile(); DateTime end = reader.ReadDateTime(); - StartTimer( m, end - DateTime.Now ); + StartTimer(m, end - DateTime.Now); } } } @@ -844,7 +851,7 @@ namespace Server.Items { private TimeoutTeleporter m_Teleporter; - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public TimeoutTeleporter Teleporter { get { return m_Teleporter; } @@ -853,7 +860,7 @@ namespace Server.Items [Constructable] public TimeoutGoal() - : base( 0x1822 ) + : base(0x1822) { Movable = false; Visible = false; @@ -861,10 +868,10 @@ namespace Server.Items Hue = 1154; } - public override bool OnMoveOver( Mobile m ) + public override bool OnMoveOver(Mobile m) { - if ( m_Teleporter != null ) - m_Teleporter.StopTimer( m ); + if (m_Teleporter != null) + m_Teleporter.StopTimer(m); return true; } @@ -874,23 +881,23 @@ namespace Server.Items get { return "timeout teleporter goal"; } } - public TimeoutGoal( Serial serial ) - : base( serial ) + public TimeoutGoal(Serial serial) + : base(serial) { } - public override void Serialize( GenericWriter writer ) + public override void Serialize(GenericWriter writer) { - base.Serialize( writer ); + base.Serialize(writer); - writer.Write( (int) 0 ); // version + writer.Write((int)0); // version - writer.WriteItem( m_Teleporter ); + writer.WriteItem(m_Teleporter); } - public override void Deserialize( GenericReader reader ) + public override void Deserialize(GenericReader reader) { - base.Deserialize( reader ); + base.Deserialize(reader); int version = reader.ReadInt(); @@ -903,127 +910,127 @@ namespace Server.Items [Flags] protected enum ConditionFlag { - None = 0x00, - DenyMounted = 0x01, - DenyFollowers = 0x02, - DenyPackContents = 0x04, - DenyHolding = 0x08, - DenyEquipment = 0x10, - DenyTransformed = 0x20, - StaffOnly = 0x40 + None = 0x00, + DenyMounted = 0x01, + DenyFollowers = 0x02, + DenyPackContents = 0x04, + DenyHolding = 0x08, + DenyEquipment = 0x10, + DenyTransformed = 0x20, + StaffOnly = 0x40 } private ConditionFlag m_Flags; - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool DenyMounted { - get{ return GetFlag( ConditionFlag.DenyMounted ); } - set{ SetFlag( ConditionFlag.DenyMounted, value ); InvalidateProperties(); } + get { return GetFlag(ConditionFlag.DenyMounted); } + set { SetFlag(ConditionFlag.DenyMounted, value); InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool DenyFollowers { - get{ return GetFlag( ConditionFlag.DenyFollowers ); } - set{ SetFlag( ConditionFlag.DenyFollowers, value ); InvalidateProperties(); } + get { return GetFlag(ConditionFlag.DenyFollowers); } + set { SetFlag(ConditionFlag.DenyFollowers, value); InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool DenyPackContents { - get{ return GetFlag( ConditionFlag.DenyPackContents ); } - set{ SetFlag( ConditionFlag.DenyPackContents, value ); InvalidateProperties(); } + get { return GetFlag(ConditionFlag.DenyPackContents); } + set { SetFlag(ConditionFlag.DenyPackContents, value); InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool DenyHolding { - get{ return GetFlag( ConditionFlag.DenyHolding ); } - set{ SetFlag( ConditionFlag.DenyHolding, value ); InvalidateProperties(); } + get { return GetFlag(ConditionFlag.DenyHolding); } + set { SetFlag(ConditionFlag.DenyHolding, value); InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool DenyEquipment { - get{ return GetFlag( ConditionFlag.DenyEquipment ); } - set{ SetFlag( ConditionFlag.DenyEquipment, value ); InvalidateProperties(); } + get { return GetFlag(ConditionFlag.DenyEquipment); } + set { SetFlag(ConditionFlag.DenyEquipment, value); InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool DenyTransformed { - get{ return GetFlag( ConditionFlag.DenyTransformed ); } - set{ SetFlag( ConditionFlag.DenyTransformed, value ); InvalidateProperties(); } + get { return GetFlag(ConditionFlag.DenyTransformed); } + set { SetFlag(ConditionFlag.DenyTransformed, value); InvalidateProperties(); } } - [CommandProperty( AccessLevel.GameMaster )] + [CommandProperty(AccessLevel.GameMaster)] public bool StaffOnly { - get{ return GetFlag( ConditionFlag.StaffOnly ); } - set{ SetFlag( ConditionFlag.StaffOnly, value ); InvalidateProperties(); } + get { return GetFlag(ConditionFlag.StaffOnly); } + set { SetFlag(ConditionFlag.StaffOnly, value); InvalidateProperties(); } } - public override bool CanTeleport( Mobile m ) + public override bool CanTeleport(Mobile m) { - if ( !base.CanTeleport( m ) ) + if (!base.CanTeleport(m)) return false; - if ( GetFlag( ConditionFlag.StaffOnly ) && m.AccessLevel < AccessLevel.Counselor ) + if (GetFlag(ConditionFlag.StaffOnly) && m.AccessLevel < AccessLevel.Counselor) return false; - if ( GetFlag( ConditionFlag.DenyMounted ) && m.Mounted ) + if (GetFlag(ConditionFlag.DenyMounted) && m.Mounted) { - m.SendLocalizedMessage( 1077252 ); // You must dismount before proceeding. + m.SendLocalizedMessage(1077252); // You must dismount before proceeding. return false; } - if ( GetFlag( ConditionFlag.DenyFollowers ) && ( m.Followers != 0 || ( m is PlayerMobile && ( (PlayerMobile) m ).AutoStabled.Count != 0 ) ) ) + if (GetFlag(ConditionFlag.DenyFollowers) && (m.Followers != 0 || (m is PlayerMobile && ((PlayerMobile)m).AutoStabled.Count != 0))) { - m.SendLocalizedMessage( 1077250 ); // No pets permitted beyond this point. + m.SendLocalizedMessage(1077250); // No pets permitted beyond this point. return false; } Container pack; - if ( GetFlag( ConditionFlag.DenyPackContents ) && ( pack = m.Backpack ) != null && pack.TotalItems != 0 ) + if (GetFlag(ConditionFlag.DenyPackContents) && (pack = m.Backpack) != null && pack.TotalItems != 0) { - m.SendMessage( "You must empty your backpack before proceeding." ); + m.SendMessage("You must empty your backpack before proceeding."); return false; } - if ( GetFlag( ConditionFlag.DenyHolding ) && m.Holding != null ) + if (GetFlag(ConditionFlag.DenyHolding) && m.Holding != null) { - m.SendMessage( "You must let go of what you are holding before proceeding." ); + m.SendMessage("You must let go of what you are holding before proceeding."); return false; } - if ( GetFlag( ConditionFlag.DenyEquipment ) ) + if (GetFlag(ConditionFlag.DenyEquipment)) { - foreach ( Item item in m.Items ) + foreach (Item item in m.Items) { - switch ( item.Layer ) + switch (item.Layer) { case Layer.Hair: case Layer.FacialHair: case Layer.Backpack: case Layer.Mount: case Layer.Bank: - { - continue; // ignore - } + { + continue; // ignore + } default: - { - m.SendMessage( "You must remove all of your equipment before proceeding." ); - return false; - } + { + m.SendMessage("You must remove all of your equipment before proceeding."); + return false; + } } } } - if ( GetFlag( ConditionFlag.DenyTransformed ) && m.IsBodyMod ) + if (GetFlag(ConditionFlag.DenyTransformed) && m.IsBodyMod) { - m.SendMessage( "You cannot go there in this form." ); + m.SendMessage("You cannot go there in this form."); return false; } @@ -1035,71 +1042,71 @@ namespace Server.Items { } - public override void GetProperties( ObjectPropertyList list ) + public override void GetProperties(ObjectPropertyList list) { - base.GetProperties( list ); + base.GetProperties(list); StringBuilder props = new StringBuilder(); - if ( GetFlag( ConditionFlag.DenyMounted ) ) - props.Append( "
Deny Mounted" ); + if (GetFlag(ConditionFlag.DenyMounted)) + props.Append("
Deny Mounted"); - if ( GetFlag( ConditionFlag.DenyFollowers ) ) - props.Append( "
Deny Followers" ); + if (GetFlag(ConditionFlag.DenyFollowers)) + props.Append("
Deny Followers"); - if ( GetFlag( ConditionFlag.DenyPackContents ) ) - props.Append( "
Deny Pack Contents" ); + if (GetFlag(ConditionFlag.DenyPackContents)) + props.Append("
Deny Pack Contents"); - if ( GetFlag( ConditionFlag.DenyHolding ) ) - props.Append( "
Deny Holding" ); + if (GetFlag(ConditionFlag.DenyHolding)) + props.Append("
Deny Holding"); - if ( GetFlag( ConditionFlag.DenyEquipment ) ) - props.Append( "
Deny Equipment" ); + if (GetFlag(ConditionFlag.DenyEquipment)) + props.Append("
Deny Equipment"); - if ( GetFlag( ConditionFlag.DenyTransformed ) ) - props.Append( "
Deny Transformed" ); + if (GetFlag(ConditionFlag.DenyTransformed)) + props.Append("
Deny Transformed"); - if ( GetFlag( ConditionFlag.StaffOnly ) ) - props.Append( "
Staff Only" ); + if (GetFlag(ConditionFlag.StaffOnly)) + props.Append("
Staff Only"); - if ( props.Length != 0 ) + if (props.Length != 0) { - props.Remove( 0, 4 ); - list.Add( props.ToString() ); + props.Remove(0, 4); + list.Add(props.ToString()); } } - public ConditionTeleporter( Serial serial ) - : base( serial ) + public ConditionTeleporter(Serial serial) + : base(serial) { } - public override void Serialize( GenericWriter writer ) + public override void Serialize(GenericWriter writer) { - base.Serialize( writer ); + base.Serialize(writer); - writer.Write( (int) 0 ); // version + writer.Write((int)0); // version - writer.Write( (int) m_Flags ); + writer.Write((int)m_Flags); } - public override void Deserialize( GenericReader reader ) + public override void Deserialize(GenericReader reader) { - base.Deserialize( reader ); + base.Deserialize(reader); int version = reader.ReadInt(); - m_Flags = (ConditionFlag) reader.ReadInt(); + m_Flags = (ConditionFlag)reader.ReadInt(); } - protected bool GetFlag( ConditionFlag flag ) + protected bool GetFlag(ConditionFlag flag) { - return ( ( m_Flags & flag ) != 0 ); + return ((m_Flags & flag) != 0); } - protected void SetFlag( ConditionFlag flag, bool value ) + protected void SetFlag(ConditionFlag flag, bool value) { - if ( value ) + if (value) m_Flags |= flag; else m_Flags &= ~flag; diff --git a/Scripts/Mobiles/AI/BaseAI.cs b/Scripts/Mobiles/AI/BaseAI.cs index 2ea1820f8..d6b235d71 100644 --- a/Scripts/Mobiles/AI/BaseAI.cs +++ b/Scripts/Mobiles/AI/BaseAI.cs @@ -1,308 +1,308 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using Server; -using Server.Items; -using Server.Targeting; -using Server.Targets; -using Server.Network; -using Server.Regions; -using Server.ContextMenus; -using Server.Engines.Quests; -using Server.Engines.Quests.Necro; -using MoveImpl=Server.Movement.MovementImpl; -using Server.Spells; -using Server.Spells.Spellweaving; - -namespace Server.Mobiles -{ - public enum AIType - { - AI_Use_Default, - AI_Melee, - AI_Animal, - AI_Archer, - AI_Healer, - AI_Vendor, - AI_Mage, - AI_Berserk, - AI_Predator, - AI_Thief - } - - public enum ActionType - { - Wander, - Combat, - Guard, - Flee, - Backoff, - Interact - } - - public abstract class BaseAI - { - public Timer m_Timer; - protected ActionType m_Action; - private DateTime m_NextStopGuard; - - public BaseCreature m_Mobile; - - public BaseAI( BaseCreature m ) - { - m_Mobile = m; - - m_Timer = new AITimer( this ); - - bool activate; - - if( !m.PlayerRangeSensitive ) - activate = true; - else if( World.Loading ) - activate = false; - else if( m.Map == null || m.Map == Map.Internal || !m.Map.GetSector( m ).Active ) - activate = false; - else - activate = true; - - if( activate ) - m_Timer.Start(); - - Action = ActionType.Wander; - } - - public ActionType Action - { - get - { - return m_Action; - } - set - { - m_Action = value; - OnActionChanged(); - } - } - - public virtual bool WasNamed( string speech ) - { - string name = m_Mobile.Name; - - return (name != null && Insensitive.StartsWith( speech, name )); - } - - private class InternalEntry : ContextMenuEntry - { - private Mobile m_From; - private BaseCreature m_Mobile; - private BaseAI m_AI; - private OrderType m_Order; - - public InternalEntry( Mobile from, int number, int range, BaseCreature mobile, BaseAI ai, OrderType order ) - : base( number, range ) - { - m_From = from; - m_Mobile = mobile; - m_AI = ai; - m_Order = order; - - if( mobile.IsDeadPet && (order == OrderType.Guard || order == OrderType.Attack || order == OrderType.Transfer || order == OrderType.Drop) ) - Enabled = false; - } - - public override void OnClick() - { - if( !m_Mobile.Deleted && m_Mobile.Controlled && m_From.CheckAlive() ) - { - if( m_Mobile.IsDeadPet && (m_Order == OrderType.Guard || m_Order == OrderType.Attack || m_Order == OrderType.Transfer || m_Order == OrderType.Drop) ) - return; - - bool isOwner = (m_From == m_Mobile.ControlMaster); - bool isFriend = (!isOwner && m_Mobile.IsPetFriend( m_From )); - - if( !isOwner && !isFriend ) - return; - else if( isFriend && m_Order != OrderType.Follow && m_Order != OrderType.Stay && m_Order != OrderType.Stop ) - return; - - switch( m_Order ) - { - case OrderType.Follow: - case OrderType.Attack: - case OrderType.Transfer: - case OrderType.Friend: - case OrderType.Unfriend: - { - if( m_Order == OrderType.Transfer && m_From.HasTrade ) - m_From.SendLocalizedMessage( 1010507 ); // You cannot transfer a pet with a trade pending - else if( m_Order == OrderType.Friend && m_From.HasTrade ) - m_From.SendLocalizedMessage( 1070947 ); // You cannot friend a pet with a trade pending - else - m_AI.BeginPickTarget( m_From, m_Order ); - - break; - } - case OrderType.Release: - { - if( m_Mobile.Summoned ) - goto default; - else - m_From.SendGump( new Gumps.ConfirmReleaseGump( m_From, m_Mobile ) ); - - break; - } - default: - { - if( m_Mobile.CheckControlChance( m_From ) ) - m_Mobile.ControlOrder = m_Order; - - break; - } - } - } - } - } - - public virtual void GetContextMenuEntries( Mobile from, List list ) - { - if( from.Alive && m_Mobile.Controlled && from.InRange( m_Mobile, 14 ) ) - { - if( from == m_Mobile.ControlMaster ) - { - list.Add( new InternalEntry( from, 6107, 14, m_Mobile, this, OrderType.Guard ) ); // Command: Guard - list.Add( new InternalEntry( from, 6108, 14, m_Mobile, this, OrderType.Follow ) ); // Command: Follow - - if( m_Mobile.CanDrop ) - list.Add( new InternalEntry( from, 6109, 14, m_Mobile, this, OrderType.Drop ) ); // Command: Drop - - list.Add( new InternalEntry( from, 6111, 14, m_Mobile, this, OrderType.Attack ) ); // Command: Kill - - list.Add( new InternalEntry( from, 6112, 14, m_Mobile, this, OrderType.Stop ) ); // Command: Stop - list.Add( new InternalEntry( from, 6114, 14, m_Mobile, this, OrderType.Stay ) ); // Command: Stay - - if( !m_Mobile.Summoned && !( m_Mobile is GrizzledMare ) ) - { - list.Add( new InternalEntry( from, 6110, 14, m_Mobile, this, OrderType.Friend ) ); // Add Friend - list.Add( new InternalEntry( from, 6099, 14, m_Mobile, this, OrderType.Unfriend ) ); // Remove Friend - list.Add( new InternalEntry( from, 6113, 14, m_Mobile, this, OrderType.Transfer ) ); // Transfer - } - - list.Add( new InternalEntry( from, 6118, 14, m_Mobile, this, OrderType.Release ) ); // Release - } - else if( m_Mobile.IsPetFriend( from ) ) - { - list.Add( new InternalEntry( from, 6108, 14, m_Mobile, this, OrderType.Follow ) ); // Command: Follow - list.Add( new InternalEntry( from, 6112, 14, m_Mobile, this, OrderType.Stop ) ); // Command: Stop - list.Add( new InternalEntry( from, 6114, 14, m_Mobile, this, OrderType.Stay ) ); // Command: Stay - } - } - } - - public virtual void BeginPickTarget( Mobile from, OrderType order ) - { - if( m_Mobile.Deleted || !m_Mobile.Controlled || !from.InRange( m_Mobile, 14 ) || from.Map != m_Mobile.Map ) - return; - - bool isOwner = (from == m_Mobile.ControlMaster); - bool isFriend = (!isOwner && m_Mobile.IsPetFriend( from )); - - if( !isOwner && !isFriend ) - return; - else if( isFriend && order != OrderType.Follow && order != OrderType.Stay && order != OrderType.Stop ) - return; - - if( from.Target == null ) - { - if( order == OrderType.Transfer ) - from.SendLocalizedMessage( 502038 ); // Click on the person to transfer ownership to. - else if( order == OrderType.Friend ) - from.SendLocalizedMessage( 502020 ); // Click on the player whom you wish to make a co-owner. - else if( order == OrderType.Unfriend ) - from.SendLocalizedMessage( 1070948 ); // Click on the player whom you wish to remove as a co-owner. - - from.Target = new AIControlMobileTarget( this, order ); - } - else if( from.Target is AIControlMobileTarget ) - { - AIControlMobileTarget t = (AIControlMobileTarget)from.Target; - - if( t.Order == order ) - t.AddAI( this ); - } - } - - public virtual void OnAggressiveAction( Mobile aggressor ) - { - Mobile currentCombat = m_Mobile.Combatant; - - if( currentCombat != null && !aggressor.Hidden && currentCombat != aggressor && m_Mobile.GetDistanceToSqrt( currentCombat ) > m_Mobile.GetDistanceToSqrt( aggressor ) ) - m_Mobile.Combatant = aggressor; - } - - public virtual void EndPickTarget( Mobile from, Mobile target, OrderType order ) - { - if( m_Mobile.Deleted || !m_Mobile.Controlled || !from.InRange( m_Mobile, 14 ) || from.Map != m_Mobile.Map || !from.CheckAlive() ) - return; - - bool isOwner = (from == m_Mobile.ControlMaster); - bool isFriend = (!isOwner && m_Mobile.IsPetFriend( from )); - - if( !isOwner && !isFriend ) - return; - else if( isFriend && order != OrderType.Follow && order != OrderType.Stay && order != OrderType.Stop ) - return; - - if( order == OrderType.Attack ) - { - if( target is BaseCreature && ((BaseCreature)target).IsScaryToPets && m_Mobile.IsScaredOfScaryThings ) - { - m_Mobile.SayTo( from, "Your pet refuses to attack this creature!" ); - return; - } - - if( (SolenHelper.CheckRedFriendship( from ) && - (target is RedSolenInfiltratorQueen - || target is RedSolenInfiltratorWarrior - || target is RedSolenQueen - || target is RedSolenWarrior - || target is RedSolenWorker)) - || (SolenHelper.CheckBlackFriendship( from ) && - (target is BlackSolenInfiltratorQueen - || target is BlackSolenInfiltratorWarrior - || target is BlackSolenQueen - || target is BlackSolenWarrior - || target is BlackSolenWorker)) ) - { - from.SendAsciiMessage( "You can not force your pet to attack a creature you are protected from." ); - return; - } - - if( target is Factions.BaseFactionGuard ) - { - m_Mobile.SayTo( from, "Your pet refuses to attack the guard." ); - return; - } - } - - if( m_Mobile.CheckControlChance( from ) ) - { - m_Mobile.ControlTarget = target; - m_Mobile.ControlOrder = order; - } - } - - public virtual bool HandlesOnSpeech( Mobile from ) - { - if( from.AccessLevel >= AccessLevel.GameMaster ) - return true; - - if( from.Alive && m_Mobile.Controlled && m_Mobile.Commandable && (from == m_Mobile.ControlMaster || m_Mobile.IsPetFriend( from )) ) - return true; - - return (from.Alive && from.InRange( m_Mobile.Location, 3 ) && m_Mobile.IsHumanInTown()); - } - +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using Server; +using Server.Items; +using Server.Targeting; +using Server.Targets; +using Server.Network; +using Server.Regions; +using Server.ContextMenus; +using Server.Engines.Quests; +using Server.Engines.Quests.Necro; +using MoveImpl = Server.Movement.MovementImpl; +using Server.Spells; +using Server.Spells.Spellweaving; + +namespace Server.Mobiles +{ + public enum AIType + { + AI_Use_Default, + AI_Melee, + AI_Animal, + AI_Archer, + AI_Healer, + AI_Vendor, + AI_Mage, + AI_Berserk, + AI_Predator, + AI_Thief + } + + public enum ActionType + { + Wander, + Combat, + Guard, + Flee, + Backoff, + Interact + } + + public abstract class BaseAI + { + public Timer m_Timer; + protected ActionType m_Action; + private DateTime m_NextStopGuard; + + public BaseCreature m_Mobile; + + public BaseAI(BaseCreature m) + { + m_Mobile = m; + + m_Timer = new AITimer(this); + + bool activate; + + if (!m.PlayerRangeSensitive) + activate = true; + else if (World.Loading) + activate = false; + else if (m.Map == null || m.Map == Map.Internal || !m.Map.GetSector(m).Active) + activate = false; + else + activate = true; + + if (activate) + m_Timer.Start(); + + Action = ActionType.Wander; + } + + public ActionType Action + { + get + { + return m_Action; + } + set + { + m_Action = value; + OnActionChanged(); + } + } + + public virtual bool WasNamed(string speech) + { + string name = m_Mobile.Name; + + return (name != null && Insensitive.StartsWith(speech, name)); + } + + private class InternalEntry : ContextMenuEntry + { + private Mobile m_From; + private BaseCreature m_Mobile; + private BaseAI m_AI; + private OrderType m_Order; + + public InternalEntry(Mobile from, int number, int range, BaseCreature mobile, BaseAI ai, OrderType order) + : base(number, range) + { + m_From = from; + m_Mobile = mobile; + m_AI = ai; + m_Order = order; + + if (mobile.IsDeadPet && (order == OrderType.Guard || order == OrderType.Attack || order == OrderType.Transfer || order == OrderType.Drop)) + Enabled = false; + } + + public override void OnClick() + { + if (!m_Mobile.Deleted && m_Mobile.Controlled && m_From.CheckAlive()) + { + if (m_Mobile.IsDeadPet && (m_Order == OrderType.Guard || m_Order == OrderType.Attack || m_Order == OrderType.Transfer || m_Order == OrderType.Drop)) + return; + + bool isOwner = (m_From == m_Mobile.ControlMaster); + bool isFriend = (!isOwner && m_Mobile.IsPetFriend(m_From)); + + if (!isOwner && !isFriend) + return; + else if (isFriend && m_Order != OrderType.Follow && m_Order != OrderType.Stay && m_Order != OrderType.Stop) + return; + + switch (m_Order) + { + case OrderType.Follow: + case OrderType.Attack: + case OrderType.Transfer: + case OrderType.Friend: + case OrderType.Unfriend: + { + if (m_Order == OrderType.Transfer && m_From.HasTrade) + m_From.SendLocalizedMessage(1010507); // You cannot transfer a pet with a trade pending + else if (m_Order == OrderType.Friend && m_From.HasTrade) + m_From.SendLocalizedMessage(1070947); // You cannot friend a pet with a trade pending + else + m_AI.BeginPickTarget(m_From, m_Order); + + break; + } + case OrderType.Release: + { + if (m_Mobile.Summoned) + goto default; + else + m_From.SendGump(new Gumps.ConfirmReleaseGump(m_From, m_Mobile)); + + break; + } + default: + { + if (m_Mobile.CheckControlChance(m_From)) + m_Mobile.ControlOrder = m_Order; + + break; + } + } + } + } + } + + public virtual void GetContextMenuEntries(Mobile from, List list) + { + if (from.Alive && m_Mobile.Controlled && from.InRange(m_Mobile, 14)) + { + if (from == m_Mobile.ControlMaster) + { + list.Add(new InternalEntry(from, 6107, 14, m_Mobile, this, OrderType.Guard)); // Command: Guard + list.Add(new InternalEntry(from, 6108, 14, m_Mobile, this, OrderType.Follow)); // Command: Follow + + if (m_Mobile.CanDrop) + list.Add(new InternalEntry(from, 6109, 14, m_Mobile, this, OrderType.Drop)); // Command: Drop + + list.Add(new InternalEntry(from, 6111, 14, m_Mobile, this, OrderType.Attack)); // Command: Kill + + list.Add(new InternalEntry(from, 6112, 14, m_Mobile, this, OrderType.Stop)); // Command: Stop + list.Add(new InternalEntry(from, 6114, 14, m_Mobile, this, OrderType.Stay)); // Command: Stay + + if (!m_Mobile.Summoned && !(m_Mobile is GrizzledMare)) + { + list.Add(new InternalEntry(from, 6110, 14, m_Mobile, this, OrderType.Friend)); // Add Friend + list.Add(new InternalEntry(from, 6099, 14, m_Mobile, this, OrderType.Unfriend)); // Remove Friend + list.Add(new InternalEntry(from, 6113, 14, m_Mobile, this, OrderType.Transfer)); // Transfer + } + + list.Add(new InternalEntry(from, 6118, 14, m_Mobile, this, OrderType.Release)); // Release + } + else if (m_Mobile.IsPetFriend(from)) + { + list.Add(new InternalEntry(from, 6108, 14, m_Mobile, this, OrderType.Follow)); // Command: Follow + list.Add(new InternalEntry(from, 6112, 14, m_Mobile, this, OrderType.Stop)); // Command: Stop + list.Add(new InternalEntry(from, 6114, 14, m_Mobile, this, OrderType.Stay)); // Command: Stay + } + } + } + + public virtual void BeginPickTarget(Mobile from, OrderType order) + { + if (m_Mobile.Deleted || !m_Mobile.Controlled || !from.InRange(m_Mobile, 14) || from.Map != m_Mobile.Map) + return; + + bool isOwner = (from == m_Mobile.ControlMaster); + bool isFriend = (!isOwner && m_Mobile.IsPetFriend(from)); + + if (!isOwner && !isFriend) + return; + else if (isFriend && order != OrderType.Follow && order != OrderType.Stay && order != OrderType.Stop) + return; + + if (from.Target == null) + { + if (order == OrderType.Transfer) + from.SendLocalizedMessage(502038); // Click on the person to transfer ownership to. + else if (order == OrderType.Friend) + from.SendLocalizedMessage(502020); // Click on the player whom you wish to make a co-owner. + else if (order == OrderType.Unfriend) + from.SendLocalizedMessage(1070948); // Click on the player whom you wish to remove as a co-owner. + + from.Target = new AIControlMobileTarget(this, order); + } + else if (from.Target is AIControlMobileTarget) + { + AIControlMobileTarget t = (AIControlMobileTarget)from.Target; + + if (t.Order == order) + t.AddAI(this); + } + } + + public virtual void OnAggressiveAction(Mobile aggressor) + { + Mobile currentCombat = m_Mobile.Combatant; + + if (currentCombat != null && !aggressor.Hidden && currentCombat != aggressor && m_Mobile.GetDistanceToSqrt(currentCombat) > m_Mobile.GetDistanceToSqrt(aggressor)) + m_Mobile.Combatant = aggressor; + } + + public virtual void EndPickTarget(Mobile from, Mobile target, OrderType order) + { + if (m_Mobile.Deleted || !m_Mobile.Controlled || !from.InRange(m_Mobile, 14) || from.Map != m_Mobile.Map || !from.CheckAlive()) + return; + + bool isOwner = (from == m_Mobile.ControlMaster); + bool isFriend = (!isOwner && m_Mobile.IsPetFriend(from)); + + if (!isOwner && !isFriend) + return; + else if (isFriend && order != OrderType.Follow && order != OrderType.Stay && order != OrderType.Stop) + return; + + if (order == OrderType.Attack) + { + if (target is BaseCreature && ((BaseCreature)target).IsScaryToPets && m_Mobile.IsScaredOfScaryThings) + { + m_Mobile.SayTo(from, "Your pet refuses to attack this creature!"); + return; + } + + if ((SolenHelper.CheckRedFriendship(from) && + (target is RedSolenInfiltratorQueen + || target is RedSolenInfiltratorWarrior + || target is RedSolenQueen + || target is RedSolenWarrior + || target is RedSolenWorker)) + || (SolenHelper.CheckBlackFriendship(from) && + (target is BlackSolenInfiltratorQueen + || target is BlackSolenInfiltratorWarrior + || target is BlackSolenQueen + || target is BlackSolenWarrior + || target is BlackSolenWorker))) + { + from.SendAsciiMessage("You can not force your pet to attack a creature you are protected from."); + return; + } + + if (target is Factions.BaseFactionGuard) + { + m_Mobile.SayTo(from, "Your pet refuses to attack the guard."); + return; + } + } + + if (m_Mobile.CheckControlChance(from)) + { + m_Mobile.ControlTarget = target; + m_Mobile.ControlOrder = order; + } + } + + public virtual bool HandlesOnSpeech(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + + if (from.Alive && m_Mobile.Controlled && m_Mobile.Commandable && (from == m_Mobile.ControlMaster || m_Mobile.IsPetFriend(from))) + return true; + + return (from.Alive && from.InRange(m_Mobile.Location, 3) && m_Mobile.IsHumanInTown()); + } + private static SkillName[] m_KeywordTable = new SkillName[] { SkillName.Parry, @@ -353,1978 +353,1983 @@ namespace Server.Mobiles SkillName.Lumberjacking, SkillName.Mining, SkillName.Meditation - }; - - public virtual void OnSpeech( SpeechEventArgs e ) - { - if( e.Mobile.Alive && e.Mobile.InRange( m_Mobile.Location, 3 ) && m_Mobile.IsHumanInTown() ) - { - if( e.HasKeyword( 0x9D ) && WasNamed( e.Speech ) ) // *move* - { - if( m_Mobile.Combatant != null ) - { - // I am too busy fighting to deal with thee! - m_Mobile.PublicOverheadMessage( MessageType.Regular, 0x3B2, 501482 ); - } - else - { - // Excuse me? - m_Mobile.PublicOverheadMessage( MessageType.Regular, 0x3B2, 501516 ); - WalkRandomInHome( 2, 2, 1 ); - } - } - else if( e.HasKeyword( 0x9E ) && WasNamed( e.Speech ) ) // *time* - { - if( m_Mobile.Combatant != null ) - { - // I am too busy fighting to deal with thee! - m_Mobile.PublicOverheadMessage( MessageType.Regular, 0x3B2, 501482 ); - } - else - { - int generalNumber; - string exactTime; - - Clock.GetTime( m_Mobile, out generalNumber, out exactTime ); - - m_Mobile.PublicOverheadMessage( MessageType.Regular, 0x3B2, generalNumber ); - } - } - else if( e.HasKeyword( 0x6C ) && WasNamed( e.Speech ) ) // *train - { - if( m_Mobile.Combatant != null ) - { - // I am too busy fighting to deal with thee! - m_Mobile.PublicOverheadMessage( MessageType.Regular, 0x3B2, 501482 ); - } - else - { - bool foundSomething = false; - - Skills ourSkills = m_Mobile.Skills; - Skills theirSkills = e.Mobile.Skills; - - for( int i = 0; i < ourSkills.Length && i < theirSkills.Length; ++i ) - { - Skill skill = ourSkills[i]; - Skill theirSkill = theirSkills[i]; - - if( skill != null && theirSkill != null && skill.Base >= 60.0 && m_Mobile.CheckTeach( skill.SkillName, e.Mobile ) ) - { - double toTeach = skill.Base / 3.0; - - if( toTeach > 42.0 ) - toTeach = 42.0; - - if( toTeach > theirSkill.Base ) - { - int number = 1043059 + i; - - if( number > 1043107 ) - continue; - - if( !foundSomething ) - m_Mobile.Say( 1043058 ); // I can train the following: - - m_Mobile.Say( number ); - - foundSomething = true; - } - } - } - - if( !foundSomething ) - m_Mobile.Say( 501505 ); // Alas, I cannot teach thee anything. - } - } - else - { - SkillName toTrain = (SkillName)(-1); - - for( int i = 0; toTrain == (SkillName)(-1) && i < e.Keywords.Length; ++i ) - { - int keyword = e.Keywords[i]; - - if( keyword == 0x154 ) - { - toTrain = SkillName.Anatomy; - } - else if( keyword >= 0x6D && keyword <= 0x9C ) - { - int index = keyword - 0x6D; - - if( index >= 0 && index < m_KeywordTable.Length ) - toTrain = m_KeywordTable[index]; - } - } - - if( toTrain != (SkillName)(-1) && WasNamed( e.Speech ) ) - { - if( m_Mobile.Combatant != null ) - { - // I am too busy fighting to deal with thee! - m_Mobile.PublicOverheadMessage( MessageType.Regular, 0x3B2, 501482 ); - } - else - { - Skills skills = m_Mobile.Skills; - Skill skill = skills[toTrain]; - - if( skill == null || skill.Base < 60.0 || !m_Mobile.CheckTeach( toTrain, e.Mobile ) ) - { - m_Mobile.Say( 501507 ); // 'Tis not something I can teach thee of. - } - else - { - m_Mobile.Teach( toTrain, e.Mobile, 0, false ); - } - } - } - } - } - - if( m_Mobile.Controlled && m_Mobile.Commandable ) - { - m_Mobile.DebugSay( "Listening..." ); - - bool isOwner = (e.Mobile == m_Mobile.ControlMaster); - bool isFriend = (!isOwner && m_Mobile.IsPetFriend( e.Mobile )); - - if( e.Mobile.Alive && (isOwner || isFriend) ) - { - m_Mobile.DebugSay( "It's from my master" ); - - int[] keywords = e.Keywords; - string speech = e.Speech; - - // First, check the all* - for( int i = 0; i < keywords.Length; ++i ) - { - int keyword = keywords[i]; - - switch( keyword ) - { - case 0x164: // all come - { - if( !isOwner ) - break; - - if( m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Come; - } - - return; - } - case 0x165: // all follow - { - BeginPickTarget( e.Mobile, OrderType.Follow ); - return; - } - case 0x166: // all guard - case 0x16B: // all guard me - { - if( !isOwner ) - break; - - if( m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Guard; - } - return; - } - case 0x167: // all stop - { - if( m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Stop; - } - return; - } - case 0x168: // all kill - case 0x169: // all attack - { - if( !isOwner ) - break; - - BeginPickTarget( e.Mobile, OrderType.Attack ); - return; - } - case 0x16C: // all follow me - { - if( m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = e.Mobile; - m_Mobile.ControlOrder = OrderType.Follow; - } - return; - } - case 0x170: // all stay - { - if( m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Stay; - } - return; - } - } - } - - // No all*, so check *command - for( int i = 0; i < keywords.Length; ++i ) - { - int keyword = keywords[i]; - - switch( keyword ) - { - case 0x155: // *come - { - if( !isOwner ) - break; - - if( WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Come; - } - - return; - } - case 0x156: // *drop - { - if( !isOwner ) - break; - - if( !m_Mobile.IsDeadPet && !m_Mobile.Summoned && WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Drop; - } - - return; - } - case 0x15A: // *follow - { - if( WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - BeginPickTarget( e.Mobile, OrderType.Follow ); - - return; - } - case 0x15B: // *friend - { - if( !isOwner ) - break; - - if( WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - { - if( m_Mobile.Summoned || ( m_Mobile is GrizzledMare ) ) - e.Mobile.SendLocalizedMessage( 1005481 ); // Summoned creatures are loyal only to their summoners. - else if( e.Mobile.HasTrade ) - e.Mobile.SendLocalizedMessage( 1070947 ); // You cannot friend a pet with a trade pending - else - BeginPickTarget( e.Mobile, OrderType.Friend ); - } - - return; - } - case 0x15C: // *guard - { - if( !isOwner ) - break; - - if( !m_Mobile.IsDeadPet && WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Guard; - } - - return; - } - case 0x15D: // *kill - case 0x15E: // *attack - { - if( !isOwner ) - break; - - if( !m_Mobile.IsDeadPet && WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - BeginPickTarget( e.Mobile, OrderType.Attack ); - - return; - } - case 0x15F: // *patrol - { - if( !isOwner ) - break; - - if( WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Patrol; - } - - return; - } - case 0x161: // *stop - { - if( WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Stop; - } - - return; - } - case 0x163: // *follow me - { - if( WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = e.Mobile; - m_Mobile.ControlOrder = OrderType.Follow; - } - - return; - } - case 0x16D: // *release - { - if( !isOwner ) - break; - - if( WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - { - if( !m_Mobile.Summoned ) - { - e.Mobile.SendGump( new Gumps.ConfirmReleaseGump( e.Mobile, m_Mobile ) ); - } - else - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Release; - } - } - - return; - } - case 0x16E: // *transfer - { - if( !isOwner ) - break; - - if( !m_Mobile.IsDeadPet && WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - { - if( m_Mobile.Summoned || ( m_Mobile is GrizzledMare ) ) - e.Mobile.SendLocalizedMessage( 1005487 ); // You cannot transfer ownership of a summoned creature. - else if( e.Mobile.HasTrade ) - e.Mobile.SendLocalizedMessage( 1010507 ); // You cannot transfer a pet with a trade pending - else - BeginPickTarget( e.Mobile, OrderType.Transfer ); - } - - return; - } - case 0x16F: // *stay - { - if( WasNamed( speech ) && m_Mobile.CheckControlChance( e.Mobile ) ) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Stay; - } - - return; - } - } - } - } - } - else - { - if( e.Mobile.AccessLevel >= AccessLevel.GameMaster ) - { - m_Mobile.DebugSay( "It's from a GM" ); - - if( m_Mobile.FindMyName( e.Speech, true ) ) - { - string[] str = e.Speech.Split( ' ' ); - int i; - - for( i=0; i < str.Length; i++ ) - { - string word = str[i]; - - if( Insensitive.Equals( word, "obey" ) ) - { - m_Mobile.SetControlMaster( e.Mobile ); - - if( m_Mobile.Summoned ) - m_Mobile.SummonMaster = e.Mobile; - - return; - } - } - } - } - } - } - - public virtual bool Think() - { - if( m_Mobile.Deleted ) - return false; - - if( CheckFlee() ) - return true; - - switch( Action ) - { - case ActionType.Wander: - m_Mobile.OnActionWander(); - return DoActionWander(); - - case ActionType.Combat: - m_Mobile.OnActionCombat(); - return DoActionCombat(); - - case ActionType.Guard: - m_Mobile.OnActionGuard(); - return DoActionGuard(); - - case ActionType.Flee: - m_Mobile.OnActionFlee(); - return DoActionFlee(); - - case ActionType.Interact: - m_Mobile.OnActionInteract(); - return DoActionInteract(); - - case ActionType.Backoff: - m_Mobile.OnActionBackoff(); - return DoActionBackoff(); - - default: - return false; - } - } - - public virtual void OnActionChanged() - { - switch( Action ) - { - case ActionType.Wander: - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - m_Mobile.FocusMob = null; - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - break; - - case ActionType.Combat: - m_Mobile.Warmode = true; - m_Mobile.FocusMob = null; - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - break; - - case ActionType.Guard: - m_Mobile.Warmode = true; - m_Mobile.FocusMob = null; - m_Mobile.Combatant = null; - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_NextStopGuard = DateTime.Now + TimeSpan.FromSeconds( 10 ); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - break; - - case ActionType.Flee: - m_Mobile.Warmode = true; - m_Mobile.FocusMob = null; - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - break; - - case ActionType.Interact: - m_Mobile.Warmode = false; - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - break; - - case ActionType.Backoff: - m_Mobile.Warmode = false; - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - break; - } - } - - public virtual bool OnAtWayPoint() - { - return true; - } - - public virtual bool DoActionWander() - { - if( CheckHerding() ) - { - m_Mobile.DebugSay( "Praise the shepherd!" ); - } - else if( m_Mobile.CurrentWayPoint != null ) - { - WayPoint point = m_Mobile.CurrentWayPoint; - if( (point.X != m_Mobile.Location.X || point.Y != m_Mobile.Location.Y) && point.Map == m_Mobile.Map && point.Parent == null && !point.Deleted ) - { - m_Mobile.DebugSay( "I will move towards my waypoint." ); - DoMove( m_Mobile.GetDirectionTo( m_Mobile.CurrentWayPoint ) ); - } - else if( OnAtWayPoint() ) - { - m_Mobile.DebugSay( "I will go to the next waypoint" ); - m_Mobile.CurrentWayPoint = point.NextPoint; - if( point.NextPoint != null && point.NextPoint.Deleted ) - m_Mobile.CurrentWayPoint = point.NextPoint = point.NextPoint.NextPoint; - } - } - else if( m_Mobile.IsAnimatedDead ) - { - // animated dead follow their master - Mobile master = m_Mobile.SummonMaster; - - if( master != null && master.Map == m_Mobile.Map && master.InRange( m_Mobile, m_Mobile.RangePerception ) ) - MoveTo( master, false, 1 ); - else - WalkRandomInHome( 2, 2, 1 ); - } - else if( CheckMove() ) - { - if( !m_Mobile.CheckIdle() ) - WalkRandomInHome( 2, 2, 1 ); - } - - if( m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet ) - { - m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.Combatant ); - } - - return true; - } - - public virtual bool DoActionCombat() - { - if ( Core.AOS && CheckHerding() ) - { - m_Mobile.DebugSay( "Praise the shepherd!" ); - } - else - { - Mobile c = m_Mobile.Combatant; - - if ( c == null || c.Deleted || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet ) - Action = ActionType.Wander; - else - m_Mobile.Direction = m_Mobile.GetDirectionTo( c ); - } - - return true; - } - - public virtual bool DoActionGuard() - { - if ( Core.AOS && CheckHerding() ) - { - m_Mobile.DebugSay( "Praise the shepherd!" ); - } - else if( DateTime.Now < m_NextStopGuard ) - { - m_Mobile.DebugSay( "I am on guard" ); - //m_Mobile.Turn( Utility.Random(0, 2) - 1 ); - } - else - { - m_Mobile.DebugSay( "I stopped being on guard" ); - Action = ActionType.Wander; - } - - return true; - } - - public virtual bool DoActionFlee() - { - Mobile from = m_Mobile.FocusMob; - - if( from == null || from.Deleted || from.Map != m_Mobile.Map ) - { - m_Mobile.DebugSay( "I have lost him" ); - Action = ActionType.Guard; - return true; - } - - if( WalkMobileRange( from, 1, true, m_Mobile.RangePerception*2, m_Mobile.RangePerception*3 ) ) - { - m_Mobile.DebugSay( "I have fled" ); - Action = ActionType.Guard; - return true; - } - else - { - m_Mobile.DebugSay( "I am fleeing!" ); - } - - return true; - } - - public virtual bool DoActionInteract() - { - return true; - } - - public virtual bool DoActionBackoff() - { - return true; - } - - public virtual bool Obey() - { - if( m_Mobile.Deleted ) - return false; - - switch( m_Mobile.ControlOrder ) - { - case OrderType.None: - return DoOrderNone(); - - case OrderType.Come: - return DoOrderCome(); - - case OrderType.Drop: - return DoOrderDrop(); - - case OrderType.Friend: - return DoOrderFriend(); - - case OrderType.Unfriend: - return DoOrderUnfriend(); - - case OrderType.Guard: - return DoOrderGuard(); - - case OrderType.Attack: - return DoOrderAttack(); - - case OrderType.Patrol: - return DoOrderPatrol(); - - case OrderType.Release: - return DoOrderRelease(); - - case OrderType.Stay: - return DoOrderStay(); - - case OrderType.Stop: - return DoOrderStop(); - - case OrderType.Follow: - return DoOrderFollow(); - - case OrderType.Transfer: - return DoOrderTransfer(); - - default: - return false; - } - } - - public virtual void OnCurrentOrderChanged() - { - if( m_Mobile.Deleted || m_Mobile.ControlMaster == null || m_Mobile.ControlMaster.Deleted ) - return; - - switch( m_Mobile.ControlOrder ) - { - case OrderType.None: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.Home = m_Mobile.Location; - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Come: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Drop: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - m_Mobile.Warmode = true; - m_Mobile.Combatant = null; - break; - - case OrderType.Friend: - case OrderType.Unfriend: - m_Mobile.ControlMaster.RevealingAction(); - break; - - case OrderType.Guard: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - m_Mobile.Warmode = true; - m_Mobile.Combatant = null; - string petname = String.Format( "{0}", m_Mobile.Name ); - m_Mobile.ControlMaster.SendLocalizedMessage ( 1049671, petname ); //~1_PETNAME~ is now guarding you. - break; - - case OrderType.Attack: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - - m_Mobile.Warmode = true; - m_Mobile.Combatant = null; - break; - - case OrderType.Patrol: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Release: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Stay: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Stop: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.Home = m_Mobile.Location; - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Follow: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Transfer: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound( m_Mobile.GetIdleSound() ); - - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - } - } - - public virtual bool DoOrderNone() - { - m_Mobile.DebugSay( "I have no order" ); - - WalkRandomInHome( 3, 2, 1 ); - - if( m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet ) - { - m_Mobile.Warmode = true; - m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.Combatant ); - } - else - { - m_Mobile.Warmode = false; - } - - return true; - } - - public virtual bool DoOrderCome() - { - if( m_Mobile.ControlMaster != null && !m_Mobile.ControlMaster.Deleted ) - { - int iCurrDist = (int)m_Mobile.GetDistanceToSqrt( m_Mobile.ControlMaster ); - - if( iCurrDist > m_Mobile.RangePerception ) - { - m_Mobile.DebugSay( "I have lost my master. I stay here" ); - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.None; - } - else - { - m_Mobile.DebugSay( "My master told me come" ); - - // Not exactly OSI style, but better than nothing. - bool bRun = (iCurrDist > 5); - - if( WalkMobileRange( m_Mobile.ControlMaster, 1, bRun, 0, 1 ) ) - { - if( m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet ) - { - m_Mobile.Warmode = true; - m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.Combatant ); - } - else - { - m_Mobile.Warmode = false; - } - } - } - } - - return true; - } - - public virtual bool DoOrderDrop() - { - if( m_Mobile.IsDeadPet || !m_Mobile.CanDrop ) - return true; - - m_Mobile.DebugSay( "I drop my stuff for my master" ); - - Container pack = m_Mobile.Backpack; - - if( pack != null ) - { - List list = pack.Items; - - for( int i = list.Count - 1; i >= 0; --i ) - if( i < list.Count ) - list[i].MoveToWorld( m_Mobile.Location, m_Mobile.Map ); - } - - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.None; - - return true; - } - - public virtual bool CheckHerding() - { - IPoint2D target = m_Mobile.TargetLocation; - - if ( target == null ) - return false; // Creature is not being herded - - double distance = m_Mobile.GetDistanceToSqrt( target ); - - if( distance < 1 || distance > 15 ) - { - if( distance < 1 && target.X == 1076 && target.Y == 450 && (m_Mobile is HordeMinionFamiliar) ) - { - PlayerMobile pm = m_Mobile.ControlMaster as PlayerMobile; - - if( pm != null ) - { - QuestSystem qs = pm.Quest; - - if( qs is DarkTidesQuest ) - { - QuestObjective obj = qs.FindObjective( typeof( FetchAbraxusScrollObjective ) ); - - if( obj != null && !obj.Completed ) - { - m_Mobile.AddToBackpack( new ScrollOfAbraxus() ); - obj.Complete(); - } - } - } - } - - m_Mobile.TargetLocation = null; - return false; // At the target or too far away - } - - DoMove( m_Mobile.GetDirectionTo( target ) ); - - return true; - } - - public virtual bool DoOrderFollow() - { - if( CheckHerding() ) - { - m_Mobile.DebugSay( "Praise the shepherd!" ); - } - else if( m_Mobile.ControlTarget != null && !m_Mobile.ControlTarget.Deleted && m_Mobile.ControlTarget != m_Mobile ) - { - int iCurrDist = (int)m_Mobile.GetDistanceToSqrt( m_Mobile.ControlTarget ); - - if( iCurrDist > m_Mobile.RangePerception ) - { - m_Mobile.DebugSay( "I have lost the one to follow. I stay here" ); - - if( m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet ) - { - m_Mobile.Warmode = true; - m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.Combatant ); - } - else - { - m_Mobile.Warmode = false; - } - } - else - { - m_Mobile.DebugSay( "My master told me to follow: {0}", m_Mobile.ControlTarget.Name ); - - // Not exactly OSI style, but better than nothing. - bool bRun = (iCurrDist > 5); - - if( WalkMobileRange( m_Mobile.ControlTarget, 1, bRun, 0, 1 ) ) - { - if( m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet ) - { - m_Mobile.Warmode = true; - m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.Combatant ); - } - else - { - m_Mobile.Warmode = false; - if ( Core.AOS ) - m_Mobile.CurrentSpeed = 0.1; - } - } - } - } - else - { - m_Mobile.DebugSay( "I have nobody to follow" ); - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.None; - } - - return true; - } - - public virtual bool DoOrderFriend() - { - Mobile from = m_Mobile.ControlMaster; - Mobile to = m_Mobile.ControlTarget; - - if( from == null || to == null || from == to || from.Deleted || to.Deleted || !to.Player ) - { - m_Mobile.PublicOverheadMessage( MessageType.Regular, 0x3B2, 502039 ); // *looks confused* - } - else - { - bool youngFrom = from is PlayerMobile ? ((PlayerMobile)from).Young : false; - bool youngTo = to is PlayerMobile ? ((PlayerMobile)to).Young : false; - - if( youngFrom && !youngTo ) - { - from.SendLocalizedMessage( 502040 ); // As a young player, you may not friend pets to older players. - } - else if( !youngFrom && youngTo ) - { - from.SendLocalizedMessage( 502041 ); // As an older player, you may not friend pets to young players. - } - else if( from.CanBeBeneficial( to, true ) ) - { - NetState fromState = from.NetState, toState = to.NetState; - - if( fromState != null && toState != null ) - { - if( from.HasTrade ) - { - from.SendLocalizedMessage( 1070947 ); // You cannot friend a pet with a trade pending - } - else if( to.HasTrade ) - { - to.SendLocalizedMessage( 1070947 ); // You cannot friend a pet with a trade pending - } - else if( m_Mobile.IsPetFriend( to ) ) - { - from.SendLocalizedMessage( 1049691 ); // That person is already a friend. - } - else if( !m_Mobile.AllowNewPetFriend ) - { - from.SendLocalizedMessage( 1005482 ); // Your pet does not seem to be interested in making new friends right now. - } - else - { - // ~1_NAME~ will now accept movement commands from ~2_NAME~. - from.SendLocalizedMessage( 1049676, String.Format( "{0}\t{1}", m_Mobile.Name, to.Name ) ); - + }; + + public virtual void OnSpeech(SpeechEventArgs e) + { + if (e.Mobile.Alive && e.Mobile.InRange(m_Mobile.Location, 3) && m_Mobile.IsHumanInTown()) + { + if (e.HasKeyword(0x9D) && WasNamed(e.Speech)) // *move* + { + if (m_Mobile.Combatant != null) + { + // I am too busy fighting to deal with thee! + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); + } + else + { + // Excuse me? + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501516); + WalkRandomInHome(2, 2, 1); + } + } + else if (e.HasKeyword(0x9E) && WasNamed(e.Speech)) // *time* + { + if (m_Mobile.Combatant != null) + { + // I am too busy fighting to deal with thee! + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); + } + else + { + int generalNumber; + string exactTime; + + Clock.GetTime(m_Mobile, out generalNumber, out exactTime); + + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, generalNumber); + } + } + else if (e.HasKeyword(0x6C) && WasNamed(e.Speech)) // *train + { + if (m_Mobile.Combatant != null) + { + // I am too busy fighting to deal with thee! + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); + } + else + { + bool foundSomething = false; + + Skills ourSkills = m_Mobile.Skills; + Skills theirSkills = e.Mobile.Skills; + + for (int i = 0; i < ourSkills.Length && i < theirSkills.Length; ++i) + { + Skill skill = ourSkills[i]; + Skill theirSkill = theirSkills[i]; + + if (skill != null && theirSkill != null && skill.Base >= 60.0 && m_Mobile.CheckTeach(skill.SkillName, e.Mobile)) + { + double toTeach = skill.Base / 3.0; + + if (toTeach > 42.0) + toTeach = 42.0; + + if (toTeach > theirSkill.Base) + { + int number = 1043059 + i; + + if (number > 1043107) + continue; + + if (!foundSomething) + m_Mobile.Say(1043058); // I can train the following: + + m_Mobile.Say(number); + + foundSomething = true; + } + } + } + + if (!foundSomething) + m_Mobile.Say(501505); // Alas, I cannot teach thee anything. + } + } + else + { + SkillName toTrain = (SkillName)(-1); + + for (int i = 0; toTrain == (SkillName)(-1) && i < e.Keywords.Length; ++i) + { + int keyword = e.Keywords[i]; + + if (keyword == 0x154) + { + toTrain = SkillName.Anatomy; + } + else if (keyword >= 0x6D && keyword <= 0x9C) + { + int index = keyword - 0x6D; + + if (index >= 0 && index < m_KeywordTable.Length) + toTrain = m_KeywordTable[index]; + } + } + + if (toTrain != (SkillName)(-1) && WasNamed(e.Speech)) + { + if (m_Mobile.Combatant != null) + { + // I am too busy fighting to deal with thee! + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); + } + else + { + Skills skills = m_Mobile.Skills; + Skill skill = skills[toTrain]; + + if (skill == null || skill.Base < 60.0 || !m_Mobile.CheckTeach(toTrain, e.Mobile)) + { + m_Mobile.Say(501507); // 'Tis not something I can teach thee of. + } + else + { + m_Mobile.Teach(toTrain, e.Mobile, 0, false); + } + } + } + } + } + + if (m_Mobile.Controlled && m_Mobile.Commandable) + { + m_Mobile.DebugSay("Listening..."); + + bool isOwner = (e.Mobile == m_Mobile.ControlMaster); + bool isFriend = (!isOwner && m_Mobile.IsPetFriend(e.Mobile)); + + if (e.Mobile.Alive && (isOwner || isFriend)) + { + m_Mobile.DebugSay("It's from my master"); + + int[] keywords = e.Keywords; + string speech = e.Speech; + + // First, check the all* + for (int i = 0; i < keywords.Length; ++i) + { + int keyword = keywords[i]; + + switch (keyword) + { + case 0x164: // all come + { + if (!isOwner) + break; + + if (m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Come; + } + + return; + } + case 0x165: // all follow + { + BeginPickTarget(e.Mobile, OrderType.Follow); + return; + } + case 0x166: // all guard + case 0x16B: // all guard me + { + if (!isOwner) + break; + + if (m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Guard; + } + return; + } + case 0x167: // all stop + { + if (m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Stop; + } + return; + } + case 0x168: // all kill + case 0x169: // all attack + { + if (!isOwner) + break; + + BeginPickTarget(e.Mobile, OrderType.Attack); + return; + } + case 0x16C: // all follow me + { + if (m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = e.Mobile; + m_Mobile.ControlOrder = OrderType.Follow; + } + return; + } + case 0x170: // all stay + { + if (m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Stay; + } + return; + } + } + } + + // No all*, so check *command + for (int i = 0; i < keywords.Length; ++i) + { + int keyword = keywords[i]; + + switch (keyword) + { + case 0x155: // *come + { + if (!isOwner) + break; + + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Come; + } + + return; + } + case 0x156: // *drop + { + if (!isOwner) + break; + + if (!m_Mobile.IsDeadPet && !m_Mobile.Summoned && WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Drop; + } + + return; + } + case 0x15A: // *follow + { + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + BeginPickTarget(e.Mobile, OrderType.Follow); + + return; + } + case 0x15B: // *friend + { + if (!isOwner) + break; + + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + if (m_Mobile.Summoned || (m_Mobile is GrizzledMare)) + e.Mobile.SendLocalizedMessage(1005481); // Summoned creatures are loyal only to their summoners. + else if (e.Mobile.HasTrade) + e.Mobile.SendLocalizedMessage(1070947); // You cannot friend a pet with a trade pending + else + BeginPickTarget(e.Mobile, OrderType.Friend); + } + + return; + } + case 0x15C: // *guard + { + if (!isOwner) + break; + + if (!m_Mobile.IsDeadPet && WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Guard; + } + + return; + } + case 0x15D: // *kill + case 0x15E: // *attack + { + if (!isOwner) + break; + + if (!m_Mobile.IsDeadPet && WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + BeginPickTarget(e.Mobile, OrderType.Attack); + + return; + } + case 0x15F: // *patrol + { + if (!isOwner) + break; + + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Patrol; + } + + return; + } + case 0x161: // *stop + { + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Stop; + } + + return; + } + case 0x163: // *follow me + { + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = e.Mobile; + m_Mobile.ControlOrder = OrderType.Follow; + } + + return; + } + case 0x16D: // *release + { + if (!isOwner) + break; + + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + if (!m_Mobile.Summoned) + { + e.Mobile.SendGump(new Gumps.ConfirmReleaseGump(e.Mobile, m_Mobile)); + } + else + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Release; + } + } + + return; + } + case 0x16E: // *transfer + { + if (!isOwner) + break; + + if (!m_Mobile.IsDeadPet && WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + if (m_Mobile.Summoned || (m_Mobile is GrizzledMare)) + e.Mobile.SendLocalizedMessage(1005487); // You cannot transfer ownership of a summoned creature. + else if (e.Mobile.HasTrade) + e.Mobile.SendLocalizedMessage(1010507); // You cannot transfer a pet with a trade pending + else + BeginPickTarget(e.Mobile, OrderType.Transfer); + } + + return; + } + case 0x16F: // *stay + { + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Stay; + } + + return; + } + } + } + } + } + else + { + if (e.Mobile.AccessLevel >= AccessLevel.GameMaster) + { + m_Mobile.DebugSay("It's from a GM"); + + if (m_Mobile.FindMyName(e.Speech, true)) + { + string[] str = e.Speech.Split(' '); + int i; + + for (i = 0; i < str.Length; i++) + { + string word = str[i]; + + if (Insensitive.Equals(word, "obey")) + { + m_Mobile.SetControlMaster(e.Mobile); + + if (m_Mobile.Summoned) + m_Mobile.SummonMaster = e.Mobile; + + return; + } + } + } + } + } + } + + public virtual bool Think() + { + if (m_Mobile.Deleted) + return false; + + if (CheckFlee()) + return true; + + switch (Action) + { + case ActionType.Wander: + m_Mobile.OnActionWander(); + return DoActionWander(); + + case ActionType.Combat: + m_Mobile.OnActionCombat(); + return DoActionCombat(); + + case ActionType.Guard: + m_Mobile.OnActionGuard(); + return DoActionGuard(); + + case ActionType.Flee: + m_Mobile.OnActionFlee(); + return DoActionFlee(); + + case ActionType.Interact: + m_Mobile.OnActionInteract(); + return DoActionInteract(); + + case ActionType.Backoff: + m_Mobile.OnActionBackoff(); + return DoActionBackoff(); + + default: + return false; + } + } + + public virtual void OnActionChanged() + { + switch (Action) + { + case ActionType.Wander: + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + m_Mobile.FocusMob = null; + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + break; + + case ActionType.Combat: + m_Mobile.Warmode = true; + m_Mobile.FocusMob = null; + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + break; + + case ActionType.Guard: + m_Mobile.Warmode = true; + m_Mobile.FocusMob = null; + m_Mobile.Combatant = null; + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_NextStopGuard = DateTime.Now + TimeSpan.FromSeconds(10); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + break; + + case ActionType.Flee: + m_Mobile.Warmode = true; + m_Mobile.FocusMob = null; + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + break; + + case ActionType.Interact: + m_Mobile.Warmode = false; + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + break; + + case ActionType.Backoff: + m_Mobile.Warmode = false; + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + break; + } + } + + public virtual bool OnAtWayPoint() + { + return true; + } + + public virtual bool DoActionWander() + { + if (CheckHerding()) + { + m_Mobile.DebugSay("Praise the shepherd!"); + } + else if (m_Mobile.CurrentWayPoint != null) + { + WayPoint point = m_Mobile.CurrentWayPoint; + if ((point.X != m_Mobile.Location.X || point.Y != m_Mobile.Location.Y) && point.Map == m_Mobile.Map && point.Parent == null && !point.Deleted) + { + m_Mobile.DebugSay("I will move towards my waypoint."); + DoMove(m_Mobile.GetDirectionTo(m_Mobile.CurrentWayPoint)); + } + else if (OnAtWayPoint()) + { + m_Mobile.DebugSay("I will go to the next waypoint"); + m_Mobile.CurrentWayPoint = point.NextPoint; + if (point.NextPoint != null && point.NextPoint.Deleted) + m_Mobile.CurrentWayPoint = point.NextPoint = point.NextPoint.NextPoint; + } + } + else if (m_Mobile.IsAnimatedDead) + { + // animated dead follow their master + Mobile master = m_Mobile.SummonMaster; + + if (master != null && master.Map == m_Mobile.Map && master.InRange(m_Mobile, m_Mobile.RangePerception)) + MoveTo(master, false, 1); + else + WalkRandomInHome(2, 2, 1); + } + else if (CheckMove()) + { + if (!m_Mobile.CheckIdle()) + WalkRandomInHome(2, 2, 1); + } + + if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet) + { + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); + } + + return true; + } + + public virtual bool DoActionCombat() + { + if (Core.AOS && CheckHerding()) + { + m_Mobile.DebugSay("Praise the shepherd!"); + } + else + { + Mobile c = m_Mobile.Combatant; + + if (c == null || c.Deleted || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet) + Action = ActionType.Wander; + else + m_Mobile.Direction = m_Mobile.GetDirectionTo(c); + } + + return true; + } + + public virtual bool DoActionGuard() + { + if (Core.AOS && CheckHerding()) + { + m_Mobile.DebugSay("Praise the shepherd!"); + } + else if (DateTime.Now < m_NextStopGuard) + { + m_Mobile.DebugSay("I am on guard"); + //m_Mobile.Turn( Utility.Random(0, 2) - 1 ); + } + else + { + m_Mobile.DebugSay("I stopped being on guard"); + Action = ActionType.Wander; + } + + return true; + } + + public virtual bool DoActionFlee() + { + Mobile from = m_Mobile.FocusMob; + + if (from == null || from.Deleted || from.Map != m_Mobile.Map) + { + m_Mobile.DebugSay("I have lost him"); + Action = ActionType.Guard; + return true; + } + + if (WalkMobileRange(from, 1, true, m_Mobile.RangePerception * 2, m_Mobile.RangePerception * 3)) + { + m_Mobile.DebugSay("I have fled"); + Action = ActionType.Guard; + return true; + } + else + { + m_Mobile.DebugSay("I am fleeing!"); + } + + return true; + } + + public virtual bool DoActionInteract() + { + return true; + } + + public virtual bool DoActionBackoff() + { + return true; + } + + public virtual bool Obey() + { + if (m_Mobile.Deleted) + return false; + + switch (m_Mobile.ControlOrder) + { + case OrderType.None: + return DoOrderNone(); + + case OrderType.Come: + return DoOrderCome(); + + case OrderType.Drop: + return DoOrderDrop(); + + case OrderType.Friend: + return DoOrderFriend(); + + case OrderType.Unfriend: + return DoOrderUnfriend(); + + case OrderType.Guard: + return DoOrderGuard(); + + case OrderType.Attack: + return DoOrderAttack(); + + case OrderType.Patrol: + return DoOrderPatrol(); + + case OrderType.Release: + return DoOrderRelease(); + + case OrderType.Stay: + return DoOrderStay(); + + case OrderType.Stop: + return DoOrderStop(); + + case OrderType.Follow: + return DoOrderFollow(); + + case OrderType.Transfer: + return DoOrderTransfer(); + + default: + return false; + } + } + + public virtual void OnCurrentOrderChanged() + { + if (m_Mobile.Deleted || m_Mobile.ControlMaster == null || m_Mobile.ControlMaster.Deleted) + return; + + switch (m_Mobile.ControlOrder) + { + case OrderType.None: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.Home = m_Mobile.Location; + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Come: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Drop: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = true; + m_Mobile.Combatant = null; + break; + + case OrderType.Friend: + case OrderType.Unfriend: + m_Mobile.ControlMaster.RevealingAction(); + break; + + case OrderType.Guard: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = true; + m_Mobile.Combatant = null; + string petname = String.Format("{0}", m_Mobile.Name); + m_Mobile.ControlMaster.SendLocalizedMessage(1049671, petname); //~1_PETNAME~ is now guarding you. + break; + + case OrderType.Attack: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + + m_Mobile.Warmode = true; + m_Mobile.Combatant = null; + break; + + case OrderType.Patrol: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Release: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Stay: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Stop: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.Home = m_Mobile.Location; + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Follow: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Transfer: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + } + } + + public virtual bool DoOrderNone() + { + m_Mobile.DebugSay("I have no order"); + + WalkRandomInHome(3, 2, 1); + + if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet) + { + m_Mobile.Warmode = true; + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); + } + else + { + m_Mobile.Warmode = false; + } + + return true; + } + + public virtual bool DoOrderCome() + { + if (m_Mobile.ControlMaster != null && !m_Mobile.ControlMaster.Deleted) + { + int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m_Mobile.ControlMaster); + + if (iCurrDist > m_Mobile.RangePerception) + { + m_Mobile.DebugSay("I have lost my master. I stay here"); + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.None; + } + else + { + m_Mobile.DebugSay("My master told me come"); + + // Not exactly OSI style, but better than nothing. + bool bRun = (iCurrDist > 5); + + if (WalkMobileRange(m_Mobile.ControlMaster, 1, bRun, 0, 1)) + { + if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet) + { + m_Mobile.Warmode = true; + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); + } + else + { + m_Mobile.Warmode = false; + } + } + } + } + + return true; + } + + public virtual bool DoOrderDrop() + { + if (m_Mobile.IsDeadPet || !m_Mobile.CanDrop) + return true; + + m_Mobile.DebugSay("I drop my stuff for my master"); + + Container pack = m_Mobile.Backpack; + + if (pack != null) + { + List list = pack.Items; + + for (int i = list.Count - 1; i >= 0; --i) + if (i < list.Count) + list[i].MoveToWorld(m_Mobile.Location, m_Mobile.Map); + } + + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.None; + + return true; + } + + public virtual bool CheckHerding() + { + IPoint2D target = m_Mobile.TargetLocation; + + if (target == null) + return false; // Creature is not being herded + + double distance = m_Mobile.GetDistanceToSqrt(target); + + if (distance < 1 || distance > 15) + { + if (distance < 1 && target.X == 1076 && target.Y == 450 && (m_Mobile is HordeMinionFamiliar)) + { + PlayerMobile pm = m_Mobile.ControlMaster as PlayerMobile; + + if (pm != null) + { + QuestSystem qs = pm.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(typeof(FetchAbraxusScrollObjective)); + + if (obj != null && !obj.Completed) + { + m_Mobile.AddToBackpack(new ScrollOfAbraxus()); + obj.Complete(); + } + } + } + } + + m_Mobile.TargetLocation = null; + return false; // At the target or too far away + } + + DoMove(m_Mobile.GetDirectionTo(target)); + + return true; + } + + public virtual bool DoOrderFollow() + { + if (CheckHerding()) + { + m_Mobile.DebugSay("Praise the shepherd!"); + } + else if (m_Mobile.ControlTarget != null && !m_Mobile.ControlTarget.Deleted && m_Mobile.ControlTarget != m_Mobile) + { + int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m_Mobile.ControlTarget); + + if (iCurrDist > m_Mobile.RangePerception) + { + m_Mobile.DebugSay("I have lost the one to follow. I stay here"); + + if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet) + { + m_Mobile.Warmode = true; + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); + } + else + { + m_Mobile.Warmode = false; + } + } + else + { + m_Mobile.DebugSay("My master told me to follow: {0}", m_Mobile.ControlTarget.Name); + + // Not exactly OSI style, but better than nothing. + bool bRun = (iCurrDist > 5); + + if (WalkMobileRange(m_Mobile.ControlTarget, 1, bRun, 0, 1)) + { + if (m_Mobile.Combatant != null && !m_Mobile.Combatant.Deleted && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet) + { + m_Mobile.Warmode = true; + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); + } + else + { + m_Mobile.Warmode = false; + if (Core.AOS) + m_Mobile.CurrentSpeed = 0.1; + } + } + } + } + else + { + m_Mobile.DebugSay("I have nobody to follow"); + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.None; + } + + return true; + } + + public virtual bool DoOrderFriend() + { + Mobile from = m_Mobile.ControlMaster; + Mobile to = m_Mobile.ControlTarget; + + if (from == null || to == null || from == to || from.Deleted || to.Deleted || !to.Player) + { + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 502039); // *looks confused* + } + else + { + bool youngFrom = from is PlayerMobile ? ((PlayerMobile)from).Young : false; + bool youngTo = to is PlayerMobile ? ((PlayerMobile)to).Young : false; + + if (youngFrom && !youngTo) + { + from.SendLocalizedMessage(502040); // As a young player, you may not friend pets to older players. + } + else if (!youngFrom && youngTo) + { + from.SendLocalizedMessage(502041); // As an older player, you may not friend pets to young players. + } + else if (from.CanBeBeneficial(to, true)) + { + NetState fromState = from.NetState, toState = to.NetState; + + if (fromState != null && toState != null) + { + if (from.HasTrade) + { + from.SendLocalizedMessage(1070947); // You cannot friend a pet with a trade pending + } + else if (to.HasTrade) + { + to.SendLocalizedMessage(1070947); // You cannot friend a pet with a trade pending + } + else if (m_Mobile.IsPetFriend(to)) + { + from.SendLocalizedMessage(1049691); // That person is already a friend. + } + else if (!m_Mobile.AllowNewPetFriend) + { + from.SendLocalizedMessage(1005482); // Your pet does not seem to be interested in making new friends right now. + } + else + { + // ~1_NAME~ will now accept movement commands from ~2_NAME~. + from.SendLocalizedMessage(1049676, String.Format("{0}\t{1}", m_Mobile.Name, to.Name)); + /* ~1_NAME~ has granted you the ability to give orders to their pet ~2_PET_NAME~. * This creature will now consider you as a friend. - */ - to.SendLocalizedMessage( 1043246, String.Format( "{0}\t{1}", from.Name, m_Mobile.Name ) ); - - m_Mobile.AddPetFriend( to ); - - m_Mobile.ControlTarget = to; - m_Mobile.ControlOrder = OrderType.Follow; - - return true; - } - } - } - } - - m_Mobile.ControlTarget = from; - m_Mobile.ControlOrder = OrderType.Follow; - - return true; - } - - public virtual bool DoOrderUnfriend() - { - Mobile from = m_Mobile.ControlMaster; - Mobile to = m_Mobile.ControlTarget; - - if( from == null || to == null || from == to || from.Deleted || to.Deleted || !to.Player ) - { - m_Mobile.PublicOverheadMessage( MessageType.Regular, 0x3B2, 502039 ); // *looks confused* - } - else if( !m_Mobile.IsPetFriend( to ) ) - { - from.SendLocalizedMessage( 1070953 ); // That person is not a friend. - } - else - { - // ~1_NAME~ will no longer accept movement commands from ~2_NAME~. - from.SendLocalizedMessage( 1070951, String.Format( "{0}\t{1}", m_Mobile.Name, to.Name ) ); - + */ + to.SendLocalizedMessage(1043246, String.Format("{0}\t{1}", from.Name, m_Mobile.Name)); + + m_Mobile.AddPetFriend(to); + + m_Mobile.ControlTarget = to; + m_Mobile.ControlOrder = OrderType.Follow; + + return true; + } + } + } + } + + m_Mobile.ControlTarget = from; + m_Mobile.ControlOrder = OrderType.Follow; + + return true; + } + + public virtual bool DoOrderUnfriend() + { + Mobile from = m_Mobile.ControlMaster; + Mobile to = m_Mobile.ControlTarget; + + if (from == null || to == null || from == to || from.Deleted || to.Deleted || !to.Player) + { + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 502039); // *looks confused* + } + else if (!m_Mobile.IsPetFriend(to)) + { + from.SendLocalizedMessage(1070953); // That person is not a friend. + } + else + { + // ~1_NAME~ will no longer accept movement commands from ~2_NAME~. + from.SendLocalizedMessage(1070951, String.Format("{0}\t{1}", m_Mobile.Name, to.Name)); + /* ~1_NAME~ has no longer granted you the ability to give orders to their pet ~2_PET_NAME~. * This creature will no longer consider you as a friend. - */ - to.SendLocalizedMessage( 1070952, String.Format( "{0}\t{1}", from.Name, m_Mobile.Name ) ); - - m_Mobile.RemovePetFriend( to ); - } - - m_Mobile.ControlTarget = from; - m_Mobile.ControlOrder = OrderType.Follow; - - return true; - } - - public virtual bool DoOrderGuard() - { - if( m_Mobile.IsDeadPet ) - return true; - - Mobile controlMaster = m_Mobile.ControlMaster; - - if( controlMaster == null || controlMaster.Deleted ) - return true; - - Mobile combatant = m_Mobile.Combatant; - - List aggressors = controlMaster.Aggressors; - - if( aggressors.Count > 0 ) - { - for( int i = 0; i < aggressors.Count; ++i ) - { - AggressorInfo info = aggressors[i]; - Mobile attacker = info.Attacker; - - if( attacker != null && !attacker.Deleted && attacker.GetDistanceToSqrt( m_Mobile ) <= m_Mobile.RangePerception ) - { - if( combatant == null || attacker.GetDistanceToSqrt( controlMaster ) < combatant.GetDistanceToSqrt( controlMaster ) ) - combatant = attacker; - } - } - - if( combatant != null ) - m_Mobile.DebugSay( "Crap, my master has been attacked! I will attack one of those bastards!" ); - } - - if( combatant != null && combatant != m_Mobile && combatant != m_Mobile.ControlMaster && !combatant.Deleted && combatant.Alive && !combatant.IsDeadBondedPet && m_Mobile.CanSee( combatant ) && m_Mobile.CanBeHarmful( combatant, false ) && combatant.Map == m_Mobile.Map ) - { - m_Mobile.DebugSay( "Guarding from target..." ); - - m_Mobile.Combatant = combatant; - m_Mobile.FocusMob = combatant; - Action = ActionType.Combat; - + */ + to.SendLocalizedMessage(1070952, String.Format("{0}\t{1}", from.Name, m_Mobile.Name)); + + m_Mobile.RemovePetFriend(to); + } + + m_Mobile.ControlTarget = from; + m_Mobile.ControlOrder = OrderType.Follow; + + return true; + } + + public virtual bool DoOrderGuard() + { + if (m_Mobile.IsDeadPet) + return true; + + Mobile controlMaster = m_Mobile.ControlMaster; + + if (controlMaster == null || controlMaster.Deleted) + return true; + + Mobile combatant = m_Mobile.Combatant; + + List aggressors = controlMaster.Aggressors; + + if (aggressors.Count > 0) + { + for (int i = 0; i < aggressors.Count; ++i) + { + AggressorInfo info = aggressors[i]; + Mobile attacker = info.Attacker; + + if (attacker != null && !attacker.Deleted && attacker.GetDistanceToSqrt(m_Mobile) <= m_Mobile.RangePerception) + { + if (combatant == null || attacker.GetDistanceToSqrt(controlMaster) < combatant.GetDistanceToSqrt(controlMaster)) + combatant = attacker; + } + } + + if (combatant != null) + m_Mobile.DebugSay("Crap, my master has been attacked! I will attack one of those bastards!"); + } + + if (combatant != null && combatant != m_Mobile && combatant != m_Mobile.ControlMaster && !combatant.Deleted && combatant.Alive && !combatant.IsDeadBondedPet && m_Mobile.CanSee(combatant) && m_Mobile.CanBeHarmful(combatant, false) && combatant.Map == m_Mobile.Map) + { + m_Mobile.DebugSay("Guarding from target..."); + + m_Mobile.Combatant = combatant; + m_Mobile.FocusMob = combatant; + Action = ActionType.Combat; + /* * We need to call Think() here or spell casting monsters will not use * spells when guarding because their target is never processed. - */ - Think(); - } - else - { - m_Mobile.DebugSay( "Nothing to guard from" ); - - m_Mobile.Warmode = false; - if ( Core.AOS ) - m_Mobile.CurrentSpeed = 0.1; - - WalkMobileRange( controlMaster, 1, false, 0, 1 ); - } - - return true; - } - - public virtual bool DoOrderAttack() - { - if( m_Mobile.IsDeadPet ) - return true; - - if( m_Mobile.ControlTarget == null || m_Mobile.ControlTarget.Deleted || m_Mobile.ControlTarget.Map != m_Mobile.Map || !m_Mobile.ControlTarget.Alive || m_Mobile.ControlTarget.IsDeadBondedPet ) - { - m_Mobile.DebugSay( "I think he might be dead. He's not anywhere around here at least. That's cool. I'm glad he's dead." ); - - if ( Core.AOS ) { - m_Mobile.ControlTarget = m_Mobile.ControlMaster; - m_Mobile.ControlOrder = OrderType.Follow; - } else { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.None; - } - - if( m_Mobile.FightMode == FightMode.Closest || m_Mobile.FightMode == FightMode.Aggressor ) - { - Mobile newCombatant = null; - double newScore = 0.0; - - foreach( Mobile aggr in m_Mobile.GetMobilesInRange( m_Mobile.RangePerception ) ) - { - if( !m_Mobile.CanSee( aggr ) || aggr.Combatant != m_Mobile ) - continue; - - if( aggr.IsDeadBondedPet || !aggr.Alive ) - continue; - - double aggrScore = m_Mobile.GetFightModeRanking( aggr, FightMode.Closest, false ); - - if( (newCombatant == null || aggrScore > newScore) && m_Mobile.InLOS( aggr ) ) - { - newCombatant = aggr; - newScore = aggrScore; - } - } - - if( newCombatant != null ) - { - m_Mobile.ControlTarget = newCombatant; - m_Mobile.ControlOrder = OrderType.Attack; - m_Mobile.Combatant = newCombatant; - m_Mobile.DebugSay( "But -that- is not dead. Here we go again..." ); - Think(); - } - } - } - else - { - m_Mobile.DebugSay( "Attacking target..." ); - Think(); - } - - return true; - } - - public virtual bool DoOrderPatrol() - { - m_Mobile.DebugSay( "This order is not yet coded" ); - return true; - } - - public virtual bool DoOrderRelease() - { - m_Mobile.DebugSay( "I have been released" ); - - m_Mobile.PlaySound( m_Mobile.GetAngerSound() ); - - m_Mobile.SetControlMaster( null ); - m_Mobile.SummonMaster = null; - - m_Mobile.BondingBegin = DateTime.MinValue; - m_Mobile.OwnerAbandonTime = DateTime.MinValue; - m_Mobile.IsBonded = false; - - SpawnEntry se = m_Mobile.Spawner as SpawnEntry; - if( se != null && se.HomeLocation != Point3D.Zero ) - { - m_Mobile.Home = se.HomeLocation; - m_Mobile.RangeHome = se.HomeRange; - } - - if( m_Mobile.DeleteOnRelease || m_Mobile.IsDeadPet ) - m_Mobile.Delete(); - - m_Mobile.BeginDeleteTimer(); - m_Mobile.DropBackpack(); - - return true; - } - - public virtual bool DoOrderStay() - { - if( CheckHerding() ) - m_Mobile.DebugSay( "Praise the shepherd!" ); - else - m_Mobile.DebugSay( "My master told me to stay" ); - - //m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.ControlMaster ); - - return true; - } - - public virtual bool DoOrderStop() - { - if( m_Mobile.ControlMaster == null || m_Mobile.ControlMaster.Deleted ) - return true; - - m_Mobile.DebugSay( "My master told me to stop." ); - - m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.ControlMaster ); - m_Mobile.Home = m_Mobile.Location; - - m_Mobile.ControlTarget = null; - - if( Core.ML ) - { - WalkRandomInHome( 3, 2, 1 ); - } - else - { - m_Mobile.ControlOrder = OrderType.None; - } - - return true; - } - - private class TransferItem : Item - { - public static bool IsInCombat( BaseCreature creature ) - { - return (creature != null && (creature.Aggressors.Count > 0 || creature.Aggressed.Count > 0)); - } - - private BaseCreature m_Creature; - - public TransferItem( BaseCreature creature ) - : base( ShrinkTable.Lookup( creature ) ) - { - m_Creature = creature; - - Movable = false; - - if( !Core.AOS ) - { - Name = creature.Name; - } - else if( this.ItemID == ShrinkTable.DefaultItemID || creature.GetType().IsDefined( typeof( FriendlyNameAttribute ), false ) || creature is Reptalon ) - Name = FriendlyNameAttribute.GetFriendlyNameFor( creature.GetType() ).ToString(); - - //(As Per OSI)No name. Normally, set by the ItemID of the Shrink Item unless we either explicitly set it with an Attribute, or, no lookup found - - Hue = creature.Hue & 0x0FFF; - } - - public TransferItem( 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(); - - Delete(); - } - - public override void GetProperties( ObjectPropertyList list ) - { - base.GetProperties( list ); - - list.Add( 1041603 ); // This item represents a pet currently in consideration for trade - list.Add( 1041601, m_Creature.Name ); // Pet Name: ~1_val~ - - if ( m_Creature.ControlMaster != null ) - list.Add( 1041602, m_Creature.ControlMaster.Name ); // Owner: ~1_val~ - } - - public override bool AllowSecureTrade( Mobile from, Mobile to, Mobile newOwner, bool accepted ) - { - if( !base.AllowSecureTrade( from, to, newOwner, accepted ) ) - return false; - - if( Deleted || m_Creature == null || m_Creature.Deleted || m_Creature.ControlMaster != from || !from.CheckAlive() || !to.CheckAlive() ) - return false; - - if( from.Map != m_Creature.Map || !from.InRange( m_Creature, 14 ) ) - return false; - - bool youngFrom = from is PlayerMobile ? ((PlayerMobile)from).Young : false; - bool youngTo = to is PlayerMobile ? ((PlayerMobile)to).Young : false; - - if( accepted && youngFrom && !youngTo ) - { - from.SendLocalizedMessage( 502051 ); // As a young player, you may not transfer pets to older players. - } - else if( accepted && !youngFrom && youngTo ) - { - from.SendLocalizedMessage( 502052 ); // As an older player, you may not transfer pets to young players. - } - else if( accepted && !m_Creature.CanBeControlledBy( to ) ) - { - string args = String.Format( "{0}\t{1}\t ", to.Name, from.Name ); - - from.SendLocalizedMessage( 1043248, args ); // The pet refuses to be transferred because it will not obey ~1_NAME~.~3_BLANK~ - to.SendLocalizedMessage( 1043249, args ); // The pet will not accept you as a master because it does not trust you.~3_BLANK~ - - return false; - } - else if( accepted && !m_Creature.CanBeControlledBy( from ) ) - { - string args = String.Format( "{0}\t{1}\t ", to.Name, from.Name ); - - from.SendLocalizedMessage( 1043250, args ); // The pet refuses to be transferred because it will not obey you sufficiently.~3_BLANK~ - to.SendLocalizedMessage( 1043251, args ); // The pet will not accept you as a master because it does not trust ~2_NAME~.~3_BLANK~ - } - else if( accepted && (to.Followers + m_Creature.ControlSlots) > to.FollowersMax ) - { - to.SendLocalizedMessage( 1049607 ); // You have too many followers to control that creature. - - return false; - } - else if( accepted && IsInCombat( m_Creature ) ) - { - from.SendMessage( "You may not transfer a pet that has recently been in combat." ); - to.SendMessage( "The pet may not be transfered to you because it has recently been in combat." ); - - return false; - } - - return true; - } - - public override void OnSecureTrade( Mobile from, Mobile to, Mobile newOwner, bool accepted ) - { - if( Deleted ) - return; - - Delete(); - - if( m_Creature == null || m_Creature.Deleted || m_Creature.ControlMaster != from || !from.CheckAlive() || !to.CheckAlive() ) - return; - - if( from.Map != m_Creature.Map || !from.InRange( m_Creature, 14 ) ) - return; - - if( accepted ) - { - if( m_Creature.SetControlMaster( to ) ) - { - if( m_Creature.Summoned ) - m_Creature.SummonMaster = to; - - m_Creature.ControlTarget = to; - m_Creature.ControlOrder = OrderType.Follow; - - m_Creature.BondingBegin = DateTime.MinValue; - m_Creature.OwnerAbandonTime = DateTime.MinValue; - m_Creature.IsBonded = false; - - m_Creature.PlaySound( m_Creature.GetIdleSound() ); - - string args = String.Format( "{0}\t{1}\t{2}", from.Name, m_Creature.Name, to.Name ); - - from.SendLocalizedMessage( 1043253, args ); // You have transferred your pet to ~3_GETTER~. - to.SendLocalizedMessage( 1043252, args ); // ~1_NAME~ has transferred the allegiance of ~2_PET_NAME~ to you. - } - } - } - } - - public virtual bool DoOrderTransfer() - { - if( m_Mobile.IsDeadPet ) - return true; - - Mobile from = m_Mobile.ControlMaster; - Mobile to = m_Mobile.ControlTarget; - - if( from != to && from != null && !from.Deleted && to != null && !to.Deleted && to.Player ) - { - m_Mobile.DebugSay( "Begin transfer with {0}", to.Name ); - - bool youngFrom = from is PlayerMobile ? ((PlayerMobile)from).Young : false; - bool youngTo = to is PlayerMobile ? ((PlayerMobile)to).Young : false; - - if( youngFrom && !youngTo ) - { - from.SendLocalizedMessage( 502051 ); // As a young player, you may not transfer pets to older players. - } - else if( !youngFrom && youngTo ) - { - from.SendLocalizedMessage( 502052 ); // As an older player, you may not transfer pets to young players. - } - else if( !m_Mobile.CanBeControlledBy( to ) ) - { - string args = String.Format( "{0}\t{1}\t ", to.Name, from.Name ); - - from.SendLocalizedMessage( 1043248, args ); // The pet refuses to be transferred because it will not obey ~1_NAME~.~3_BLANK~ - to.SendLocalizedMessage( 1043249, args ); // The pet will not accept you as a master because it does not trust you.~3_BLANK~ - } - else if( !m_Mobile.CanBeControlledBy( from ) ) - { - string args = String.Format( "{0}\t{1}\t ", to.Name, from.Name ); - - from.SendLocalizedMessage( 1043250, args ); // The pet refuses to be transferred because it will not obey you sufficiently.~3_BLANK~ - to.SendLocalizedMessage( 1043251, args ); // The pet will not accept you as a master because it does not trust ~2_NAME~.~3_BLANK~ - } - else if( TransferItem.IsInCombat( m_Mobile ) ) - { - from.SendMessage( "You may not transfer a pet that has recently been in combat." ); - to.SendMessage( "The pet may not be transfered to you because it has recently been in combat." ); - } - else - { - NetState fromState = from.NetState, toState = to.NetState; - - if( fromState != null && toState != null ) - { - if( from.HasTrade ) - { - from.SendLocalizedMessage( 1010507 ); // You cannot transfer a pet with a trade pending - } - else if( to.HasTrade ) - { - to.SendLocalizedMessage( 1010507 ); // You cannot transfer a pet with a trade pending - } - else - { - Container c = fromState.AddTrade( toState ); - c.DropItem( new TransferItem( m_Mobile ) ); - } - } - } - } - - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Stay; - - return true; - } - - public virtual bool DoBardPacified() - { - if( DateTime.Now < m_Mobile.BardEndTime ) - { - m_Mobile.DebugSay( "I am pacified, I wait" ); - m_Mobile.Combatant = null; - m_Mobile.Warmode = false; - - } - else - { - m_Mobile.DebugSay( "I'm not pacified any longer" ); - m_Mobile.BardPacified = false; - } - - return true; - } - - public virtual bool DoBardProvoked() - { - if( DateTime.Now >= m_Mobile.BardEndTime && (m_Mobile.BardMaster == null || m_Mobile.BardMaster.Deleted || m_Mobile.BardMaster.Map != m_Mobile.Map || m_Mobile.GetDistanceToSqrt( m_Mobile.BardMaster ) > m_Mobile.RangePerception) ) - { - m_Mobile.DebugSay( "I have lost my provoker" ); - m_Mobile.BardProvoked = false; - m_Mobile.BardMaster = null; - m_Mobile.BardTarget = null; - - m_Mobile.Combatant = null; - m_Mobile.Warmode = false; - } - else - { - if( m_Mobile.BardTarget == null || m_Mobile.BardTarget.Deleted || m_Mobile.BardTarget.Map != m_Mobile.Map || m_Mobile.GetDistanceToSqrt( m_Mobile.BardTarget ) > m_Mobile.RangePerception ) - { - m_Mobile.DebugSay( "I have lost my provoke target" ); - m_Mobile.BardProvoked = false; - m_Mobile.BardMaster = null; - m_Mobile.BardTarget = null; - - m_Mobile.Combatant = null; - m_Mobile.Warmode = false; - } - else - { - m_Mobile.Combatant = m_Mobile.BardTarget; - m_Action = ActionType.Combat; - - m_Mobile.OnThink(); - Think(); - } - } - - return true; - } - - public virtual void WalkRandom( int iChanceToNotMove, int iChanceToDir, int iSteps ) - { - if( m_Mobile.Deleted || m_Mobile.DisallowAllMoves ) - return; - - for( int i=0; i 1.0 ) - offset = 1.0; - - offset = 1.0 - offset; - - delay += ( offset * 0.8 ); - } - - if( delay < 0.0 ) - delay = 0.0; - - if ( double.IsNaN( delay ) ) { - using( StreamWriter op = new StreamWriter( "nan_transform.txt", true ) ) { - op.WriteLine( String.Format( "NaN in TransformMoveDelay: {0}, {1}, {2}, {3}", DateTime.Now, this.GetType().ToString(), m_Mobile == null ? "null" : m_Mobile.GetType().ToString(), m_Mobile.HitsMax ) ); - } - - return 1.0; - } - - return delay; - } - - private DateTime m_NextMove; - - public DateTime NextMove - { - get { return m_NextMove; } - set { m_NextMove = value; } - } - - public virtual bool CheckMove() - { - return (DateTime.Now >= m_NextMove); - } - - public virtual bool DoMove( Direction d ) - { - return DoMove( d, false ); - } - - public virtual bool DoMove( Direction d, bool badStateOk ) - { - MoveResult res = DoMoveImpl( d ); - - return (res == MoveResult.Success || res == MoveResult.SuccessAutoTurn || (badStateOk && res == MoveResult.BadState)); - } - - private static Queue m_Obstacles = new Queue(); - - public virtual MoveResult DoMoveImpl( Direction d ) - { - if( m_Mobile.Deleted || m_Mobile.Frozen || m_Mobile.Paralyzed || (m_Mobile.Spell != null && m_Mobile.Spell.IsCasting) || m_Mobile.DisallowAllMoves ) - return MoveResult.BadState; - else if( !CheckMove() ) - return MoveResult.BadState; - - // This makes them always move one step, never any direction changes - m_Mobile.Direction = d; - - TimeSpan delay = TimeSpan.FromSeconds( TransformMoveDelay( m_Mobile.CurrentSpeed ) ); - - m_NextMove += delay; - - if( m_NextMove < DateTime.Now ) - m_NextMove = DateTime.Now; - - m_Mobile.Pushing = false; - - MoveImpl.IgnoreMovableImpassables = (m_Mobile.CanMoveOverObstacles && !m_Mobile.CanDestroyObstacles); - - if( (m_Mobile.Direction & Direction.Mask) != (d & Direction.Mask) ) - { - bool v = m_Mobile.Move( d ); - - MoveImpl.IgnoreMovableImpassables = false; - return (v ? MoveResult.Success : MoveResult.Blocked); - } - else if( !m_Mobile.Move( d ) ) - { - bool wasPushing = m_Mobile.Pushing; - - bool blocked = true; - - bool canOpenDoors = m_Mobile.CanOpenDoors; - bool canDestroyObstacles = m_Mobile.CanDestroyObstacles; - - if( canOpenDoors || canDestroyObstacles ) - { - m_Mobile.DebugSay( "My movement was blocked, I will try to clear some obstacles." ); - - Map map = m_Mobile.Map; - - if( map != null ) - { - int x = m_Mobile.X, y = m_Mobile.Y; - Movement.Movement.Offset( d, ref x, ref y ); - - int destroyables = 0; - - IPooledEnumerable eable = map.GetItemsInRange( new Point3D( x, y, m_Mobile.Location.Z ), 1 ); - - foreach( Item item in eable ) - { - if( canOpenDoors && item is BaseDoor && (item.Z + item.ItemData.Height) > m_Mobile.Z && (m_Mobile.Z + 16) > item.Z ) - { - if( item.X != x || item.Y != y ) - continue; - - BaseDoor door = (BaseDoor)item; - - if( !door.Locked || !door.UseLocks() ) - m_Obstacles.Enqueue( door ); - - if( !canDestroyObstacles ) - break; - } - else if( canDestroyObstacles && item.Movable && item.ItemData.Impassable && (item.Z + item.ItemData.Height) > m_Mobile.Z && (m_Mobile.Z + 16) > item.Z ) - { - if( !m_Mobile.InRange( item.GetWorldLocation(), 1 ) ) - continue; - - m_Obstacles.Enqueue( item ); - ++destroyables; - } - } - - eable.Free(); - - if( destroyables > 0 ) - Effects.PlaySound( new Point3D( x, y, m_Mobile.Z ), m_Mobile.Map, 0x3B3 ); - - if( m_Obstacles.Count > 0 ) - blocked = false; // retry movement - - while( m_Obstacles.Count > 0 ) - { - Item item = (Item)m_Obstacles.Dequeue(); - - if( item is BaseDoor ) - { - m_Mobile.DebugSay( "Little do they expect, I've learned how to open doors. Didn't they read the script??" ); - m_Mobile.DebugSay( "*twist*" ); - - ((BaseDoor)item).Use( m_Mobile ); - } - else - { - m_Mobile.DebugSay( "Ugabooga. I'm so big and tough I can destroy it: {0}", item.GetType().Name ); - - if( item is Container ) - { - Container cont = (Container)item; - - for( int i = 0; i < cont.Items.Count; ++i ) - { - Item check = cont.Items[i]; - - if( check.Movable && check.ItemData.Impassable && (item.Z + check.ItemData.Height) > m_Mobile.Z ) - m_Obstacles.Enqueue( check ); - } - - cont.Destroy(); - } - else - { - item.Delete(); - } - } - } - - if( !blocked ) - blocked = !m_Mobile.Move( d ); - } - } - - if( blocked ) - { - int offset = (Utility.RandomDouble() >= 0.6 ? 1 : -1); - - for( int i = 0; i < 2; ++i ) - { - m_Mobile.TurnInternal( offset ); - - if( m_Mobile.Move( m_Mobile.Direction ) ) - { - MoveImpl.IgnoreMovableImpassables = false; - return MoveResult.SuccessAutoTurn; - } - } - - MoveImpl.IgnoreMovableImpassables = false; - return (wasPushing ? MoveResult.BadState : MoveResult.Blocked); - } - else - { - MoveImpl.IgnoreMovableImpassables = false; - return MoveResult.Success; - } - } - - MoveImpl.IgnoreMovableImpassables = false; - return MoveResult.Success; - } - - public virtual void WalkRandomInHome( int iChanceToNotMove, int iChanceToDir, int iSteps ) - { - if( m_Mobile.Deleted || m_Mobile.DisallowAllMoves ) - return; - - if( m_Mobile.Home == Point3D.Zero ) - { - if( m_Mobile.Spawner is SpawnEntry ) - { - Region region = ((SpawnEntry)m_Mobile.Spawner).Region; - - if( m_Mobile.Region.AcceptsSpawnsFrom( region ) ) - { - m_Mobile.WalkRegion = region; - WalkRandom( iChanceToNotMove, iChanceToDir, iSteps ); - m_Mobile.WalkRegion = null; - } - else - { - if( region.GoLocation != Point3D.Zero && Utility.Random( 10 ) > 5 ) - { - DoMove( m_Mobile.GetDirectionTo( region.GoLocation ) ); - } - else - { - WalkRandom( iChanceToNotMove, iChanceToDir, 1 ); - } - } - } - else - { - WalkRandom( iChanceToNotMove, iChanceToDir, iSteps ); - } - } - else - { - for( int i=0; i m_Mobile.RangeHome ) - { - DoMove( m_Mobile.GetDirectionTo( m_Mobile.Home ) ); - } - else - { - if( Utility.Random( 10 ) > 5 ) - { - DoMove( m_Mobile.GetDirectionTo( m_Mobile.Home ) ); - } - else - { - WalkRandom( iChanceToNotMove, iChanceToDir, 1 ); - } - } - } - else - { - if( m_Mobile.Location != m_Mobile.Home ) - { - DoMove( m_Mobile.GetDirectionTo( m_Mobile.Home ) ); - } - } - } - } - } - - public virtual bool CheckFlee() - { - if( m_Mobile.CheckFlee() ) - { - Mobile combatant = m_Mobile.Combatant; - - if( combatant == null ) - { - WalkRandom( 1, 2, 1 ); - } - else - { - Direction d = combatant.GetDirectionTo( m_Mobile ); - - d = (Direction)((int)d + Utility.RandomMinMax( -1, +1 )); - - m_Mobile.Direction = d; - m_Mobile.Move( d ); - } - - return true; - } - - return false; - } - - protected PathFollower m_Path; - - public virtual void OnTeleported() - { - if( m_Path != null ) - { - m_Mobile.DebugSay( "Teleported; repathing" ); - m_Path.ForceRepath(); - } - } - - public virtual bool MoveTo( Mobile m, bool run, int range ) - { - if( m_Mobile.Deleted || m_Mobile.DisallowAllMoves || m == null || m.Deleted ) - return false; - - if( m_Mobile.InRange( m, range ) ) - { - m_Path = null; - return true; - } - - if( m_Path != null && m_Path.Goal == m ) - { - if( m_Path.Follow( run, 1 ) ) - { - m_Path = null; - return true; - } - } - else if( !DoMove( m_Mobile.GetDirectionTo( m ), true ) ) - { - m_Path = new PathFollower( m_Mobile, m ); - m_Path.Mover = new MoveMethod( DoMoveImpl ); - - if( m_Path.Follow( run, 1 ) ) - { - m_Path = null; - return true; - } - } - else - { - m_Path = null; - return true; - } - - return false; - } - + */ + Think(); + } + else + { + m_Mobile.DebugSay("Nothing to guard from"); + + m_Mobile.Warmode = false; + if (Core.AOS) + m_Mobile.CurrentSpeed = 0.1; + + WalkMobileRange(controlMaster, 1, false, 0, 1); + } + + return true; + } + + public virtual bool DoOrderAttack() + { + if (m_Mobile.IsDeadPet) + return true; + + if (m_Mobile.ControlTarget == null || m_Mobile.ControlTarget.Deleted || m_Mobile.ControlTarget.Map != m_Mobile.Map || !m_Mobile.ControlTarget.Alive || m_Mobile.ControlTarget.IsDeadBondedPet) + { + m_Mobile.DebugSay("I think he might be dead. He's not anywhere around here at least. That's cool. I'm glad he's dead."); + + if (Core.AOS) + { + m_Mobile.ControlTarget = m_Mobile.ControlMaster; + m_Mobile.ControlOrder = OrderType.Follow; + } + else + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.None; + } + + if (m_Mobile.FightMode == FightMode.Closest || m_Mobile.FightMode == FightMode.Aggressor) + { + Mobile newCombatant = null; + double newScore = 0.0; + + foreach (Mobile aggr in m_Mobile.GetMobilesInRange(m_Mobile.RangePerception)) + { + if (!m_Mobile.CanSee(aggr) || aggr.Combatant != m_Mobile) + continue; + + if (aggr.IsDeadBondedPet || !aggr.Alive) + continue; + + double aggrScore = m_Mobile.GetFightModeRanking(aggr, FightMode.Closest, false); + + if ((newCombatant == null || aggrScore > newScore) && m_Mobile.InLOS(aggr)) + { + newCombatant = aggr; + newScore = aggrScore; + } + } + + if (newCombatant != null) + { + m_Mobile.ControlTarget = newCombatant; + m_Mobile.ControlOrder = OrderType.Attack; + m_Mobile.Combatant = newCombatant; + m_Mobile.DebugSay("But -that- is not dead. Here we go again..."); + Think(); + } + } + } + else + { + m_Mobile.DebugSay("Attacking target..."); + Think(); + } + + return true; + } + + public virtual bool DoOrderPatrol() + { + m_Mobile.DebugSay("This order is not yet coded"); + return true; + } + + public virtual bool DoOrderRelease() + { + m_Mobile.DebugSay("I have been released"); + + m_Mobile.PlaySound(m_Mobile.GetAngerSound()); + + m_Mobile.SetControlMaster(null); + m_Mobile.SummonMaster = null; + + m_Mobile.BondingBegin = DateTime.MinValue; + m_Mobile.OwnerAbandonTime = DateTime.MinValue; + m_Mobile.IsBonded = false; + + SpawnEntry se = m_Mobile.Spawner as SpawnEntry; + if (se != null && se.HomeLocation != Point3D.Zero) + { + m_Mobile.Home = se.HomeLocation; + m_Mobile.RangeHome = se.HomeRange; + } + + if (m_Mobile.DeleteOnRelease || m_Mobile.IsDeadPet) + m_Mobile.Delete(); + + m_Mobile.BeginDeleteTimer(); + m_Mobile.DropBackpack(); + + return true; + } + + public virtual bool DoOrderStay() + { + if (CheckHerding()) + m_Mobile.DebugSay("Praise the shepherd!"); + else + m_Mobile.DebugSay("My master told me to stay"); + + //m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.ControlMaster ); + + return true; + } + + public virtual bool DoOrderStop() + { + if (m_Mobile.ControlMaster == null || m_Mobile.ControlMaster.Deleted) + return true; + + m_Mobile.DebugSay("My master told me to stop."); + + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.ControlMaster); + m_Mobile.Home = m_Mobile.Location; + + m_Mobile.ControlTarget = null; + + if (Core.ML) + { + WalkRandomInHome(3, 2, 1); + } + else + { + m_Mobile.ControlOrder = OrderType.None; + } + + return true; + } + + private class TransferItem : Item + { + public static bool IsInCombat(BaseCreature creature) + { + return (creature != null && (creature.Aggressors.Count > 0 || creature.Aggressed.Count > 0)); + } + + private BaseCreature m_Creature; + + public TransferItem(BaseCreature creature) + : base(ShrinkTable.Lookup(creature)) + { + m_Creature = creature; + + Movable = false; + + if (!Core.AOS) + { + Name = creature.Name; + } + else if (this.ItemID == ShrinkTable.DefaultItemID || creature.GetType().IsDefined(typeof(FriendlyNameAttribute), false) || creature is Reptalon) + Name = FriendlyNameAttribute.GetFriendlyNameFor(creature.GetType()).ToString(); + + //(As Per OSI)No name. Normally, set by the ItemID of the Shrink Item unless we either explicitly set it with an Attribute, or, no lookup found + + Hue = creature.Hue & 0x0FFF; + } + + public TransferItem(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(); + + Delete(); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1041603); // This item represents a pet currently in consideration for trade + list.Add(1041601, m_Creature.Name); // Pet Name: ~1_val~ + + if (m_Creature.ControlMaster != null) + list.Add(1041602, m_Creature.ControlMaster.Name); // Owner: ~1_val~ + } + + public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) + { + if (!base.AllowSecureTrade(from, to, newOwner, accepted)) + return false; + + if (Deleted || m_Creature == null || m_Creature.Deleted || m_Creature.ControlMaster != from || !from.CheckAlive() || !to.CheckAlive()) + return false; + + if (from.Map != m_Creature.Map || !from.InRange(m_Creature, 14)) + return false; + + bool youngFrom = from is PlayerMobile ? ((PlayerMobile)from).Young : false; + bool youngTo = to is PlayerMobile ? ((PlayerMobile)to).Young : false; + + if (accepted && youngFrom && !youngTo) + { + from.SendLocalizedMessage(502051); // As a young player, you may not transfer pets to older players. + } + else if (accepted && !youngFrom && youngTo) + { + from.SendLocalizedMessage(502052); // As an older player, you may not transfer pets to young players. + } + else if (accepted && !m_Creature.CanBeControlledBy(to)) + { + string args = String.Format("{0}\t{1}\t ", to.Name, from.Name); + + from.SendLocalizedMessage(1043248, args); // The pet refuses to be transferred because it will not obey ~1_NAME~.~3_BLANK~ + to.SendLocalizedMessage(1043249, args); // The pet will not accept you as a master because it does not trust you.~3_BLANK~ + + return false; + } + else if (accepted && !m_Creature.CanBeControlledBy(from)) + { + string args = String.Format("{0}\t{1}\t ", to.Name, from.Name); + + from.SendLocalizedMessage(1043250, args); // The pet refuses to be transferred because it will not obey you sufficiently.~3_BLANK~ + to.SendLocalizedMessage(1043251, args); // The pet will not accept you as a master because it does not trust ~2_NAME~.~3_BLANK~ + } + else if (accepted && (to.Followers + m_Creature.ControlSlots) > to.FollowersMax) + { + to.SendLocalizedMessage(1049607); // You have too many followers to control that creature. + + return false; + } + else if (accepted && IsInCombat(m_Creature)) + { + from.SendMessage("You may not transfer a pet that has recently been in combat."); + to.SendMessage("The pet may not be transfered to you because it has recently been in combat."); + + return false; + } + + return true; + } + + public override void OnSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) + { + if (Deleted) + return; + + Delete(); + + if (m_Creature == null || m_Creature.Deleted || m_Creature.ControlMaster != from || !from.CheckAlive() || !to.CheckAlive()) + return; + + if (from.Map != m_Creature.Map || !from.InRange(m_Creature, 14)) + return; + + if (accepted) + { + if (m_Creature.SetControlMaster(to)) + { + if (m_Creature.Summoned) + m_Creature.SummonMaster = to; + + m_Creature.ControlTarget = to; + m_Creature.ControlOrder = OrderType.Follow; + + m_Creature.BondingBegin = DateTime.MinValue; + m_Creature.OwnerAbandonTime = DateTime.MinValue; + m_Creature.IsBonded = false; + + m_Creature.PlaySound(m_Creature.GetIdleSound()); + + string args = String.Format("{0}\t{1}\t{2}", from.Name, m_Creature.Name, to.Name); + + from.SendLocalizedMessage(1043253, args); // You have transferred your pet to ~3_GETTER~. + to.SendLocalizedMessage(1043252, args); // ~1_NAME~ has transferred the allegiance of ~2_PET_NAME~ to you. + } + } + } + } + + public virtual bool DoOrderTransfer() + { + if (m_Mobile.IsDeadPet) + return true; + + Mobile from = m_Mobile.ControlMaster; + Mobile to = m_Mobile.ControlTarget; + + if (from != to && from != null && !from.Deleted && to != null && !to.Deleted && to.Player) + { + m_Mobile.DebugSay("Begin transfer with {0}", to.Name); + + bool youngFrom = from is PlayerMobile ? ((PlayerMobile)from).Young : false; + bool youngTo = to is PlayerMobile ? ((PlayerMobile)to).Young : false; + + if (youngFrom && !youngTo) + { + from.SendLocalizedMessage(502051); // As a young player, you may not transfer pets to older players. + } + else if (!youngFrom && youngTo) + { + from.SendLocalizedMessage(502052); // As an older player, you may not transfer pets to young players. + } + else if (!m_Mobile.CanBeControlledBy(to)) + { + string args = String.Format("{0}\t{1}\t ", to.Name, from.Name); + + from.SendLocalizedMessage(1043248, args); // The pet refuses to be transferred because it will not obey ~1_NAME~.~3_BLANK~ + to.SendLocalizedMessage(1043249, args); // The pet will not accept you as a master because it does not trust you.~3_BLANK~ + } + else if (!m_Mobile.CanBeControlledBy(from)) + { + string args = String.Format("{0}\t{1}\t ", to.Name, from.Name); + + from.SendLocalizedMessage(1043250, args); // The pet refuses to be transferred because it will not obey you sufficiently.~3_BLANK~ + to.SendLocalizedMessage(1043251, args); // The pet will not accept you as a master because it does not trust ~2_NAME~.~3_BLANK~ + } + else if (TransferItem.IsInCombat(m_Mobile)) + { + from.SendMessage("You may not transfer a pet that has recently been in combat."); + to.SendMessage("The pet may not be transfered to you because it has recently been in combat."); + } + else + { + NetState fromState = from.NetState, toState = to.NetState; + + if (fromState != null && toState != null) + { + if (from.HasTrade) + { + from.SendLocalizedMessage(1010507); // You cannot transfer a pet with a trade pending + } + else if (to.HasTrade) + { + to.SendLocalizedMessage(1010507); // You cannot transfer a pet with a trade pending + } + else + { + Container c = fromState.AddTrade(toState); + c.DropItem(new TransferItem(m_Mobile)); + } + } + } + } + + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Stay; + + return true; + } + + public virtual bool DoBardPacified() + { + if (DateTime.Now < m_Mobile.BardEndTime) + { + m_Mobile.DebugSay("I am pacified, I wait"); + m_Mobile.Combatant = null; + m_Mobile.Warmode = false; + + } + else + { + m_Mobile.DebugSay("I'm not pacified any longer"); + m_Mobile.BardPacified = false; + } + + return true; + } + + public virtual bool DoBardProvoked() + { + if (DateTime.Now >= m_Mobile.BardEndTime && (m_Mobile.BardMaster == null || m_Mobile.BardMaster.Deleted || m_Mobile.BardMaster.Map != m_Mobile.Map || m_Mobile.GetDistanceToSqrt(m_Mobile.BardMaster) > m_Mobile.RangePerception)) + { + m_Mobile.DebugSay("I have lost my provoker"); + m_Mobile.BardProvoked = false; + m_Mobile.BardMaster = null; + m_Mobile.BardTarget = null; + + m_Mobile.Combatant = null; + m_Mobile.Warmode = false; + } + else + { + if (m_Mobile.BardTarget == null || m_Mobile.BardTarget.Deleted || m_Mobile.BardTarget.Map != m_Mobile.Map || m_Mobile.GetDistanceToSqrt(m_Mobile.BardTarget) > m_Mobile.RangePerception) + { + m_Mobile.DebugSay("I have lost my provoke target"); + m_Mobile.BardProvoked = false; + m_Mobile.BardMaster = null; + m_Mobile.BardTarget = null; + + m_Mobile.Combatant = null; + m_Mobile.Warmode = false; + } + else + { + m_Mobile.Combatant = m_Mobile.BardTarget; + m_Action = ActionType.Combat; + + m_Mobile.OnThink(); + Think(); + } + } + + return true; + } + + public virtual void WalkRandom(int iChanceToNotMove, int iChanceToDir, int iSteps) + { + if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves) + return; + + for (int i = 0; i < iSteps; i++) + { + if (Utility.Random(8 * iChanceToNotMove) <= 8) + { + int iRndMove = Utility.Random(0, 8 + (9 * iChanceToDir)); + + switch (iRndMove) + { + case 0: + DoMove(Direction.Up); + break; + case 1: + DoMove(Direction.North); + break; + case 2: + DoMove(Direction.Left); + break; + case 3: + DoMove(Direction.West); + break; + case 5: + DoMove(Direction.Down); + break; + case 6: + DoMove(Direction.South); + break; + case 7: + DoMove(Direction.Right); + break; + case 8: + DoMove(Direction.East); + break; + default: + DoMove(m_Mobile.Direction); + break; + } + } + } + } + + public double TransformMoveDelay(double delay) + { + bool isPassive = (delay == m_Mobile.PassiveSpeed); + bool isControlled = (m_Mobile.Controlled || m_Mobile.Summoned); + + if (delay == 0.2) + delay = 0.3; + else if (delay == 0.25) + delay = 0.45; + else if (delay == 0.3) + delay = 0.6; + else if (delay == 0.4) + delay = 0.9; + else if (delay == 0.5) + delay = 1.05; + else if (delay == 0.6) + delay = 1.2; + else if (delay == 0.8) + delay = 1.5; + + if (isPassive) + delay += 0.2; + + if (!isControlled) + { + delay += 0.1; + } + else if (m_Mobile.Controlled) + { + if (m_Mobile.ControlOrder == OrderType.Follow && m_Mobile.ControlTarget == m_Mobile.ControlMaster) + delay *= 0.5; + + delay -= 0.075; + } + + if (m_Mobile.ReduceSpeedWithDamage || m_Mobile.IsSubdued) + { + double offset = (double)m_Mobile.Hits / m_Mobile.HitsMax; + + if (offset < 0.0) + offset = 0.0; + else if (offset > 1.0) + offset = 1.0; + + offset = 1.0 - offset; + + delay += (offset * 0.8); + } + + if (delay < 0.0) + delay = 0.0; + + if (double.IsNaN(delay)) + { + using (StreamWriter op = new StreamWriter("nan_transform.txt", true)) + { + op.WriteLine(String.Format("NaN in TransformMoveDelay: {0}, {1}, {2}, {3}", DateTime.Now, this.GetType().ToString(), m_Mobile == null ? "null" : m_Mobile.GetType().ToString(), m_Mobile.HitsMax)); + } + + return 1.0; + } + + return delay; + } + + private DateTime m_NextMove; + + public DateTime NextMove + { + get { return m_NextMove; } + set { m_NextMove = value; } + } + + public virtual bool CheckMove() + { + return (DateTime.Now >= m_NextMove); + } + + public virtual bool DoMove(Direction d) + { + return DoMove(d, false); + } + + public virtual bool DoMove(Direction d, bool badStateOk) + { + MoveResult res = DoMoveImpl(d); + + return (res == MoveResult.Success || res == MoveResult.SuccessAutoTurn || (badStateOk && res == MoveResult.BadState)); + } + + private static Queue m_Obstacles = new Queue(); + + public virtual MoveResult DoMoveImpl(Direction d) + { + if (m_Mobile.Deleted || m_Mobile.Frozen || m_Mobile.Paralyzed || (m_Mobile.Spell != null && m_Mobile.Spell.IsCasting) || m_Mobile.DisallowAllMoves) + return MoveResult.BadState; + else if (!CheckMove()) + return MoveResult.BadState; + + // This makes them always move one step, never any direction changes + m_Mobile.Direction = d; + + TimeSpan delay = TimeSpan.FromSeconds(TransformMoveDelay(m_Mobile.CurrentSpeed)); + + m_NextMove += delay; + + if (m_NextMove < DateTime.Now) + m_NextMove = DateTime.Now; + + m_Mobile.Pushing = false; + + MoveImpl.IgnoreMovableImpassables = (m_Mobile.CanMoveOverObstacles && !m_Mobile.CanDestroyObstacles); + + if ((m_Mobile.Direction & Direction.Mask) != (d & Direction.Mask)) + { + bool v = m_Mobile.Move(d); + + MoveImpl.IgnoreMovableImpassables = false; + return (v ? MoveResult.Success : MoveResult.Blocked); + } + else if (!m_Mobile.Move(d)) + { + bool wasPushing = m_Mobile.Pushing; + + bool blocked = true; + + bool canOpenDoors = m_Mobile.CanOpenDoors; + bool canDestroyObstacles = m_Mobile.CanDestroyObstacles; + + if (canOpenDoors || canDestroyObstacles) + { + m_Mobile.DebugSay("My movement was blocked, I will try to clear some obstacles."); + + Map map = m_Mobile.Map; + + if (map != null) + { + int x = m_Mobile.X, y = m_Mobile.Y; + Movement.Movement.Offset(d, ref x, ref y); + + int destroyables = 0; + + IPooledEnumerable eable = map.GetItemsInRange(new Point3D(x, y, m_Mobile.Location.Z), 1); + + foreach (Item item in eable) + { + if (canOpenDoors && item is BaseDoor && (item.Z + item.ItemData.Height) > m_Mobile.Z && (m_Mobile.Z + 16) > item.Z) + { + if (item.X != x || item.Y != y) + continue; + + BaseDoor door = (BaseDoor)item; + + if (!door.Locked || !door.UseLocks()) + m_Obstacles.Enqueue(door); + + if (!canDestroyObstacles) + break; + } + else if (canDestroyObstacles && item.Movable && item.ItemData.Impassable && (item.Z + item.ItemData.Height) > m_Mobile.Z && (m_Mobile.Z + 16) > item.Z) + { + if (!m_Mobile.InRange(item.GetWorldLocation(), 1)) + continue; + + m_Obstacles.Enqueue(item); + ++destroyables; + } + } + + eable.Free(); + + if (destroyables > 0) + Effects.PlaySound(new Point3D(x, y, m_Mobile.Z), m_Mobile.Map, 0x3B3); + + if (m_Obstacles.Count > 0) + blocked = false; // retry movement + + while (m_Obstacles.Count > 0) + { + Item item = (Item)m_Obstacles.Dequeue(); + + if (item is BaseDoor) + { + m_Mobile.DebugSay("Little do they expect, I've learned how to open doors. Didn't they read the script??"); + m_Mobile.DebugSay("*twist*"); + + ((BaseDoor)item).Use(m_Mobile); + } + else + { + m_Mobile.DebugSay("Ugabooga. I'm so big and tough I can destroy it: {0}", item.GetType().Name); + + if (item is Container) + { + Container cont = (Container)item; + + for (int i = 0; i < cont.Items.Count; ++i) + { + Item check = cont.Items[i]; + + if (check.Movable && check.ItemData.Impassable && (item.Z + check.ItemData.Height) > m_Mobile.Z) + m_Obstacles.Enqueue(check); + } + + cont.Destroy(); + } + else + { + item.Delete(); + } + } + } + + if (!blocked) + blocked = !m_Mobile.Move(d); + } + } + + if (blocked) + { + int offset = (Utility.RandomDouble() >= 0.6 ? 1 : -1); + + for (int i = 0; i < 2; ++i) + { + m_Mobile.TurnInternal(offset); + + if (m_Mobile.Move(m_Mobile.Direction)) + { + MoveImpl.IgnoreMovableImpassables = false; + return MoveResult.SuccessAutoTurn; + } + } + + MoveImpl.IgnoreMovableImpassables = false; + return (wasPushing ? MoveResult.BadState : MoveResult.Blocked); + } + else + { + MoveImpl.IgnoreMovableImpassables = false; + return MoveResult.Success; + } + } + + MoveImpl.IgnoreMovableImpassables = false; + return MoveResult.Success; + } + + public virtual void WalkRandomInHome(int iChanceToNotMove, int iChanceToDir, int iSteps) + { + if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves) + return; + + if (m_Mobile.Home == Point3D.Zero) + { + if (m_Mobile.Spawner is SpawnEntry) + { + Region region = ((SpawnEntry)m_Mobile.Spawner).Region; + + if (m_Mobile.Region.AcceptsSpawnsFrom(region)) + { + m_Mobile.WalkRegion = region; + WalkRandom(iChanceToNotMove, iChanceToDir, iSteps); + m_Mobile.WalkRegion = null; + } + else + { + if (region.GoLocation != Point3D.Zero && Utility.Random(10) > 5) + { + DoMove(m_Mobile.GetDirectionTo(region.GoLocation)); + } + else + { + WalkRandom(iChanceToNotMove, iChanceToDir, 1); + } + } + } + else + { + WalkRandom(iChanceToNotMove, iChanceToDir, iSteps); + } + } + else + { + for (int i = 0; i < iSteps; i++) + { + if (m_Mobile.RangeHome != 0) + { + int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m_Mobile.Home); + + if (iCurrDist < m_Mobile.RangeHome * 2 / 3) + { + WalkRandom(iChanceToNotMove, iChanceToDir, 1); + } + else if (iCurrDist > m_Mobile.RangeHome) + { + DoMove(m_Mobile.GetDirectionTo(m_Mobile.Home)); + } + else + { + if (Utility.Random(10) > 5) + { + DoMove(m_Mobile.GetDirectionTo(m_Mobile.Home)); + } + else + { + WalkRandom(iChanceToNotMove, iChanceToDir, 1); + } + } + } + else + { + if (m_Mobile.Location != m_Mobile.Home) + { + DoMove(m_Mobile.GetDirectionTo(m_Mobile.Home)); + } + } + } + } + } + + public virtual bool CheckFlee() + { + if (m_Mobile.CheckFlee()) + { + Mobile combatant = m_Mobile.Combatant; + + if (combatant == null) + { + WalkRandom(1, 2, 1); + } + else + { + Direction d = combatant.GetDirectionTo(m_Mobile); + + d = (Direction)((int)d + Utility.RandomMinMax(-1, +1)); + + m_Mobile.Direction = d; + m_Mobile.Move(d); + } + + return true; + } + + return false; + } + + protected PathFollower m_Path; + + public virtual void OnTeleported() + { + if (m_Path != null) + { + m_Mobile.DebugSay("Teleported; repathing"); + m_Path.ForceRepath(); + } + } + + public virtual bool MoveTo(Mobile m, bool run, int range) + { + if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves || m == null || m.Deleted) + return false; + + if (m_Mobile.InRange(m, range)) + { + m_Path = null; + return true; + } + + if (m_Path != null && m_Path.Goal == m) + { + if (m_Path.Follow(run, 1)) + { + m_Path = null; + return true; + } + } + else if (!DoMove(m_Mobile.GetDirectionTo(m), true)) + { + m_Path = new PathFollower(m_Mobile, m); + m_Path.Mover = new MoveMethod(DoMoveImpl); + + if (m_Path.Follow(run, 1)) + { + m_Path = null; + return true; + } + } + else + { + m_Path = null; + return true; + } + + return false; + } + /* * Walk at range distance from mobile * @@ -2333,74 +2338,74 @@ namespace Server.Mobiles * iWantDistMin : The minimum distance we want to be * iWantDistMax : The maximum distance we want to be * - */ - public virtual bool WalkMobileRange( Mobile m, int iSteps, bool bRun, int iWantDistMin, int iWantDistMax ) - { - if( m_Mobile.Deleted || m_Mobile.DisallowAllMoves ) - return false; - - if( m != null ) - { - for( int i=0; i iWantDistMax ) - { - bool needCloser = (iCurrDist > iWantDistMax); - bool needFurther = !needCloser; - - if( needCloser && m_Path != null && m_Path.Goal == m ) - { - if( m_Path.Follow( bRun, 1 ) ) - m_Path = null; - } - else - { - Direction dirTo; - - if( iCurrDist > iWantDistMax ) - dirTo = m_Mobile.GetDirectionTo( m ); - else - dirTo = m.GetDirectionTo( m_Mobile ); - - // Add the run flag - if( bRun ) - dirTo = dirTo | Direction.Running; - - if( !DoMove( dirTo, true ) && needCloser ) - { - m_Path = new PathFollower( m_Mobile, m ); - m_Path.Mover = new MoveMethod( DoMoveImpl ); - - if( m_Path.Follow( bRun, 1 ) ) - m_Path = null; - } - else - { - m_Path = null; - } - } - } - else - { - return true; - } - } - - // Get the curent distance - int iNewDist = (int)m_Mobile.GetDistanceToSqrt( m ); - - if( iNewDist >= iWantDistMin && iNewDist <= iWantDistMax ) - return true; - else - return false; - } - - return false; - } - + */ + public virtual bool WalkMobileRange(Mobile m, int iSteps, bool bRun, int iWantDistMin, int iWantDistMax) + { + if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves) + return false; + + if (m != null) + { + for (int i = 0; i < iSteps; i++) + { + // Get the curent distance + int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m); + + if (iCurrDist < iWantDistMin || iCurrDist > iWantDistMax) + { + bool needCloser = (iCurrDist > iWantDistMax); + bool needFurther = !needCloser; + + if (needCloser && m_Path != null && m_Path.Goal == m) + { + if (m_Path.Follow(bRun, 1)) + m_Path = null; + } + else + { + Direction dirTo; + + if (iCurrDist > iWantDistMax) + dirTo = m_Mobile.GetDirectionTo(m); + else + dirTo = m.GetDirectionTo(m_Mobile); + + // Add the run flag + if (bRun) + dirTo = dirTo | Direction.Running; + + if (!DoMove(dirTo, true) && needCloser) + { + m_Path = new PathFollower(m_Mobile, m); + m_Path.Mover = new MoveMethod(DoMoveImpl); + + if (m_Path.Follow(bRun, 1)) + m_Path = null; + } + else + { + m_Path = null; + } + } + } + else + { + return true; + } + } + + // Get the curent distance + int iNewDist = (int)m_Mobile.GetDistanceToSqrt(m); + + if (iNewDist >= iWantDistMin && iNewDist <= iWantDistMax) + return true; + else + return false; + } + + return false; + } + /* * Here we check to acquire a target from our surronding * @@ -2410,408 +2415,410 @@ namespace Server.Mobiles * bFacFriend : Check people in my faction * bFacFoe : Check people in other factions * - */ - public virtual bool AcquireFocusMob( int iRange, FightMode acqType, bool bPlayerOnly, bool bFacFriend, bool bFacFoe ) - { - if( m_Mobile.Deleted ) - return false; - - if( m_Mobile.BardProvoked ) - { - if( m_Mobile.BardTarget == null || m_Mobile.BardTarget.Deleted ) - { - m_Mobile.FocusMob = null; - return false; - } - else - { - m_Mobile.FocusMob = m_Mobile.BardTarget; - return (m_Mobile.FocusMob != null); - } - } - else if( m_Mobile.Controlled ) - { - if( m_Mobile.ControlTarget == null || m_Mobile.ControlTarget.Deleted || m_Mobile.ControlTarget.Hidden || !m_Mobile.ControlTarget.Alive || m_Mobile.ControlTarget.IsDeadBondedPet || !m_Mobile.InRange( m_Mobile.ControlTarget, m_Mobile.RangePerception * 2 ) ) - { - if ( m_Mobile.ControlTarget != null && m_Mobile.ControlTarget != m_Mobile.ControlMaster ) - m_Mobile.ControlTarget = null; - - m_Mobile.FocusMob = null; - return false; - } - else - { - m_Mobile.FocusMob = m_Mobile.ControlTarget; - return (m_Mobile.FocusMob != null); - } - } - - if( m_Mobile.ConstantFocus != null ) - { - m_Mobile.DebugSay( "Acquired my constant focus" ); - m_Mobile.FocusMob = m_Mobile.ConstantFocus; - return true; - } - - if( acqType == FightMode.None ) - { - m_Mobile.FocusMob = null; - return false; - } - - if ( acqType == FightMode.Aggressor && m_Mobile.Aggressors.Count == 0 && m_Mobile.Aggressed.Count == 0 && m_Mobile.FactionAllegiance == null && m_Mobile.EthicAllegiance == null ) - { - m_Mobile.FocusMob = null; - return false; - } - - if( m_Mobile.NextReacquireTime > DateTime.Now ) - { - m_Mobile.FocusMob = null; - return false; - } - - m_Mobile.NextReacquireTime = DateTime.Now + m_Mobile.ReacquireDelay; - - m_Mobile.DebugSay( "Acquiring..." ); - - Map map = m_Mobile.Map; - - if( map != null ) - { - Mobile newFocusMob = null; - double val = double.MinValue; - double theirVal; - - IPooledEnumerable eable = map.GetMobilesInRange( m_Mobile.Location, iRange ); - - foreach( Mobile m in eable ) - { - if ( m.Deleted || m.Blessed ) - continue; - - // Let's not target ourselves... - if ( m == m_Mobile || m is BaseFamiliar ) - continue; - - // Dead targets are invalid. - if ( !m.Alive || m.IsDeadBondedPet ) - continue; - - // Staff members cannot be targeted. - if ( m.AccessLevel > AccessLevel.Player ) - continue; - - // Does it have to be a player? - if ( bPlayerOnly && !m.Player ) - continue; - - // Can't acquire a target we can't see. - if ( !m_Mobile.CanSee( m ) ) - continue; - - if( Core.AOS && m is BaseCreature && ( m as BaseCreature ).Summoned && !( m as BaseCreature ).Controlled ) - continue; - - if ( m_Mobile.Summoned && m_Mobile.SummonMaster != null ) - { - // If this is a summon, it can't target its controller. - if ( m == m_Mobile.SummonMaster ) - continue; - - // It also must abide by harmful spell rules. - if ( !Server.Spells.SpellHelper.ValidIndirectTarget( m_Mobile.SummonMaster, m ) ) - continue; - - // Animated creatures cannot attack players directly. - if ( m is PlayerMobile && m_Mobile.IsAnimatedDead ) - continue; - } - - // If we only want faction friends, make sure it's one. - if ( bFacFriend && !m_Mobile.IsFriend( m ) ) - continue; - - //Ignore anyone under EtherealVoyage - if( TransformationSpellHelper.UnderTransformation( m, typeof( EtherealVoyageSpell ) ) ) - continue; - - // Ignore players with activated honor - if ( m is PlayerMobile && ( (PlayerMobile)m ).HonorActive && !( m_Mobile.Combatant == m )) - continue; - - if( acqType == FightMode.Aggressor || acqType == FightMode.Evil ) - { - bool bValid = IsHostile( m ); - - if ( !bValid ) - bValid = ( m_Mobile.GetFactionAllegiance( m ) == BaseCreature.Allegiance.Enemy || m_Mobile.GetEthicAllegiance( m ) == BaseCreature.Allegiance.Enemy ); - - if ( acqType == FightMode.Evil && !bValid ) - { - if( m is BaseCreature && ((BaseCreature)m).Controlled && ((BaseCreature)m).ControlMaster != null ) - bValid = ( ((BaseCreature)m).ControlMaster.Karma < 0 ); - else - bValid = ( m.Karma < 0 ); - } - - if ( !bValid ) - continue; - } else { - // Same goes for faction enemies. - if ( bFacFoe && !m_Mobile.IsEnemy( m ) ) - continue; - - // If it's an enemy factioned mobile, make sure we can be harmful to it. - if ( bFacFoe && !bFacFriend && !m_Mobile.CanBeHarmful( m, false ) ) - continue; - } - - theirVal = m_Mobile.GetFightModeRanking( m, acqType, bPlayerOnly ); - - if( theirVal > val && m_Mobile.InLOS( m ) ) - { - newFocusMob = m; - val = theirVal; - } - } - - eable.Free(); - - m_Mobile.FocusMob = newFocusMob; - } - - return (m_Mobile.FocusMob != null); - } - - private bool IsHostile( Mobile from ) - { - int count = Math.Max( m_Mobile.Aggressors.Count, m_Mobile.Aggressed.Count ); - - if( m_Mobile.Combatant == from || from.Combatant == m_Mobile ) - { - return true; - } - - if( count > 0 ) - { - for( int a = 0; a < count; ++a ) - { - if( a < m_Mobile.Aggressed.Count && m_Mobile.Aggressed[ a ].Attacker == from ) - { - return true; - } - - if( a < m_Mobile.Aggressors.Count && m_Mobile.Aggressors[ a ].Defender == from ) - { - return true; - } - } - } - - return false; - } - - - public virtual void DetectHidden() - { - if( m_Mobile.Deleted || m_Mobile.Map == null ) - return; - - m_Mobile.DebugSay( "Checking for hidden players" ); - - double srcSkill = m_Mobile.Skills[SkillName.DetectHidden].Value; - - if( srcSkill <= 0 ) - return; - - foreach( Mobile trg in m_Mobile.GetMobilesInRange( m_Mobile.RangePerception ) ) - { - if( trg != m_Mobile && trg.Player && trg.Alive && trg.Hidden && trg.AccessLevel == AccessLevel.Player && m_Mobile.InLOS( trg ) ) - { - m_Mobile.DebugSay( "Trying to detect {0}", trg.Name ); - - double trgHiding = trg.Skills[SkillName.Hiding].Value / 2.9; - double trgStealth = trg.Skills[SkillName.Stealth].Value / 1.8; - - double chance = srcSkill / 1.2 - Math.Min( trgHiding, trgStealth ); - - if( chance < srcSkill / 10 ) - chance = srcSkill / 10; - - chance /= 100; - - if( chance > Utility.RandomDouble() ) - { - trg.RevealingAction(); - trg.SendLocalizedMessage( 500814 ); // You have been revealed! - } - } - } - } - - public virtual void Deactivate() - { - if( m_Mobile.PlayerRangeSensitive ) - { - m_Timer.Stop(); - - SpawnEntry se = m_Mobile.Spawner as SpawnEntry; - - if( se != null && se.ReturnOnDeactivate && !m_Mobile.Controlled ) - { - if( se.HomeLocation == Point3D.Zero ) - { - if( !m_Mobile.Region.AcceptsSpawnsFrom( se.Region ) ) - { - Timer.DelayCall( TimeSpan.Zero, new TimerCallback( ReturnToHome ) ); - } - } - else if( !m_Mobile.InRange( se.HomeLocation, se.HomeRange ) ) - { - Timer.DelayCall( TimeSpan.Zero, new TimerCallback( ReturnToHome ) ); - } - } - } - } - - private void ReturnToHome() - { - SpawnEntry se = m_Mobile.Spawner as SpawnEntry; - - if( se != null ) - { - Point3D loc = se.RandomSpawnLocation( 16, !m_Mobile.CantWalk, m_Mobile.CanSwim ); - - if( loc != Point3D.Zero ) - { - m_Mobile.MoveToWorld( loc, se.Region.Map ); - return; - } - } - } - - public virtual void Activate() - { - if( !m_Timer.Running ) - { - m_Timer.Delay = TimeSpan.Zero; - m_Timer.Start(); - } - } - + */ + public virtual bool AcquireFocusMob(int iRange, FightMode acqType, bool bPlayerOnly, bool bFacFriend, bool bFacFoe) + { + if (m_Mobile.Deleted) + return false; + + if (m_Mobile.BardProvoked) + { + if (m_Mobile.BardTarget == null || m_Mobile.BardTarget.Deleted) + { + m_Mobile.FocusMob = null; + return false; + } + else + { + m_Mobile.FocusMob = m_Mobile.BardTarget; + return (m_Mobile.FocusMob != null); + } + } + else if (m_Mobile.Controlled) + { + if (m_Mobile.ControlTarget == null || m_Mobile.ControlTarget.Deleted || m_Mobile.ControlTarget.Hidden || !m_Mobile.ControlTarget.Alive || m_Mobile.ControlTarget.IsDeadBondedPet || !m_Mobile.InRange(m_Mobile.ControlTarget, m_Mobile.RangePerception * 2)) + { + if (m_Mobile.ControlTarget != null && m_Mobile.ControlTarget != m_Mobile.ControlMaster) + m_Mobile.ControlTarget = null; + + m_Mobile.FocusMob = null; + return false; + } + else + { + m_Mobile.FocusMob = m_Mobile.ControlTarget; + return (m_Mobile.FocusMob != null); + } + } + + if (m_Mobile.ConstantFocus != null) + { + m_Mobile.DebugSay("Acquired my constant focus"); + m_Mobile.FocusMob = m_Mobile.ConstantFocus; + return true; + } + + if (acqType == FightMode.None) + { + m_Mobile.FocusMob = null; + return false; + } + + if (acqType == FightMode.Aggressor && m_Mobile.Aggressors.Count == 0 && m_Mobile.Aggressed.Count == 0 && m_Mobile.FactionAllegiance == null && m_Mobile.EthicAllegiance == null) + { + m_Mobile.FocusMob = null; + return false; + } + + if (m_Mobile.NextReacquireTime > DateTime.Now) + { + m_Mobile.FocusMob = null; + return false; + } + + m_Mobile.NextReacquireTime = DateTime.Now + m_Mobile.ReacquireDelay; + + m_Mobile.DebugSay("Acquiring..."); + + Map map = m_Mobile.Map; + + if (map != null) + { + Mobile newFocusMob = null; + double val = double.MinValue; + double theirVal; + + IPooledEnumerable eable = map.GetMobilesInRange(m_Mobile.Location, iRange); + + foreach (Mobile m in eable) + { + if (m.Deleted || m.Blessed) + continue; + + // Let's not target ourselves... + if (m == m_Mobile || m is BaseFamiliar) + continue; + + // Dead targets are invalid. + if (!m.Alive || m.IsDeadBondedPet) + continue; + + // Staff members cannot be targeted. + if (m.AccessLevel > AccessLevel.Player) + continue; + + // Does it have to be a player? + if (bPlayerOnly && !m.Player) + continue; + + // Can't acquire a target we can't see. + if (!m_Mobile.CanSee(m)) + continue; + + if (Core.AOS && m is BaseCreature && (m as BaseCreature).Summoned && !(m as BaseCreature).Controlled) + continue; + + if (m_Mobile.Summoned && m_Mobile.SummonMaster != null) + { + // If this is a summon, it can't target its controller. + if (m == m_Mobile.SummonMaster) + continue; + + // It also must abide by harmful spell rules. + if (!Server.Spells.SpellHelper.ValidIndirectTarget(m_Mobile.SummonMaster, m)) + continue; + + // Animated creatures cannot attack players directly. + if (m is PlayerMobile && m_Mobile.IsAnimatedDead) + continue; + } + + // If we only want faction friends, make sure it's one. + if (bFacFriend && !m_Mobile.IsFriend(m)) + continue; + + //Ignore anyone under EtherealVoyage + if (TransformationSpellHelper.UnderTransformation(m, typeof(EtherealVoyageSpell))) + continue; + + // Ignore players with activated honor + if (m is PlayerMobile && ((PlayerMobile)m).HonorActive && !(m_Mobile.Combatant == m)) + continue; + + if (acqType == FightMode.Aggressor || acqType == FightMode.Evil) + { + bool bValid = IsHostile(m); + + if (!bValid) + bValid = (m_Mobile.GetFactionAllegiance(m) == BaseCreature.Allegiance.Enemy || m_Mobile.GetEthicAllegiance(m) == BaseCreature.Allegiance.Enemy); + + if (acqType == FightMode.Evil && !bValid) + { + if (m is BaseCreature && ((BaseCreature)m).Controlled && ((BaseCreature)m).ControlMaster != null) + bValid = (((BaseCreature)m).ControlMaster.Karma < 0); + else + bValid = (m.Karma < 0); + } + + if (!bValid) + continue; + } + else + { + // Same goes for faction enemies. + if (bFacFoe && !m_Mobile.IsEnemy(m)) + continue; + + // If it's an enemy factioned mobile, make sure we can be harmful to it. + if (bFacFoe && !bFacFriend && !m_Mobile.CanBeHarmful(m, false)) + continue; + } + + theirVal = m_Mobile.GetFightModeRanking(m, acqType, bPlayerOnly); + + if (theirVal > val && m_Mobile.InLOS(m)) + { + newFocusMob = m; + val = theirVal; + } + } + + eable.Free(); + + m_Mobile.FocusMob = newFocusMob; + } + + return (m_Mobile.FocusMob != null); + } + + private bool IsHostile(Mobile from) + { + int count = Math.Max(m_Mobile.Aggressors.Count, m_Mobile.Aggressed.Count); + + if (m_Mobile.Combatant == from || from.Combatant == m_Mobile) + { + return true; + } + + if (count > 0) + { + for (int a = 0; a < count; ++a) + { + if (a < m_Mobile.Aggressed.Count && m_Mobile.Aggressed[a].Attacker == from) + { + return true; + } + + if (a < m_Mobile.Aggressors.Count && m_Mobile.Aggressors[a].Defender == from) + { + return true; + } + } + } + + return false; + } + + + public virtual void DetectHidden() + { + if (m_Mobile.Deleted || m_Mobile.Map == null) + return; + + m_Mobile.DebugSay("Checking for hidden players"); + + double srcSkill = m_Mobile.Skills[SkillName.DetectHidden].Value; + + if (srcSkill <= 0) + return; + + foreach (Mobile trg in m_Mobile.GetMobilesInRange(m_Mobile.RangePerception)) + { + if (trg != m_Mobile && trg.Player && trg.Alive && trg.Hidden && trg.AccessLevel == AccessLevel.Player && m_Mobile.InLOS(trg)) + { + m_Mobile.DebugSay("Trying to detect {0}", trg.Name); + + double trgHiding = trg.Skills[SkillName.Hiding].Value / 2.9; + double trgStealth = trg.Skills[SkillName.Stealth].Value / 1.8; + + double chance = srcSkill / 1.2 - Math.Min(trgHiding, trgStealth); + + if (chance < srcSkill / 10) + chance = srcSkill / 10; + + chance /= 100; + + if (chance > Utility.RandomDouble()) + { + trg.RevealingAction(); + trg.SendLocalizedMessage(500814); // You have been revealed! + } + } + } + } + + public virtual void Deactivate() + { + if (m_Mobile.PlayerRangeSensitive) + { + m_Timer.Stop(); + + SpawnEntry se = m_Mobile.Spawner as SpawnEntry; + + if (se != null && se.ReturnOnDeactivate && !m_Mobile.Controlled) + { + if (se.HomeLocation == Point3D.Zero) + { + if (!m_Mobile.Region.AcceptsSpawnsFrom(se.Region)) + { + Timer.DelayCall(TimeSpan.Zero, new TimerCallback(ReturnToHome)); + } + } + else if (!m_Mobile.InRange(se.HomeLocation, se.HomeRange)) + { + Timer.DelayCall(TimeSpan.Zero, new TimerCallback(ReturnToHome)); + } + } + } + } + + private void ReturnToHome() + { + SpawnEntry se = m_Mobile.Spawner as SpawnEntry; + + if (se != null) + { + Point3D loc = se.RandomSpawnLocation(16, !m_Mobile.CantWalk, m_Mobile.CanSwim); + + if (loc != Point3D.Zero) + { + m_Mobile.MoveToWorld(loc, se.Region.Map); + return; + } + } + } + + public virtual void Activate() + { + if (!m_Timer.Running) + { + m_Timer.Delay = TimeSpan.Zero; + m_Timer.Start(); + } + } + /* * The mobile changed it speed, we must ajust the timer - */ - public virtual void OnCurrentSpeedChanged() - { - m_Timer.Stop(); - m_Timer.Delay = TimeSpan.FromSeconds( Utility.RandomDouble() ); - m_Timer.Interval = TimeSpan.FromSeconds( Math.Max( 0.0, m_Mobile.CurrentSpeed ) ); - m_Timer.Start(); - } - - private DateTime m_NextDetectHidden; - - public virtual bool CanDetectHidden { get { return m_Mobile.Skills[SkillName.DetectHidden].Value > 0; } } - + */ + public virtual void OnCurrentSpeedChanged() + { + m_Timer.Stop(); + m_Timer.Delay = TimeSpan.FromSeconds(Utility.RandomDouble()); + m_Timer.Interval = TimeSpan.FromSeconds(Math.Max(0.0, m_Mobile.CurrentSpeed)); + m_Timer.Start(); + } + + private DateTime m_NextDetectHidden; + + public virtual bool CanDetectHidden { get { return m_Mobile.Skills[SkillName.DetectHidden].Value > 0; } } + /* * The Timer object - */ - private class AITimer : Timer - { - private BaseAI m_Owner; - - public AITimer( BaseAI owner ) - : base( TimeSpan.FromSeconds( Utility.RandomDouble() ), TimeSpan.FromSeconds( Math.Max( 0.0, owner.m_Mobile.CurrentSpeed ) ) ) - { - m_Owner = owner; - - m_Owner.m_NextDetectHidden = DateTime.Now; - - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - if( m_Owner.m_Mobile.Deleted ) - { - Stop(); - return; - } - else if( m_Owner.m_Mobile.Map == null || m_Owner.m_Mobile.Map == Map.Internal ) - { - m_Owner.Deactivate(); - return; - } - else if( m_Owner.m_Mobile.PlayerRangeSensitive )//have to check this in the timer.... - { - Sector sect = m_Owner.m_Mobile.Map.GetSector( m_Owner.m_Mobile ); - if( !sect.Active ) - { - m_Owner.Deactivate(); - return; - } - } - - m_Owner.m_Mobile.OnThink(); - - if( m_Owner.m_Mobile.Deleted ) - { - Stop(); - return; - } - else if( m_Owner.m_Mobile.Map == null || m_Owner.m_Mobile.Map == Map.Internal ) - { - m_Owner.Deactivate(); - return; - } - - if( m_Owner.m_Mobile.BardPacified ) - { - m_Owner.DoBardPacified(); - } - else if( m_Owner.m_Mobile.BardProvoked ) - { - m_Owner.DoBardProvoked(); - } - else - { - if( !m_Owner.m_Mobile.Controlled ) - { - if( !m_Owner.Think() ) - { - Stop(); - return; - } - } - else - { - if( !m_Owner.Obey() ) - { - Stop(); - return; - } - } - } - - if( m_Owner.CanDetectHidden && DateTime.Now > m_Owner.m_NextDetectHidden ) - { - m_Owner.DetectHidden(); - - // Not exactly OSI style, approximation. - int delay = (15000 / m_Owner.m_Mobile.Int); - - if( delay > 60 ) - delay = 60; - - int min = delay * (9 / 10); // 13s at 1000 int, 33s at 400 int, 54s at <250 int - int max = delay * (10 / 9); // 16s at 1000 int, 41s at 400 int, 66s at <250 int - - m_Owner.m_NextDetectHidden = DateTime.Now + TimeSpan.FromSeconds( Utility.RandomMinMax( min, max ) ); - } - } - } - } -} - + */ + private class AITimer : Timer + { + private BaseAI m_Owner; + + public AITimer(BaseAI owner) + : base(TimeSpan.FromSeconds(Utility.RandomDouble()), TimeSpan.FromSeconds(Math.Max(0.0, owner.m_Mobile.CurrentSpeed))) + { + m_Owner = owner; + + m_Owner.m_NextDetectHidden = DateTime.Now; + + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + if (m_Owner.m_Mobile.Deleted) + { + Stop(); + return; + } + else if (m_Owner.m_Mobile.Map == null || m_Owner.m_Mobile.Map == Map.Internal) + { + m_Owner.Deactivate(); + return; + } + else if (m_Owner.m_Mobile.PlayerRangeSensitive)//have to check this in the timer.... + { + Sector sect = m_Owner.m_Mobile.Map.GetSector(m_Owner.m_Mobile); + if (!sect.Active) + { + m_Owner.Deactivate(); + return; + } + } + + m_Owner.m_Mobile.OnThink(); + + if (m_Owner.m_Mobile.Deleted) + { + Stop(); + return; + } + else if (m_Owner.m_Mobile.Map == null || m_Owner.m_Mobile.Map == Map.Internal) + { + m_Owner.Deactivate(); + return; + } + + if (m_Owner.m_Mobile.BardPacified) + { + m_Owner.DoBardPacified(); + } + else if (m_Owner.m_Mobile.BardProvoked) + { + m_Owner.DoBardProvoked(); + } + else + { + if (!m_Owner.m_Mobile.Controlled) + { + if (!m_Owner.Think()) + { + Stop(); + return; + } + } + else + { + if (!m_Owner.Obey()) + { + Stop(); + return; + } + } + } + + if (m_Owner.CanDetectHidden && DateTime.Now > m_Owner.m_NextDetectHidden) + { + m_Owner.DetectHidden(); + + // Not exactly OSI style, approximation. + int delay = (15000 / m_Owner.m_Mobile.Int); + + if (delay > 60) + delay = 60; + + int min = delay * (9 / 10); // 13s at 1000 int, 33s at 400 int, 54s at <250 int + int max = delay * (10 / 9); // 16s at 1000 int, 41s at 400 int, 66s at <250 int + + m_Owner.m_NextDetectHidden = DateTime.Now + TimeSpan.FromSeconds(Utility.RandomMinMax(min, max)); + } + } + } + } +} +