This commit is contained in:
mark 2006-06-15 04:14:30 +00:00
commit 47711d616e
2644 changed files with 479454 additions and 0 deletions

View file

@ -0,0 +1,157 @@
using System;
using System.Collections;
using Server.Targeting;
using Server.Network;
// Ideas
// When you run on animals the panic
// When if ( distance < 8 && Utility.RandomDouble() * Math.Sqrt( (8 - distance) / 6 ) >= incoming.Skills[SkillName.AnimalTaming].Value )
// More your close, the more it can panic
/*
* AnimalHunterAI, AnimalHidingAI, AnimalDomesticAI...
*
*/
namespace Server.Mobiles
{
public class AnimalAI : BaseAI
{
public AnimalAI(BaseCreature m) : base (m)
{
}
public override bool DoActionWander()
{
// Old:
#if false
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, true, false, true))
{
m_Mobile.DebugSay( "There is something near, I go away" );
Action = ActionType.Backoff;
}
else if ( m_Mobile.IsHurt() || m_Mobile.Combatant != null )
{
m_Mobile.DebugSay( "I am hurt or being attacked, I flee" );
Action = ActionType.Flee;
}
else
{
base.DoActionWander();
}
return true;
#endif
// New, only flee @ 10%
double hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax;
if ( !m_Mobile.Summoned && !m_Mobile.Controlled && hitPercent < 0.1 ) // Less than 10% health
{
m_Mobile.DebugSay( "I am low on health!" );
Action = ActionType.Flee;
}
else if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I have detected {0}, attacking", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
Mobile combatant = m_Mobile.Combatant;
if ( combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map )
{
m_Mobile.DebugSay( "My combatant is gone.." );
Action = ActionType.Wander;
return true;
}
if ( WalkMobileRange( combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight ) )
{
m_Mobile.Direction = m_Mobile.GetDirectionTo( combatant );
}
else
{
if ( m_Mobile.GetDistanceToSqrt( combatant ) > m_Mobile.RangePerception + 1 )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I cannot find {0}", combatant.Name );
Action = ActionType.Wander;
return true;
}
else
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I should be closer to {0}", combatant.Name );
}
}
if ( !m_Mobile.Controlled && !m_Mobile.Summoned )
{
double hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax;
if ( hitPercent < 0.1 )
{
m_Mobile.DebugSay( "I am low on health!" );
Action = ActionType.Flee;
}
}
return true;
}
public override bool DoActionBackoff()
{
double hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax;
if ( !m_Mobile.Summoned && !m_Mobile.Controlled && hitPercent < 0.1 ) // Less than 10% health
{
Action = ActionType.Flee;
}
else
{
if (AcquireFocusMob(m_Mobile.RangePerception * 2, FightMode.Closest, true, false , true))
{
if ( WalkMobileRange(m_Mobile.FocusMob, 1, false, m_Mobile.RangePerception, m_Mobile.RangePerception * 2) )
{
m_Mobile.DebugSay( "Well, here I am safe" );
Action = ActionType.Wander;
}
}
else
{
m_Mobile.DebugSay( "I have lost my focus, lets relax" );
Action = ActionType.Wander;
}
}
return true;
}
public override bool DoActionFlee()
{
AcquireFocusMob(m_Mobile.RangePerception * 2, m_Mobile.FightMode, true, false, true);
if ( m_Mobile.FocusMob == null )
m_Mobile.FocusMob = m_Mobile.Combatant;
return base.DoActionFlee();
}
}
}

View file

@ -0,0 +1,131 @@
using System;
using System.Collections;
using Server.Targeting;
using Server.Network;
using Server.Mobiles;
using Server.Items;
namespace Server.Mobiles
{
public class ArcherAI : BaseAI
{
public ArcherAI(BaseCreature m) : base (m)
{
}
public override bool DoActionWander()
{
m_Mobile.DebugSay( "I have no combatant" );
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I have detected {0} and I will attack", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
return base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
if ( m_Mobile.Combatant == null || m_Mobile.Combatant.Deleted || !m_Mobile.Combatant.Alive || m_Mobile.Combatant.IsDeadBondedPet )
{
m_Mobile.DebugSay("My combatant is deleted");
Action = ActionType.Guard;
return true;
}
if ( (m_Mobile.LastMoveTime + TimeSpan.FromSeconds( 1.0 )) < DateTime.Now )
{
if (WalkMobileRange(m_Mobile.Combatant, 1, true, m_Mobile.RangeFight, m_Mobile.Weapon.MaxRange))
{
// Be sure to face the combatant
m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant.Location);
}
else
{
if ( m_Mobile.Combatant != null )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I am still not in range of {0}", m_Mobile.Combatant.Name);
if ( (int) m_Mobile.GetDistanceToSqrt( m_Mobile.Combatant ) > m_Mobile.RangePerception + 1 )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I have lost {0}", m_Mobile.Combatant.Name);
m_Mobile.Combatant = null;
Action = ActionType.Guard;
return true;
}
}
}
}
// When we have no ammo, we flee
Container pack = m_Mobile.Backpack;
if ( pack == null || pack.FindItemByType( typeof( Arrow ) ) == null )
{
Action = ActionType.Flee;
return true;
}
// At 20% we should check if we must leave
if ( m_Mobile.Hits < m_Mobile.HitsMax*20/100 )
{
bool bFlee = false;
// if my current hits are more than my opponent, i don't care
if ( m_Mobile.Combatant != null && m_Mobile.Hits < m_Mobile.Combatant.Hits)
{
int iDiff = m_Mobile.Combatant.Hits - m_Mobile.Hits;
if ( Utility.Random(0, 100) > 10 + iDiff) // 10% to flee + the diff of hits
{
bFlee = true;
}
}
else if ( m_Mobile.Combatant != null && m_Mobile.Hits >= m_Mobile.Combatant.Hits)
{
if ( Utility.Random(0, 100) > 10 ) // 10% to flee
{
bFlee = true;
}
}
if (bFlee)
{
Action = ActionType.Flee;
}
}
return true;
}
public override bool DoActionGuard()
{
if ( AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I have detected {0}, attacking", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionGuard();
}
return true;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,87 @@
using System;
using System.Collections;
using Server.Targeting;
using Server.Network;
namespace Server.Mobiles
{
public class BerserkAI : BaseAI
{
public BerserkAI(BaseCreature m) : base (m)
{
}
public override bool DoActionWander()
{
m_Mobile.DebugSay( "I have No Combatant" );
if( AcquireFocusMob( m_Mobile.RangePerception, FightMode.Closest, false, true, true) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I have detected " + m_Mobile.FocusMob.Name + " and I will attack" );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
if( m_Mobile.Combatant == null || m_Mobile.Combatant.Deleted )
{
m_Mobile.DebugSay("My combatant is deleted");
Action = ActionType.Guard;
return true;
}
if( WalkMobileRange( m_Mobile.Combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight ) )
{
// Be sure to face the combatant
m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.Combatant.Location );
}
else
{
if( m_Mobile.Combatant != null )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay("I am still not in range of " + m_Mobile.Combatant.Name);
if( (int) m_Mobile.GetDistanceToSqrt( m_Mobile.Combatant ) > m_Mobile.RangePerception + 1 )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I have lost " + m_Mobile.Combatant.Name );
Action = ActionType.Guard;
return true;
}
}
}
return true;
}
public override bool DoActionGuard()
{
if ( AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, true, true ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I have detected {0}, attacking", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionGuard();
}
return true;
}
}
}

View file

@ -0,0 +1,176 @@
using System;
using System.Collections;
using Server.Targeting;
using Server.Network;
using Server.Spells;
using Server.Spells.First;
using Server.Spells.Second;
using Server.Spells.Fourth;
namespace Server.Mobiles
{
public class HealerAI : BaseAI
{
private static NeedDelegate m_Cure = new NeedDelegate( NeedCure );
private static NeedDelegate m_GHeal = new NeedDelegate( NeedGHeal );
private static NeedDelegate m_LHeal = new NeedDelegate( NeedLHeal );
private static NeedDelegate[] m_ACure = new NeedDelegate[] { m_Cure };
private static NeedDelegate[] m_AGHeal = new NeedDelegate[] { m_GHeal };
private static NeedDelegate[] m_ALHeal = new NeedDelegate[] { m_LHeal };
private static NeedDelegate[] m_All = new NeedDelegate[] { m_Cure, m_GHeal, m_LHeal };
public HealerAI( BaseCreature m ) : base( m )
{
}
public override bool Think()
{
if ( m_Mobile.Deleted )
return false;
Target targ = m_Mobile.Target;
if ( targ != null )
{
if ( targ is CureSpell.InternalTarget )
{
ProcessTarget( targ, m_ACure );
}
else if ( targ is GreaterHealSpell.InternalTarget )
{
ProcessTarget( targ, m_AGHeal );
}
else if ( targ is HealSpell.InternalTarget )
{
ProcessTarget( targ, m_ALHeal );
}
else
{
targ.Cancel( m_Mobile, TargetCancelType.Canceled );
}
}
else
{
Mobile toHelp = Find( m_All );
if ( toHelp != null )
{
if ( NeedCure( toHelp ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "{0} needs a cure", toHelp.Name );
if ( !(new CureSpell( m_Mobile, null )).Cast() )
new CureSpell( m_Mobile, null ).Cast();
}
else if ( NeedGHeal( toHelp ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "{0} needs a greater heal", toHelp.Name );
if ( !(new GreaterHealSpell( m_Mobile, null )).Cast() )
new HealSpell( m_Mobile, null ).Cast();
}
else if ( NeedLHeal( toHelp ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "{0} needs a lesser heal", toHelp.Name );
new HealSpell( m_Mobile, null ).Cast();
}
}
else
{
if ( AcquireFocusMob( m_Mobile.RangePerception, FightMode.Weakest, false, true, false ) )
{
WalkMobileRange( m_Mobile.FocusMob, 1, false, 4, 7 );
}
else
{
WalkRandomInHome( 3, 2, 1 );
}
}
}
return true;
}
private delegate bool NeedDelegate( Mobile m );
private void ProcessTarget( Target targ, NeedDelegate[] func )
{
Mobile toHelp = Find( func );
if ( toHelp != null )
{
if ( targ.Range != -1 && !m_Mobile.InRange( toHelp, targ.Range ) )
{
DoMove( m_Mobile.GetDirectionTo( toHelp ) | Direction.Running );
}
else
{
targ.Invoke( m_Mobile, toHelp );
}
}
else
{
targ.Cancel( m_Mobile, TargetCancelType.Canceled );
}
}
private Mobile Find( params NeedDelegate[] funcs )
{
if ( m_Mobile.Deleted )
return null;
Map map = m_Mobile.Map;
if ( map != null )
{
double prio = 0.0;
Mobile found = null;
foreach ( Mobile m in m_Mobile.GetMobilesInRange( m_Mobile.RangePerception ) )
{
if ( !m_Mobile.CanSee( m ) || !(m is BaseCreature) || ((BaseCreature)m).Team != m_Mobile.Team )
continue;
for ( int i = 0; i < funcs.Length; ++i )
{
if ( funcs[i]( m ) )
{
double val = -m_Mobile.GetDistanceToSqrt( m );
if ( found == null || val > prio )
{
prio = val;
found = m;
}
break;
}
}
}
return found;
}
return null;
}
private static bool NeedCure( Mobile m )
{
return m.Poisoned;
}
private static bool NeedGHeal( Mobile m )
{
return m.Hits < m.HitsMax - 40;
}
private static bool NeedLHeal( Mobile m )
{
return m.Hits < m.HitsMax - 10;
}
}
}

View file

@ -0,0 +1,992 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Server.Targeting;
using Server.Network;
using Server.Mobiles;
using Server.Items;
using Server.Spells;
using Server.Spells.First;
using Server.Spells.Second;
using Server.Spells.Third;
using Server.Spells.Fourth;
using Server.Spells.Fifth;
using Server.Spells.Sixth;
using Server.Spells.Seventh;
using Server.Misc;
using Server.Regions;
using Server.SkillHandlers;
namespace Server.Mobiles
{
public class MageAI : BaseAI
{
private DateTime m_NextCastTime;
private DateTime m_NextHealTime;
public MageAI( BaseCreature m ) : base( m )
{
}
public override bool Think()
{
if ( m_Mobile.Deleted )
return false;
if ( ProcessTarget() )
return true;
else
return base.Think();
}
public virtual bool SmartAI
{
get{ return ( m_Mobile is BaseVendor || m_Mobile is BaseEscortable ); }
}
private const double HealChance = 0.10; // 10% chance to heal at gm magery
private const double TeleportChance = 0.05; // 5% chance to teleport at gm magery
private const double DispelChance = 0.75; // 75% chance to dispel at gm magery
public virtual double ScaleByMagery( double v )
{
return m_Mobile.Skills[SkillName.Magery].Value * v * 0.01;
}
public override bool DoActionWander()
{
if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I am going to attack {0}", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
m_NextCastTime = DateTime.Now;
}
else if ( SmartAI && m_Mobile.Mana < m_Mobile.ManaMax )
{
m_Mobile.DebugSay( "I am going to meditate" );
m_Mobile.UseSkill( SkillName.Meditation );
}
else
{
m_Mobile.DebugSay( "I am wandering" );
m_Mobile.Warmode = false;
base.DoActionWander();
if ( !m_Mobile.Controlled )
{
Spell spell = CheckCastHealingSpell();
if ( spell != null )
spell.Cast();
}
}
return true;
}
private Spell CheckCastHealingSpell()
{
// If I'm poisoned, always attempt to cure.
if ( m_Mobile.Poisoned )
return new CureSpell( m_Mobile, null );
// Summoned creatures never heal themselves.
if ( m_Mobile.Summoned )
return null;
if ( m_Mobile.Controlled )
{
if ( DateTime.Now < m_NextHealTime )
return null;
}
if ( !SmartAI )
{
if ( ScaleByMagery( HealChance ) < Utility.RandomDouble() )
return null;
}
else
{
if ( Utility.Random( 0, 4 + (m_Mobile.Hits == 0 ? m_Mobile.HitsMax : (m_Mobile.HitsMax / m_Mobile.Hits)) ) < 3 )
return null;
}
Spell spell = null;
if ( m_Mobile.Hits < (m_Mobile.HitsMax - 50) )
{
spell = new GreaterHealSpell( m_Mobile, null );
if ( spell == null )
spell = new HealSpell( m_Mobile, null );
}
else if ( m_Mobile.Hits < (m_Mobile.HitsMax - 10) )
spell = new HealSpell( m_Mobile, null );
double delay;
if ( m_Mobile.Int >= 500 )
delay = Utility.RandomMinMax( 7, 10 );
else
delay = Math.Sqrt( 600 - m_Mobile.Int );
m_NextHealTime = DateTime.Now + TimeSpan.FromSeconds( delay );
return spell;
}
public void RunTo( Mobile m )
{
if ( !SmartAI )
{
if ( !MoveTo( m, true, m_Mobile.RangeFight ) )
OnFailedMove();
return;
}
if ( m.Paralyzed || m.Frozen )
{
if ( m_Mobile.InRange( m, 1 ) )
RunFrom( m );
else if ( !m_Mobile.InRange( m, m_Mobile.RangeFight > 2 ? m_Mobile.RangeFight : 2 ) && !MoveTo( m, true, 1 ) )
OnFailedMove();
}
else
{
if ( !m_Mobile.InRange( m, m_Mobile.RangeFight ) )
{
if ( !MoveTo( m, true, 1 ) )
OnFailedMove();
}
else if ( m_Mobile.InRange( m, m_Mobile.RangeFight - 1 ) )
{
RunFrom( m );
}
}
}
public void RunFrom( Mobile m )
{
Run( (m_Mobile.GetDirectionTo( m ) - 4) & Direction.Mask );
}
public void OnFailedMove()
{
if ( !m_Mobile.DisallowAllMoves && (SmartAI ? Utility.Random( 4 ) == 0 : ScaleByMagery( TeleportChance ) > Utility.RandomDouble()) )
{
if ( m_Mobile.Target != null )
m_Mobile.Target.Cancel( m_Mobile, TargetCancelType.Canceled );
new TeleportSpell( m_Mobile, null ).Cast();
m_Mobile.DebugSay( "I am stuck, I'm going to try teleporting away" );
}
else if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
m_Mobile.DebugSay( "I am stuck" );
}
}
public void Run( Direction d )
{
if ( (m_Mobile.Spell != null && m_Mobile.Spell.IsCasting) || m_Mobile.Paralyzed || m_Mobile.Frozen || m_Mobile.DisallowAllMoves )
return;
m_Mobile.Direction = d | Direction.Running;
if ( !DoMove( m_Mobile.Direction, true ) )
OnFailedMove();
}
public virtual Spell GetRandomDamageSpell()
{
int maxCircle = (int)((m_Mobile.Skills[SkillName.Magery].Value + 20.0) / (100.0 / 7.0));
if ( maxCircle < 1 )
maxCircle = 1;
switch ( Utility.Random( maxCircle*2 ) )
{
case 0: case 1: return new MagicArrowSpell( m_Mobile, null );
case 2: case 3: return new HarmSpell( m_Mobile, null );
case 4: case 5: return new FireballSpell( m_Mobile, null );
case 6: case 7: return new LightningSpell( m_Mobile, null );
case 8: case 9: return new MindBlastSpell( m_Mobile, null );
case 10: return new EnergyBoltSpell( m_Mobile, null );
case 11: return new ExplosionSpell( m_Mobile, null );
default: return new FlameStrikeSpell( m_Mobile, null );
}
}
public virtual Spell GetRandomCurseSpell()
{
if ( Utility.RandomBool() )
{
if ( m_Mobile.Skills[SkillName.Magery].Value >= 40.0 )
return new CurseSpell( m_Mobile, null );
}
switch ( Utility.Random( 3 ) )
{
default:
case 0: return new WeakenSpell( m_Mobile, null );
case 1: return new ClumsySpell( m_Mobile, null );
case 2: return new FeeblemindSpell( m_Mobile, null );
}
}
public virtual Spell GetRandomManaDrainSpell()
{
if ( Utility.RandomBool() )
{
if ( m_Mobile.Skills[SkillName.Magery].Value >= 80.0 )
return new ManaVampireSpell( m_Mobile, null );
}
return new ManaDrainSpell( m_Mobile, null );
}
public virtual Spell DoDispel( Mobile toDispel )
{
if ( !SmartAI )
{
if ( ScaleByMagery( DispelChance ) > Utility.RandomDouble() )
return new DispelSpell( m_Mobile, null );
return ChooseSpell( toDispel );
}
Spell spell = CheckCastHealingSpell();
if ( spell == null )
{
if ( !m_Mobile.DisallowAllMoves && Utility.Random( (int)m_Mobile.GetDistanceToSqrt( toDispel ) ) == 0 )
spell = new TeleportSpell( m_Mobile, null );
else if ( Utility.Random( 3 ) == 0 && !m_Mobile.InRange( toDispel, 3 ) && !toDispel.Paralyzed && !toDispel.Frozen )
spell = new ParalyzeSpell( m_Mobile, null );
else
spell = new DispelSpell( m_Mobile, null );
}
return spell;
}
public virtual Spell ChooseSpell( Mobile c )
{
Spell spell = null;
if ( !SmartAI )
{
spell = CheckCastHealingSpell();
if ( spell != null )
return spell;
switch ( Utility.Random( 16 ) )
{
case 0:
case 1:
case 2: // Poison them
{
m_Mobile.DebugSay( "Attempting to poison" );
if ( !c.Poisoned )
spell = new PoisonSpell( m_Mobile, null );
break;
}
case 3: // Bless ourselves.
{
m_Mobile.DebugSay( "Blessing myself" );
spell = new BlessSpell( m_Mobile, null );
break;
}
case 4:
case 5:
case 6: // Curse them.
{
m_Mobile.DebugSay( "Attempting to curse" );
spell = GetRandomCurseSpell();
break;
}
case 7: // Paralyze them.
{
m_Mobile.DebugSay( "Attempting to paralyze" );
if ( m_Mobile.Skills[SkillName.Magery].Value > 50.0 )
spell = new ParalyzeSpell( m_Mobile, null );
break;
}
case 8: // Drain mana
{
m_Mobile.DebugSay( "Attempting to drain mana" );
spell = GetRandomManaDrainSpell();
break;
}
default: // Damage them.
{
m_Mobile.DebugSay( "Just doing damage" );
spell = GetRandomDamageSpell();
break;
}
}
return spell;
}
spell = CheckCastHealingSpell();
if ( spell != null )
return spell;
switch ( Utility.Random( 3 ) )
{
default:
case 0: // Poison them
{
if ( !c.Poisoned )
spell = new PoisonSpell( m_Mobile, null );
break;
}
case 1: // Deal some damage
{
spell = GetRandomDamageSpell();
break;
}
case 2: // Set up a combo
{
if ( m_Mobile.Mana < 40 && m_Mobile.Mana > 15 )
{
if ( c.Paralyzed && !c.Poisoned )
{
m_Mobile.DebugSay( "I am going to meditate" );
m_Mobile.UseSkill( SkillName.Meditation );
}
else if ( !c.Poisoned )
{
spell = new ParalyzeSpell( m_Mobile, null );
}
}
else if ( m_Mobile.Mana > 60 )
{
if ( Utility.Random( 2 ) == 0 && !c.Paralyzed && !c.Frozen && !c.Poisoned )
{
m_Combo = 0;
spell = new ParalyzeSpell( m_Mobile, null );
}
else
{
m_Combo = 1;
spell = new ExplosionSpell( m_Mobile, null );
}
}
break;
}
}
return spell;
}
protected int m_Combo = -1;
public virtual Spell DoCombo( Mobile c )
{
Spell spell = null;
if ( m_Combo == 0 )
{
spell = new ExplosionSpell( m_Mobile, null );
++m_Combo; // Move to next spell
}
else if ( m_Combo == 1 )
{
spell = new WeakenSpell( m_Mobile, null );
++m_Combo; // Move to next spell
}
else if ( m_Combo == 2 )
{
if ( !c.Poisoned )
spell = new PoisonSpell( m_Mobile, null );
++m_Combo; // Move to next spell
}
if ( m_Combo == 3 && spell == null )
{
switch ( Utility.Random( 3 ) )
{
default:
case 0:
{
if ( c.Int < c.Dex )
spell = new FeeblemindSpell( m_Mobile, null );
else
spell = new ClumsySpell( m_Mobile, null );
++m_Combo; // Move to next spell
break;
}
case 1:
{
spell = new EnergyBoltSpell( m_Mobile, null );
m_Combo = -1; // Reset combo state
break;
}
case 2:
{
spell = new FlameStrikeSpell( m_Mobile, null );
m_Combo = -1; // Reset combo state
break;
}
}
}
else if ( m_Combo == 4 && spell == null )
{
spell = new MindBlastSpell( m_Mobile, null );
m_Combo = -1;
}
return spell;
}
private TimeSpan GetDelay()
{
double del = ScaleByMagery( 3.0 );
double min = 6.0 - (del * 0.75);
double max = 6.0 - (del * 1.25);
return TimeSpan.FromSeconds( min + ((max - min) * Utility.RandomDouble()) );
}
public override bool DoActionCombat()
{
Mobile c = m_Mobile.Combatant;
m_Mobile.Warmode = true;
if ( c == null || c.Deleted || !c.Alive || c.IsDeadBondedPet || !m_Mobile.CanSee( c ) || !m_Mobile.CanBeHarmful( c, false ) || c.Map != m_Mobile.Map )
{
// Our combatant is deleted, dead, hidden, or we cannot hurt them
// Try to find another combatant
if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "Something happened to my combatant, so I am going to fight {0}", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = c = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
else
{
m_Mobile.DebugSay( "Something happened to my combatant, and nothing is around. I am on guard." );
Action = ActionType.Guard;
return true;
}
}
if ( !m_Mobile.InLOS( c ) )
{
m_Mobile.DebugSay( "I can't see my target" );
if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
m_Mobile.DebugSay( "Nobody else is around" );
m_Mobile.Combatant = c = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
}
if ( SmartAI && !m_Mobile.StunReady && m_Mobile.Skills[SkillName.Wrestling].Value >= 80.0 && m_Mobile.Skills[SkillName.Anatomy].Value >= 80.0 )
EventSink.InvokeStunRequest( new StunRequestEventArgs( m_Mobile ) );
if ( !m_Mobile.InRange( c, m_Mobile.RangePerception ) )
{
// They are somewhat far away, can we find something else?
if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
m_Mobile.Combatant = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
else if ( !m_Mobile.InRange( c, m_Mobile.RangePerception * 3 ) )
{
m_Mobile.Combatant = null;
}
c = m_Mobile.Combatant;
if ( c == null )
{
m_Mobile.DebugSay( "My combatant has fled, so I am on guard" );
Action = ActionType.Guard;
return true;
}
}
if ( !m_Mobile.Controlled && !m_Mobile.Summoned && !m_Mobile.IsParagon )
{
if ( m_Mobile.Hits < m_Mobile.HitsMax * 20/100 )
{
// We are low on health, should we flee?
bool flee = false;
if ( m_Mobile.Hits < c.Hits )
{
// We are more hurt than them
int diff = c.Hits - m_Mobile.Hits;
flee = ( Utility.Random( 0, 100 ) > (10 + diff) ); // (10 + diff)% chance to flee
}
else
{
flee = Utility.Random( 0, 100 ) > 10; // 10% chance to flee
}
if ( flee )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I am going to flee from {0}", c.Name );
Action = ActionType.Flee;
return true;
}
}
}
if ( m_Mobile.Spell == null && DateTime.Now > m_NextCastTime && m_Mobile.InRange( c, 12 ) )
{
// We are ready to cast a spell
Spell spell = null;
Mobile toDispel = FindDispelTarget( true );
if ( m_Mobile.Poisoned ) // Top cast priority is cure
{
m_Mobile.DebugSay( "I am going to cure myself" );
spell = new CureSpell( m_Mobile, null );
}
else if ( toDispel != null ) // Something dispellable is attacking us
{
m_Mobile.DebugSay( "I am going to dispel {0}", toDispel );
spell = DoDispel( toDispel );
}
else if ( SmartAI && m_Combo != -1 ) // We are doing a spell combo
{
spell = DoCombo( c );
}
else if ( SmartAI && (c.Spell is HealSpell || c.Spell is GreaterHealSpell) && !c.Poisoned ) // They have a heal spell out
{
spell = new PoisonSpell( m_Mobile, null );
}
else
{
spell = ChooseSpell( c );
}
// Now we have a spell picked
// Move first before casting
if ( SmartAI && toDispel != null )
{
if ( m_Mobile.InRange( toDispel, 10 ) )
RunFrom( toDispel );
else if ( !m_Mobile.InRange( toDispel, 12 ) )
RunTo( toDispel );
}
else
{
RunTo( c );
}
if ( spell != null )
spell.Cast();
TimeSpan delay;
if ( SmartAI || ( spell is DispelSpell ) )
delay = TimeSpan.FromSeconds( m_Mobile.ActiveSpeed );
else
delay = GetDelay();
m_NextCastTime = DateTime.Now + delay;
}
else if ( m_Mobile.Spell == null || !m_Mobile.Spell.IsCasting )
{
RunTo( c );
}
return true;
}
public override bool DoActionGuard()
{
if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
m_Mobile.DebugSay( "I am going to attack {0}", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
if ( !m_Mobile.Controlled )
{
ProcessTarget();
Spell spell = CheckCastHealingSpell();
if ( spell != null )
spell.Cast();
}
base.DoActionGuard();
}
return true;
}
public override bool DoActionFlee()
{
Mobile c = m_Mobile.Combatant;
if ( (m_Mobile.Mana > 20 || m_Mobile.Mana == m_Mobile.ManaMax) && m_Mobile.Hits > (m_Mobile.HitsMax / 2) )
{
m_Mobile.DebugSay( "I am stronger now, my guard is up" );
Action = ActionType.Guard;
}
else if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I am scared of {0}", m_Mobile.FocusMob.Name );
RunFrom( m_Mobile.FocusMob );
m_Mobile.FocusMob = null;
if ( m_Mobile.Poisoned && Utility.Random( 0, 5 ) == 0 )
new CureSpell( m_Mobile, null ).Cast();
}
else
{
m_Mobile.DebugSay( "Area seems clear, but my guard is up" );
Action = ActionType.Guard;
m_Mobile.Warmode = true;
}
return true;
}
public Mobile FindDispelTarget( bool activeOnly )
{
if ( m_Mobile.Deleted || m_Mobile.Int < 95 || CanDispel( m_Mobile ) || m_Mobile.AutoDispel )
return null;
if ( activeOnly )
{
List<AggressorInfo> aggressed = m_Mobile.Aggressed;
List<AggressorInfo> aggressors = m_Mobile.Aggressors;
Mobile active = null;
double activePrio = 0.0;
Mobile comb = m_Mobile.Combatant;
if ( comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && m_Mobile.InRange( comb, 12 ) && CanDispel( comb ) )
{
active = comb;
activePrio = m_Mobile.GetDistanceToSqrt( comb );
if ( activePrio <= 2 )
return active;
}
for ( int i = 0; i < aggressed.Count; ++i )
{
AggressorInfo info = aggressed[i];
Mobile m = info.Defender;
if ( m != comb && m.Combatant == m_Mobile && m_Mobile.InRange( m, 12 ) && CanDispel( m ) )
{
double prio = m_Mobile.GetDistanceToSqrt( m );
if ( active == null || prio < activePrio )
{
active = m;
activePrio = prio;
if ( activePrio <= 2 )
return active;
}
}
}
for ( int i = 0; i < aggressors.Count; ++i )
{
AggressorInfo info = aggressors[i];
Mobile m = info.Attacker;
if ( m != comb && m.Combatant == m_Mobile && m_Mobile.InRange( m, 12 ) && CanDispel( m ) )
{
double prio = m_Mobile.GetDistanceToSqrt( m );
if ( active == null || prio < activePrio )
{
active = m;
activePrio = prio;
if ( activePrio <= 2 )
return active;
}
}
}
return active;
}
else
{
Map map = m_Mobile.Map;
if ( map != null )
{
Mobile active = null, inactive = null;
double actPrio = 0.0, inactPrio = 0.0;
Mobile comb = m_Mobile.Combatant;
if ( comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && CanDispel( comb ) )
{
active = inactive = comb;
actPrio = inactPrio = m_Mobile.GetDistanceToSqrt( comb );
}
foreach ( Mobile m in m_Mobile.GetMobilesInRange( 12 ) )
{
if ( m != m_Mobile && CanDispel( m ) )
{
double prio = m_Mobile.GetDistanceToSqrt( m );
if ( !activeOnly && (inactive == null || prio < inactPrio) )
{
inactive = m;
inactPrio = prio;
}
if ( (m_Mobile.Combatant == m || m.Combatant == m_Mobile) && (active == null || prio < actPrio) )
{
active = m;
actPrio = prio;
}
}
}
return active != null ? active : inactive;
}
}
return null;
}
public bool CanDispel( Mobile m )
{
return ( m is BaseCreature && ((BaseCreature)m).Summoned && m_Mobile.CanBeHarmful( m, false ) && !((BaseCreature)m).IsAnimatedDead );
}
private static int[] m_Offsets = new int[]
{
-1, -1,
-1, 0,
-1, 1,
0, -1,
0, 1,
1, -1,
1, 0,
1, 1,
-2, -2,
-2, -1,
-2, 0,
-2, 1,
-2, 2,
-1, -2,
-1, 2,
0, -2,
0, 2,
1, -2,
1, 2,
2, -2,
2, -1,
2, 0,
2, 1,
2, 2
};
private bool ProcessTarget()
{
Target targ = m_Mobile.Target;
if ( targ == null )
return false;
bool isDispel = ( targ is DispelSpell.InternalTarget );
bool isParalyze = ( targ is ParalyzeSpell.InternalTarget );
bool isTeleport = ( targ is TeleportSpell.InternalTarget );
bool teleportAway = false;
Mobile toTarget;
if ( isDispel )
{
toTarget = FindDispelTarget( false );
if ( !SmartAI && toTarget != null )
RunTo( toTarget );
else if ( toTarget != null && m_Mobile.InRange( toTarget, 10 ) )
RunFrom( toTarget );
}
else if ( SmartAI && (isParalyze || isTeleport) )
{
toTarget = FindDispelTarget( true );
if ( toTarget == null )
{
toTarget = m_Mobile.Combatant;
if ( toTarget != null )
RunTo( toTarget );
}
else if ( m_Mobile.InRange( toTarget, 10 ) )
{
RunFrom( toTarget );
teleportAway = true;
}
else
{
teleportAway = true;
}
}
else
{
toTarget = m_Mobile.Combatant;
if ( toTarget != null )
RunTo( toTarget );
}
if ( (targ.Flags & TargetFlags.Harmful) != 0 && toTarget != null )
{
if ( (targ.Range == -1 || m_Mobile.InRange( toTarget, targ.Range )) && m_Mobile.CanSee( toTarget ) && m_Mobile.InLOS( toTarget ) )
{
targ.Invoke( m_Mobile, toTarget );
}
else if ( isDispel )
{
targ.Cancel( m_Mobile, TargetCancelType.Canceled );
}
}
else if ( (targ.Flags & TargetFlags.Beneficial) != 0 )
{
targ.Invoke( m_Mobile, m_Mobile );
}
else if ( isTeleport && toTarget != null )
{
Map map = m_Mobile.Map;
if ( map == null )
{
targ.Cancel( m_Mobile, TargetCancelType.Canceled );
return true;
}
int px, py;
if ( teleportAway )
{
int rx = m_Mobile.X - toTarget.X;
int ry = m_Mobile.Y - toTarget.Y;
double d = m_Mobile.GetDistanceToSqrt( toTarget );
px = toTarget.X + (int)(rx * (10 / d));
py = toTarget.Y + (int)(ry * (10 / d));
}
else
{
px = toTarget.X;
py = toTarget.Y;
}
for ( int i = 0; i < m_Offsets.Length; i += 2 )
{
int x = m_Offsets[i], y = m_Offsets[i + 1];
Point3D p = new Point3D( px + x, py + y, 0 );
LandTarget lt = new LandTarget( p, map );
if ( (targ.Range == -1 || m_Mobile.InRange( p, targ.Range )) && m_Mobile.InLOS( lt ) && map.CanSpawnMobile( px + x, py + y, lt.Z ) && !SpellHelper.CheckMulti( p, map ) )
{
targ.Invoke( m_Mobile, lt );
return true;
}
}
int teleRange = targ.Range;
if ( teleRange < 0 )
teleRange = 12;
for ( int i = 0; i < 10; ++i )
{
Point3D randomPoint = new Point3D( m_Mobile.X - teleRange + Utility.Random( teleRange * 2 + 1 ), m_Mobile.Y - teleRange + Utility.Random( teleRange * 2 + 1 ), 0 );
LandTarget lt = new LandTarget( randomPoint, map );
if ( m_Mobile.InLOS( lt ) && map.CanSpawnMobile( lt.X, lt.Y, lt.Z ) && !SpellHelper.CheckMulti( randomPoint, map ) )
{
targ.Invoke( m_Mobile, new LandTarget( randomPoint, map ) );
return true;
}
}
targ.Cancel( m_Mobile, TargetCancelType.Canceled );
}
else
{
targ.Cancel( m_Mobile, TargetCancelType.Canceled );
}
return true;
}
}
}

View file

@ -0,0 +1,183 @@
using System;
using System.Collections;
using Server.Targeting;
using Server.Network;
//
// This is a first simple AI
//
//
namespace Server.Mobiles
{
public class MeleeAI : BaseAI
{
public MeleeAI(BaseCreature m) : base (m)
{
}
public override bool DoActionWander()
{
m_Mobile.DebugSay( "I have no combatant" );
if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I have detected {0}, attacking", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
Mobile combatant = m_Mobile.Combatant;
if ( combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map || !combatant.Alive || combatant.IsDeadBondedPet )
{
m_Mobile.DebugSay( "My combatant is gone, so my guard is up" );
Action = ActionType.Guard;
return true;
}
if ( !m_Mobile.InRange( combatant, m_Mobile.RangePerception ) )
{
// They are somewhat far away, can we find something else?
if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
m_Mobile.Combatant = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
else if ( !m_Mobile.InRange( combatant, m_Mobile.RangePerception * 3 ) )
{
m_Mobile.Combatant = null;
}
combatant = m_Mobile.Combatant;
if ( combatant == null )
{
m_Mobile.DebugSay( "My combatant has fled, so I am on guard" );
Action = ActionType.Guard;
return true;
}
}
/*if ( !m_Mobile.InLOS( combatant ) )
{
if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
m_Mobile.Combatant = combatant = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
}*/
if ( MoveTo( combatant, true, m_Mobile.RangeFight ) )
{
m_Mobile.Direction = m_Mobile.GetDirectionTo( combatant );
}
else if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
return true;
}
else if ( m_Mobile.GetDistanceToSqrt( combatant ) > m_Mobile.RangePerception + 1 )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I cannot find {0}, so my guard is up", combatant.Name );
Action = ActionType.Guard;
return true;
}
else
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I should be closer to {0}", combatant.Name );
}
if ( !m_Mobile.Controlled && !m_Mobile.Summoned && !m_Mobile.IsParagon )
{
if ( m_Mobile.Hits < m_Mobile.HitsMax * 20/100 )
{
// We are low on health, should we flee?
bool flee = false;
if ( m_Mobile.Hits < combatant.Hits )
{
// We are more hurt than them
int diff = combatant.Hits - m_Mobile.Hits;
flee = ( Utility.Random( 0, 100 ) < (10 + diff) ); // (10 + diff)% chance to flee
}
else
{
flee = Utility.Random( 0, 100 ) < 10; // 10% chance to flee
}
if ( flee )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I am going to flee from {0}", combatant.Name );
Action = ActionType.Flee;
}
}
}
return true;
}
public override bool DoActionGuard()
{
if ( AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I have detected {0}, attacking", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionGuard();
}
return true;
}
public override bool DoActionFlee()
{
if ( m_Mobile.Hits > m_Mobile.HitsMax/2 )
{
m_Mobile.DebugSay( "I am stronger now, so I will continue fighting" );
Action = ActionType.Combat;
}
else
{
m_Mobile.FocusMob = m_Mobile.Combatant;
base.DoActionFlee();
}
return true;
}
}
}

