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.
This commit is contained in:
parent
9dfdf757a2
commit
e773309f17
3 changed files with 124 additions and 54 deletions
|
|
@ -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 )
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue