From e773309f17eb25b0659020f5d01d98db903ca4be Mon Sep 17 00:00:00 2001 From: xavier Date: Fri, 23 Nov 2012 21:57:03 +0000 Subject: [PATCH] uncontrolled summons will not be acquired by hostile mobiles, unless they attacked the mobile first. Necro familiars should be pretty much unlosable now... as well as not acquired by mobiles. --- Scripts/Mobiles/AI/BaseAI.cs | 70 ++++++++++++----- Scripts/Mobiles/BaseCreature.cs | 16 +++- Scripts/Mobiles/Familiars/BaseFamiliar.cs | 92 +++++++++++++++-------- 3 files changed, 124 insertions(+), 54 deletions(-) diff --git a/Scripts/Mobiles/AI/BaseAI.cs b/Scripts/Mobiles/AI/BaseAI.cs index d47646e5d..b8d681052 100644 --- a/Scripts/Mobiles/AI/BaseAI.cs +++ b/Scripts/Mobiles/AI/BaseAI.cs @@ -2491,7 +2491,7 @@ namespace Server.Mobiles continue; // Let's not target ourselves... - if ( m == m_Mobile ) + if ( m == m_Mobile || m is BaseFamiliar ) continue; // Dead targets are invalid. @@ -2537,35 +2537,33 @@ namespace Server.Mobiles if ( m is PlayerMobile && ( (PlayerMobile)m ).HonorActive && !( m_Mobile.Combatant == m )) continue; - if( acqType == FightMode.Aggressor || acqType == FightMode.Evil ) + if( acqType == FightMode.Aggressor || acqType == FightMode.Evil || ( m is BaseCreature ) && ( ( BaseCreature )m ).Summoned ) { - // Only acquire this mobile if it attacked us, or if it's evil. - bool bValid = false; + BaseCreature bc = m as BaseCreature; - for ( int a = 0; !bValid && a < m_Mobile.Aggressors.Count; ++a ) - bValid = ( m_Mobile.Aggressors[a].Attacker == m ); + bool bValid = IsHostile( m ); - for ( int a = 0; !bValid && a < m_Mobile.Aggressed.Count; ++a ) - bValid = ( m_Mobile.Aggressed[a].Defender == m ); - - #region Ethics & Faction checks - if ( !bValid ) + if( !bValid && ( !( m is BaseCreature ) || !bc.Summoned || bc.Controlled ) ) + { bValid = ( m_Mobile.GetFactionAllegiance( m ) == BaseCreature.Allegiance.Enemy || m_Mobile.GetEthicAllegiance( m ) == BaseCreature.Allegiance.Enemy ); - #endregion - if ( acqType == FightMode.Evil && !bValid ) - { - if( m is BaseCreature && ((BaseCreature)m).Controlled && ((BaseCreature)m).ControlMaster != null ) - bValid = ( ((BaseCreature)m).ControlMaster.Karma < 0 ); - else - bValid = ( (Core.AOS || m.Player) && m.Karma < 0 ); + if( acqType == FightMode.Evil && !bValid ) + { + if( m is BaseCreature && bc.Controlled && bc.ControlMaster != null ) + { + bValid = ( bc.ControlMaster.Karma < 0 ); + } + else + { + bValid = ( ( Core.AOS || m.Player ) && m.Karma < 0 ); + } + } } if ( !bValid ) continue; } else { - // Same goes for faction enemies. if ( bFacFoe && !m_Mobile.IsEnemy( m ) ) continue; @@ -2587,11 +2585,45 @@ namespace Server.Mobiles eable.Free(); m_Mobile.FocusMob = newFocusMob; + + if( m_Mobile.FocusMob is BaseFamiliar ) + { + m_Mobile.FocusMob = null; + } } 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 ) diff --git a/Scripts/Mobiles/BaseCreature.cs b/Scripts/Mobiles/BaseCreature.cs index 86c3df904..1b07a1979 100644 --- a/Scripts/Mobiles/BaseCreature.cs +++ b/Scripts/Mobiles/BaseCreature.cs @@ -1294,9 +1294,11 @@ namespace Server.Mobiles public HonorContext ReceivedHonorContext{ get{ return m_ReceivedHonorContext; } set{ m_ReceivedHonorContext = value; } } - public virtual void CheckStopFollow( Mobile from ) + public virtual bool CanBeDistracted { get { return true; } } + + public virtual void CheckDistracted( Mobile from ) { - if( ControlOrder == OrderType.Follow && Utility.RandomDouble() < .10 ) + if( Utility.RandomDouble() < .10 ) { ControlTarget = from; ControlOrder = OrderType.Attack; @@ -1342,7 +1344,10 @@ namespace Server.Mobiles if( !willKill ) { - CheckStopFollow( from ); + if( CanBeDistracted && ControlOrder == OrderType.Follow ) + { + CheckDistracted( from ); + } } else if( from is PlayerMobile ) { @@ -1354,7 +1359,10 @@ namespace Server.Mobiles public virtual void OnDamagedBySpell( Mobile from ) { - CheckStopFollow( from ); + if( CanBeDistracted && ControlOrder == OrderType.Follow ) + { + CheckDistracted( from ); + } } public virtual void OnHarmfulSpell( Mobile from ) diff --git a/Scripts/Mobiles/Familiars/BaseFamiliar.cs b/Scripts/Mobiles/Familiars/BaseFamiliar.cs index a250165d7..aa1418c2d 100644 --- a/Scripts/Mobiles/Familiars/BaseFamiliar.cs +++ b/Scripts/Mobiles/Familiars/BaseFamiliar.cs @@ -9,7 +9,8 @@ namespace Server.Mobiles { public abstract class BaseFamiliar : BaseCreature { - public BaseFamiliar() : base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 ) + public BaseFamiliar() + : base( AIType.AI_Melee, FightMode.Closest, 10, 1, -1, -1 ) { } @@ -17,54 +18,83 @@ namespace Server.Mobiles public override Poison PoisonImmune{ get{ return Poison.Lethal; } } public override bool Commandable{ get{ return false; } } + public override bool PlayerRangeSensitive { get { return false; } } + private bool m_LastHidden; + public virtual void RangeCheck() + { + if( !Deleted && ControlMaster != null && !ControlMaster.Deleted ) + { + int range = ( RangeHome - 2 ); + + if( !InRange( ControlMaster.Location, RangeHome ) ) + { + Mobile master = ControlMaster; + + Point3D m_Loc = Point3D.Zero; + + if( Map == master.Map ) + { + int x = ( X > master.X ) ? ( master.X + range ) : ( master.X - range ); + int y = ( Y > master.Y ) ? ( master.Y + range ) : ( master.Y - range ); + + for( int i = 0; i < 10; i++ ) + { + m_Loc.X = x + Utility.RandomMinMax( -1, 1 ); + m_Loc.Y = y + Utility.RandomMinMax( -1, 1 ); + + m_Loc.Z = Map.GetAverageZ( m_Loc.X, m_Loc.Y ); + + if( Map.CanSpawnMobile( m_Loc ) ) + { + break; + } + + m_Loc = master.Location; + } + + if( !Deleted ) + { + SetLocation( m_Loc, true ); + } + } + } + } + } + public override void OnThink() { - base.OnThink(); - Mobile master = ControlMaster; - if ( master == null ) + if( Deleted ) + { return; - - if ( master.Deleted ) + } + if( master == null || master.Deleted ) { DropPackContents(); EndRelease( null ); - return; } - if ( m_LastHidden != master.Hidden ) + RangeCheck(); + + if( m_LastHidden != master.Hidden ) Hidden = m_LastHidden = master.Hidden; - Mobile toAttack = null; - - if ( !Hidden ) + if( AIObject != null && AIObject.WalkMobileRange( master, 5, true, 1, 1 )) { - toAttack = master.Combatant; + Warmode = master.Warmode; + Combatant = master.Combatant; - if ( toAttack == this ) - toAttack = master; - else if ( toAttack == null ) - toAttack = this.Combatant; + CurrentSpeed = 0.10; } - - if ( Combatant != toAttack ) - Combatant = null; - - if ( toAttack == null ) + else { - if ( ControlTarget != master || ControlOrder != OrderType.Follow ) - { - ControlTarget = master; - ControlOrder = OrderType.Follow; - } - } - else if ( ControlTarget != toAttack || ControlOrder != OrderType.Attack ) - { - ControlTarget = toAttack; - ControlOrder = OrderType.Attack; + Warmode = false; + FocusMob = Combatant = null; + + CurrentSpeed = .01; } }