View file

@ -0,0 +1,100 @@
using System;
using System.Collections;
using Server.Targeting;
using Server.Network;
/*
* PredatorAI, its an animal that can attack
* Dont flee but dont attack if not hurt or attacked
*
*/
namespace Server.Mobiles
{
public class PredatorAI : BaseAI
{
public PredatorAI(BaseCreature m) : base (m)
{
}
public override bool DoActionWander()
{
if ( m_Mobile.Combatant != null )
{
m_Mobile.DebugSay( "I am hurt or being attacked, I kill him" );
Action = ActionType.Combat;
}
else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, true, false, true))
{
m_Mobile.DebugSay( "There is something near, I go away" );
Action = ActionType.Backoff;
}
else
{
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
Mobile combatant = m_Mobile.Combatant;
if ( combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map )
{
m_Mobile.DebugSay( "My combatant is gone, so my guard is up" );
Action = ActionType.Wander;
return true;
}
if ( WalkMobileRange( combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight ) )
{
m_Mobile.Direction = m_Mobile.GetDirectionTo( combatant );
}
else
{
if ( m_Mobile.GetDistanceToSqrt( combatant ) > m_Mobile.RangePerception + 1 )
{
m_Mobile.DebugSay( "I cannot find {0}", combatant.Name );
Action = ActionType.Wander;
return true;
}
else
{
m_Mobile.DebugSay( "I should be closer to {0}", combatant.Name );
}
}
return true;
}
public override bool DoActionBackoff()
{
if ( m_Mobile.IsHurt() || m_Mobile.Combatant != null )
{
Action = ActionType.Combat;
}
else
{
if (AcquireFocusMob(m_Mobile.RangePerception * 2, FightMode.Closest, true, false , true))
{
if ( WalkMobileRange(m_Mobile.FocusMob, 1, false, m_Mobile.RangePerception, m_Mobile.RangePerception * 2) )
{
m_Mobile.DebugSay( "Well, here I am safe" );
Action = ActionType.Wander;
}
}
else
{
m_Mobile.DebugSay( "I have lost my focus, lets relax" );
Action = ActionType.Wander;
}
}
return true;
}
}
}

View file

@ -0,0 +1,194 @@
using System;
using System.Collections;
using Server.Targeting;
using Server.Network;
using Server.Items;
//
// This is a first simple AI
//
//
namespace Server.Mobiles
{
public class ThiefAI : BaseAI
{
public ThiefAI(BaseCreature m) : base (m)
{
}
private Item m_toDisarm;
public override bool DoActionWander()
{
m_Mobile.DebugSay( "I have no combatant" );
if ( AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
m_Mobile.DebugSay( "I have detected {0}, attacking", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
Mobile combatant = m_Mobile.Combatant;
if ( combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map )
{
m_Mobile.DebugSay( "My combatant is gone, so my guard is up" );
Action = ActionType.Guard;
return true;
}
if ( WalkMobileRange( combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight ) )
{
m_Mobile.Direction = m_Mobile.GetDirectionTo( combatant );
if ( m_toDisarm == null )
m_toDisarm = combatant.FindItemOnLayer( Layer.OneHanded );
if ( m_toDisarm == null )
m_toDisarm = combatant.FindItemOnLayer( Layer.TwoHanded );
if ( m_toDisarm != null && m_toDisarm.IsChildOf( m_Mobile.Backpack ) )
{
m_toDisarm = combatant.FindItemOnLayer( Layer.OneHanded );
if ( m_toDisarm == null )
m_toDisarm = combatant.FindItemOnLayer( Layer.TwoHanded );
}
if ( !m_Mobile.DisarmReady && m_Mobile.Skills[SkillName.Wrestling].Value >= 80.0 && m_Mobile.Skills[SkillName.ArmsLore].Value >= 80.0 && m_toDisarm != null )
EventSink.InvokeDisarmRequest( new DisarmRequestEventArgs( m_Mobile ) );
if ( m_toDisarm != null && m_toDisarm.IsChildOf( combatant.Backpack ) && m_Mobile.NextSkillTime <= DateTime.Now && (m_toDisarm.LootType != LootType.Blessed && m_toDisarm.LootType != LootType.Newbied) )
{
m_Mobile.DebugSay( "Trying to steal from combatant." );
m_Mobile.UseSkill( SkillName.Stealing );
if ( m_Mobile.Target != null )
m_Mobile.Target.Invoke( m_Mobile, m_toDisarm );
}
else if ( m_toDisarm == null && m_Mobile.NextSkillTime <= DateTime.Now )
{
Container cpack = combatant.Backpack;
if ( cpack != null )
{
Item steala = cpack.FindItemByType( typeof ( Bandage ) );
if ( steala != null )
{
m_Mobile.DebugSay( "Trying to steal from combatant." );
m_Mobile.UseSkill( SkillName.Stealing );
if ( m_Mobile.Target != null )
m_Mobile.Target.Invoke( m_Mobile, steala );
}
Item stealb = cpack.FindItemByType( typeof ( Nightshade ) );
if ( stealb != null )
{
m_Mobile.DebugSay( "Trying to steal from combatant." );
m_Mobile.UseSkill( SkillName.Stealing );
if ( m_Mobile.Target != null )
m_Mobile.Target.Invoke( m_Mobile, stealb );
}
Item stealc = cpack.FindItemByType( typeof ( BlackPearl ) );
if ( stealc != null )
{
m_Mobile.DebugSay( "Trying to steal from combatant." );
m_Mobile.UseSkill( SkillName.Stealing );
if ( m_Mobile.Target != null )
m_Mobile.Target.Invoke( m_Mobile, stealc );
}
Item steald = cpack.FindItemByType( typeof ( MandrakeRoot ) );
if ( steald != null )
{
m_Mobile.DebugSay( "Trying to steal from combatant." );
m_Mobile.UseSkill( SkillName.Stealing );
if ( m_Mobile.Target != null )
m_Mobile.Target.Invoke( m_Mobile, steald );
}
else if ( steala == null && stealb == null && stealc == null && steald == null )
{
m_Mobile.DebugSay( "I am going to flee from {0}", combatant.Name );
Action = ActionType.Flee;
}
}
}
}
else
{
m_Mobile.DebugSay( "I should be closer to {0}", combatant.Name );
}
if ( m_Mobile.Hits < m_Mobile.HitsMax * 20/100 && !m_Mobile.IsParagon )
{
// We are low on health, should we flee?
bool flee = false;
if ( m_Mobile.Hits < combatant.Hits )
{
// We are more hurt than them
int diff = combatant.Hits - m_Mobile.Hits;
flee = ( Utility.Random( 0, 100 ) > (10 + diff) ); // (10 + diff)% chance to flee
}
else
{
flee = Utility.Random( 0, 100 ) > 10; // 10% chance to flee
}
if ( flee )
{
m_Mobile.DebugSay( "I am going to flee from {0}", combatant.Name );
Action = ActionType.Flee;
}
}
return true;
}
public override bool DoActionGuard()
{
if ( AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
{
m_Mobile.DebugSay( "I have detected {0}, attacking", m_Mobile.FocusMob.Name );
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionGuard();
}
return true;
}
public override bool DoActionFlee()
{
if ( m_Mobile.Hits > m_Mobile.HitsMax/2 )
{
m_Mobile.DebugSay( "I am stronger now, so I will continue fighting" );
Action = ActionType.Combat;
}
else
{
m_Mobile.FocusMob = m_Mobile.Combatant;
base.DoActionFlee();
}
return true;
}
}
}

View file

@ -0,0 +1,149 @@
using System;
using System.Collections;
using Server.Targeting;
using Server.Network;
//
// This is a first simple AI
//
//
namespace Server.Mobiles
{
public class VendorAI : BaseAI
{
public VendorAI(BaseCreature m) : base (m)
{
}
public override bool DoActionWander()
{
m_Mobile.DebugSay( "I'm fine" );
if ( m_Mobile.Combatant != null )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "{0} is attacking me", m_Mobile.Combatant.Name );
m_Mobile.Say( Utility.RandomList( 1005305, 501603 ) );
Action = ActionType.Flee;
}
else
{
if ( m_Mobile.FocusMob != null )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "{0} has talked to me", m_Mobile.FocusMob.Name );
Action = ActionType.Interact;
}
else
{
m_Mobile.Warmode = false;
base.DoActionWander();
}
}
return true;
}
public override bool DoActionInteract()
{
Mobile customer = m_Mobile.FocusMob;
if ( m_Mobile.Combatant != null )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "{0} is attacking me", m_Mobile.Combatant.Name );
m_Mobile.Say( Utility.RandomList( 1005305, 501603 ) );
Action = ActionType.Flee;
return true;
}
if ( customer == null || customer.Deleted || customer.Map != m_Mobile.Map )
{
m_Mobile.DebugSay( "My customer have disapeared" );
m_Mobile.FocusMob = null;
Action = ActionType.Wander;
}
else
{
if ( customer.InRange( m_Mobile, m_Mobile.RangeFight ) )
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "I am with {0}", customer.Name );
m_Mobile.Direction = m_Mobile.GetDirectionTo( customer );
}
else
{
if ( m_Mobile.Debug )
m_Mobile.DebugSay( "{0} is gone", customer.Name );
m_Mobile.FocusMob = null;
Action = ActionType.Wander;
}
}
return true;
}
public override bool DoActionGuard()
{
m_Mobile.FocusMob = m_Mobile.Combatant;
return base.DoActionGuard();
}
public override bool HandlesOnSpeech( Mobile from )
{
if ( from.InRange( m_Mobile, 4 ) )
return true;
return base.HandlesOnSpeech( from );
}
// Temporary
public override void OnSpeech( SpeechEventArgs e )
{
base.OnSpeech( e );
Mobile from = e.Mobile;
if ( m_Mobile is BaseVendor && from.InRange( m_Mobile, Core.AOS ? 1 : 4 ) && !e.Handled )
{
if ( e.HasKeyword( 0x14D ) ) // *vendor sell*
{
e.Handled = true;
((BaseVendor)m_Mobile).VendorSell( from );
m_Mobile.FocusMob = from;
}
else if ( e.HasKeyword( 0x3C ) )
{
e.Handled = true;
((BaseVendor)m_Mobile).VendorBuy( from );
m_Mobile.FocusMob = from;
}
else if ( WasNamed( e.Speech ) )
{
e.Handled = true;
if ( e.HasKeyword( 0x177 ) ) // *sell*
((BaseVendor)m_Mobile).VendorSell( from );
else if ( e.HasKeyword( 0x171 ) ) // *buy*
((BaseVendor)m_Mobile).VendorBuy( from );
m_Mobile.FocusMob = from;
}
}
}
}
}