This commit is contained in:
commit
47711d616e
2644 changed files with 479454 additions and 0 deletions
157
Scripts/Engines/AI/AI/AnimalAI.cs
Normal file
157
Scripts/Engines/AI/AI/AnimalAI.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
131
Scripts/Engines/AI/AI/ArcherAI.cs
Normal file
131
Scripts/Engines/AI/AI/ArcherAI.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
2748
Scripts/Engines/AI/AI/BaseAI.cs
Normal file
2748
Scripts/Engines/AI/AI/BaseAI.cs
Normal file
File diff suppressed because it is too large
Load diff
87
Scripts/Engines/AI/AI/BerserkAI.cs
Normal file
87
Scripts/Engines/AI/AI/BerserkAI.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
176
Scripts/Engines/AI/AI/HealerAI.cs
Normal file
176
Scripts/Engines/AI/AI/HealerAI.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
992
Scripts/Engines/AI/AI/MageAI.cs
Normal file
992
Scripts/Engines/AI/AI/MageAI.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
183
Scripts/Engines/AI/AI/MeleeAI.cs
Normal file
183
Scripts/Engines/AI/AI/MeleeAI.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
100
Scripts/Engines/AI/AI/PredatorAI.cs
Normal file
100
Scripts/Engines/AI/AI/PredatorAI.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
194
Scripts/Engines/AI/AI/ThiefAI.cs
Normal file
194
Scripts/Engines/AI/AI/ThiefAI.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
149
Scripts/Engines/AI/AI/VendorAI.cs
Normal file
149
Scripts/Engines/AI/AI/VendorAI.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
4792
Scripts/Engines/AI/Creature/BaseCreature.cs
Normal file
4792
Scripts/Engines/AI/Creature/BaseCreature.cs
Normal file
File diff suppressed because it is too large
Load diff
152
Scripts/Engines/AI/Creature/Dummy.cs
Normal file
152
Scripts/Engines/AI/Creature/Dummy.cs
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Spells;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a test creature
|
||||
/// You can set its value in game
|
||||
/// It die after 5 minutes, so your test server stay clean
|
||||
/// Create a macro to help your creation "[add Dummy 1 15 7 -1 0.5 2"
|
||||
///
|
||||
/// A iTeam of negative will set a faction at random
|
||||
///
|
||||
/// Say Kill if you want them to die
|
||||
///
|
||||
/// </summary>
|
||||
public class Dummy : BaseCreature
|
||||
{
|
||||
public Timer m_Timer;
|
||||
|
||||
[Constructable]
|
||||
public Dummy(AIType iAI, FightMode iFightMode, int iRangePerception, int iRangeFight, double dActiveSpeed, double dPassiveSpeed) : base(iAI, iFightMode, iRangePerception, iRangeFight, dActiveSpeed, dPassiveSpeed)
|
||||
{
|
||||
this.Body = 400 + Utility.Random(2);
|
||||
this.Hue = Utility.RandomSkinHue();
|
||||
|
||||
this.Skills[SkillName.DetectHidden].Base = 100;
|
||||
this.Skills[SkillName.MagicResist].Base = 120;
|
||||
|
||||
Team = Utility.Random(3);
|
||||
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
Utility.AssignRandomHair( this, iHue );
|
||||
|
||||
LeatherGloves glv = new LeatherGloves();
|
||||
glv.Hue = iHue;
|
||||
glv.LootType = LootType.Newbied;
|
||||
AddItem(glv);
|
||||
|
||||
Container pack = new Backpack();
|
||||
|
||||
pack.Movable = false;
|
||||
|
||||
AddItem( pack );
|
||||
|
||||
m_Timer = new AutokillTimer(this);
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
public Dummy( Serial serial ) : base( serial )
|
||||
{
|
||||
m_Timer = new AutokillTimer(this);
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public override bool HandlesOnSpeech( Mobile from )
|
||||
{
|
||||
if ( from.AccessLevel >= AccessLevel.GameMaster )
|
||||
return true;
|
||||
|
||||
return base.HandlesOnSpeech( from );
|
||||
}
|
||||
|
||||
public override void OnSpeech( SpeechEventArgs e )
|
||||
{
|
||||
base.OnSpeech( e );
|
||||
|
||||
if (e.Mobile.AccessLevel >= AccessLevel.GameMaster)
|
||||
{
|
||||
if (e.Speech == "kill")
|
||||
{
|
||||
m_Timer.Stop();
|
||||
m_Timer.Delay = TimeSpan.FromSeconds( Utility.Random(1, 5) );
|
||||
m_Timer.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnTeamChange()
|
||||
{
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
Item item = FindItemOnLayer( Layer.OuterTorso );
|
||||
|
||||
if ( item != null )
|
||||
item.Hue = jHue;
|
||||
|
||||
item = FindItemOnLayer( Layer.Helm );
|
||||
|
||||
if ( item != null )
|
||||
item.Hue = iHue;
|
||||
|
||||
item = FindItemOnLayer( Layer.Gloves );
|
||||
|
||||
if ( item != null )
|
||||
item.Hue = iHue;
|
||||
|
||||
item = FindItemOnLayer( Layer.Shoes );
|
||||
|
||||
if ( item != null )
|
||||
item.Hue = iHue;
|
||||
|
||||
HairHue = iHue;
|
||||
|
||||
item = FindItemOnLayer( Layer.MiddleTorso );
|
||||
|
||||
if ( item != null )
|
||||
item.Hue = iHue;
|
||||
|
||||
item = FindItemOnLayer( Layer.OuterLegs );
|
||||
|
||||
if ( item != null )
|
||||
item.Hue = iHue;
|
||||
}
|
||||
|
||||
private class AutokillTimer : Timer
|
||||
{
|
||||
private Dummy m_Owner;
|
||||
|
||||
public AutokillTimer( Dummy owner ) : base( TimeSpan.FromMinutes(5.0) )
|
||||
{
|
||||
m_Owner = owner;
|
||||
Priority = TimerPriority.FiveSeconds;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Owner.Kill();
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
814
Scripts/Engines/AI/Creature/DummySpecific.cs
Normal file
814
Scripts/Engines/AI/Creature/DummySpecific.cs
Normal file
|
|
@ -0,0 +1,814 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Spells;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a test creature
|
||||
/// You can set its value in game
|
||||
/// It die after 5 minutes, so your test server stay clean
|
||||
/// Create a macro to help your creation "[add Dummy 1 15 7 -1 0.5 2"
|
||||
///
|
||||
/// A iTeam of negative will set a faction at random
|
||||
///
|
||||
/// Say Kill if you want them to die
|
||||
///
|
||||
/// </summary>
|
||||
|
||||
public class DummyMace : Dummy
|
||||
{
|
||||
|
||||
[Constructable]
|
||||
public DummyMace() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Macer
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
this.InitStats( 125, 125, 90 );
|
||||
this.Skills[SkillName.Macing].Base = 120;
|
||||
this.Skills[SkillName.Anatomy].Base = 120;
|
||||
this.Skills[SkillName.Healing].Base = 120;
|
||||
this.Skills[SkillName.Tactics].Base = 120;
|
||||
|
||||
|
||||
// Name
|
||||
this.Name = "Macer";
|
||||
|
||||
// Equip
|
||||
WarHammer war = new WarHammer();
|
||||
war.Movable = true;
|
||||
war.Crafter = this;
|
||||
war.Quality = WeaponQuality.Regular;
|
||||
AddItem( war );
|
||||
|
||||
Boots bts = new Boots();
|
||||
bts.Hue = iHue;
|
||||
AddItem( bts );
|
||||
|
||||
ChainChest cht = new ChainChest();
|
||||
cht.Movable = false;
|
||||
cht.LootType = LootType.Newbied;
|
||||
cht.Crafter = this;
|
||||
cht.Quality = ArmorQuality.Regular;
|
||||
AddItem( cht );
|
||||
|
||||
ChainLegs chl = new ChainLegs();
|
||||
chl.Movable = false;
|
||||
chl.LootType = LootType.Newbied;
|
||||
chl.Crafter = this;
|
||||
chl.Quality = ArmorQuality.Regular;
|
||||
AddItem( chl );
|
||||
|
||||
PlateArms pla = new PlateArms();
|
||||
pla.Movable = false;
|
||||
pla.LootType = LootType.Newbied;
|
||||
pla.Crafter = this;
|
||||
pla.Quality = ArmorQuality.Regular;
|
||||
AddItem( pla );
|
||||
|
||||
Bandage band = new Bandage( 50 );
|
||||
AddToBackpack( band );
|
||||
}
|
||||
|
||||
public DummyMace( 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();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyFence : Dummy
|
||||
{
|
||||
|
||||
[Constructable]
|
||||
public DummyFence() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Fencer
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
this.InitStats( 125, 125, 90 );
|
||||
this.Skills[SkillName.Fencing].Base = 120;
|
||||
this.Skills[SkillName.Anatomy].Base = 120;
|
||||
this.Skills[SkillName.Healing].Base = 120;
|
||||
this.Skills[SkillName.Tactics].Base = 120;
|
||||
|
||||
// Name
|
||||
this.Name = "Fencer";
|
||||
|
||||
// Equip
|
||||
Spear ssp = new Spear();
|
||||
ssp.Movable = true;
|
||||
ssp.Crafter = this;
|
||||
ssp.Quality = WeaponQuality.Regular;
|
||||
AddItem( ssp );
|
||||
|
||||
Boots snd = new Boots();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem( snd );
|
||||
|
||||
ChainChest cht = new ChainChest();
|
||||
cht.Movable = false;
|
||||
cht.LootType = LootType.Newbied;
|
||||
cht.Crafter = this;
|
||||
cht.Quality = ArmorQuality.Regular;
|
||||
AddItem( cht );
|
||||
|
||||
ChainLegs chl = new ChainLegs();
|
||||
chl.Movable = false;
|
||||
chl.LootType = LootType.Newbied;
|
||||
chl.Crafter = this;
|
||||
chl.Quality = ArmorQuality.Regular;
|
||||
AddItem( chl );
|
||||
|
||||
PlateArms pla = new PlateArms();
|
||||
pla.Movable = false;
|
||||
pla.LootType = LootType.Newbied;
|
||||
pla.Crafter = this;
|
||||
pla.Quality = ArmorQuality.Regular;
|
||||
AddItem( pla );
|
||||
|
||||
Bandage band = new Bandage( 50 );
|
||||
AddToBackpack( band );
|
||||
}
|
||||
|
||||
public DummyFence( 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();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummySword : Dummy
|
||||
{
|
||||
|
||||
[Constructable]
|
||||
public DummySword() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Swordsman
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
this.InitStats( 125, 125, 90 );
|
||||
this.Skills[SkillName.Swords].Base = 120;
|
||||
this.Skills[SkillName.Anatomy].Base = 120;
|
||||
this.Skills[SkillName.Healing].Base = 120;
|
||||
this.Skills[SkillName.Tactics].Base = 120;
|
||||
this.Skills[SkillName.Parry].Base = 120;
|
||||
|
||||
|
||||
// Name
|
||||
this.Name = "Swordsman";
|
||||
|
||||
// Equip
|
||||
Katana kat = new Katana();
|
||||
kat.Crafter = this;
|
||||
kat.Movable = true;
|
||||
kat.Quality = WeaponQuality.Regular;
|
||||
AddItem( kat );
|
||||
|
||||
Boots bts = new Boots();
|
||||
bts.Hue = iHue;
|
||||
AddItem( bts );
|
||||
|
||||
ChainChest cht = new ChainChest();
|
||||
cht.Movable = false;
|
||||
cht.LootType = LootType.Newbied;
|
||||
cht.Crafter = this;
|
||||
cht.Quality = ArmorQuality.Regular;
|
||||
AddItem( cht );
|
||||
|
||||
ChainLegs chl = new ChainLegs();
|
||||
chl.Movable = false;
|
||||
chl.LootType = LootType.Newbied;
|
||||
chl.Crafter = this;
|
||||
chl.Quality = ArmorQuality.Regular;
|
||||
AddItem( chl );
|
||||
|
||||
PlateArms pla = new PlateArms();
|
||||
pla.Movable = false;
|
||||
pla.LootType = LootType.Newbied;
|
||||
pla.Crafter = this;
|
||||
pla.Quality = ArmorQuality.Regular;
|
||||
AddItem( pla );
|
||||
|
||||
Bandage band = new Bandage( 50 );
|
||||
AddToBackpack( band );
|
||||
}
|
||||
|
||||
public DummySword( 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();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyNox : Dummy
|
||||
{
|
||||
|
||||
[Constructable]
|
||||
public DummyNox() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
|
||||
// A Dummy Nox or Pure Mage
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
this.InitStats( 90, 90, 125 );
|
||||
this.Skills[SkillName.Magery].Base = 120;
|
||||
this.Skills[SkillName.EvalInt].Base = 120;
|
||||
this.Skills[SkillName.Inscribe].Base = 100;
|
||||
this.Skills[SkillName.Wrestling].Base = 120;
|
||||
this.Skills[SkillName.Meditation].Base = 120;
|
||||
this.Skills[SkillName.Poisoning].Base = 100;
|
||||
|
||||
|
||||
// Name
|
||||
this.Name = "Nox Mage";
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content =0xFFFFFFFFFFFFFFFF;
|
||||
AddItem( book );
|
||||
|
||||
Kilt kilt = new Kilt();
|
||||
kilt.Hue = jHue;
|
||||
AddItem( kilt );
|
||||
|
||||
Sandals snd = new Sandals();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem( snd );
|
||||
|
||||
SkullCap skc = new SkullCap();
|
||||
skc.Hue = iHue;
|
||||
AddItem( skc );
|
||||
|
||||
// Spells
|
||||
AddSpellAttack( typeof(Spells.First.MagicArrowSpell) );
|
||||
AddSpellAttack( typeof(Spells.First.WeakenSpell) );
|
||||
AddSpellAttack( typeof(Spells.Third.FireballSpell) );
|
||||
AddSpellDefense( typeof(Spells.Third.WallOfStoneSpell) );
|
||||
AddSpellDefense( typeof(Spells.First.HealSpell) );
|
||||
}
|
||||
|
||||
public DummyNox( 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();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyStun : Dummy
|
||||
{
|
||||
|
||||
[Constructable]
|
||||
public DummyStun() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
|
||||
// A Dummy Stun Mage
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
this.InitStats( 90, 90, 125 );
|
||||
this.Skills[SkillName.Magery].Base = 100;
|
||||
this.Skills[SkillName.EvalInt].Base = 120;
|
||||
this.Skills[SkillName.Anatomy].Base = 80;
|
||||
this.Skills[SkillName.Wrestling].Base = 80;
|
||||
this.Skills[SkillName.Meditation].Base = 100;
|
||||
this.Skills[SkillName.Poisoning].Base = 100;
|
||||
|
||||
|
||||
// Name
|
||||
this.Name = "Stun Mage";
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content =0xFFFFFFFFFFFFFFFF;
|
||||
AddItem( book );
|
||||
|
||||
LeatherArms lea = new LeatherArms();
|
||||
lea.Movable = false;
|
||||
lea.LootType = LootType.Newbied;
|
||||
lea.Crafter = this;
|
||||
lea.Quality = ArmorQuality.Regular;
|
||||
AddItem( lea );
|
||||
|
||||
LeatherChest lec = new LeatherChest();
|
||||
lec.Movable = false;
|
||||
lec.LootType = LootType.Newbied;
|
||||
lec.Crafter = this;
|
||||
lec.Quality = ArmorQuality.Regular;
|
||||
AddItem( lec );
|
||||
|
||||
LeatherGorget leg = new LeatherGorget();
|
||||
leg.Movable = false;
|
||||
leg.LootType = LootType.Newbied;
|
||||
leg.Crafter = this;
|
||||
leg.Quality = ArmorQuality.Regular;
|
||||
AddItem( leg );
|
||||
|
||||
LeatherLegs lel = new LeatherLegs();
|
||||
lel.Movable = false;
|
||||
lel.LootType = LootType.Newbied;
|
||||
lel.Crafter = this;
|
||||
lel.Quality = ArmorQuality.Regular;
|
||||
AddItem( lel );
|
||||
|
||||
Boots bts = new Boots();
|
||||
bts.Hue = iHue;
|
||||
AddItem( bts );
|
||||
|
||||
Cap cap = new Cap();
|
||||
cap.Hue = iHue;
|
||||
AddItem( cap );
|
||||
|
||||
// Spells
|
||||
AddSpellAttack( typeof(Spells.First.MagicArrowSpell) );
|
||||
AddSpellAttack( typeof(Spells.First.WeakenSpell) );
|
||||
AddSpellAttack( typeof(Spells.Third.FireballSpell) );
|
||||
AddSpellDefense( typeof(Spells.Third.WallOfStoneSpell) );
|
||||
AddSpellDefense( typeof(Spells.First.HealSpell) );
|
||||
}
|
||||
|
||||
public DummyStun( 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();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummySuper : Dummy
|
||||
{
|
||||
|
||||
[Constructable]
|
||||
public DummySuper() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Super Mage
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
this.InitStats( 125, 125, 125 );
|
||||
this.Skills[SkillName.Magery].Base = 120;
|
||||
this.Skills[SkillName.EvalInt].Base = 120;
|
||||
this.Skills[SkillName.Anatomy].Base = 120;
|
||||
this.Skills[SkillName.Wrestling].Base = 120;
|
||||
this.Skills[SkillName.Meditation].Base = 120;
|
||||
this.Skills[SkillName.Poisoning].Base = 100;
|
||||
this.Skills[SkillName.Inscribe].Base = 100;
|
||||
|
||||
// Name
|
||||
this.Name = "Super Mage";
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content =0xFFFFFFFFFFFFFFFF;
|
||||
AddItem( book );
|
||||
|
||||
LeatherArms lea = new LeatherArms();
|
||||
lea.Movable = false;
|
||||
lea.LootType = LootType.Newbied;
|
||||
lea.Crafter = this;
|
||||
lea.Quality = ArmorQuality.Regular;
|
||||
AddItem( lea );
|
||||
|
||||
LeatherChest lec = new LeatherChest();
|
||||
lec.Movable = false;
|
||||
lec.LootType = LootType.Newbied;
|
||||
lec.Crafter = this;
|
||||
lec.Quality = ArmorQuality.Regular;
|
||||
AddItem( lec );
|
||||
|
||||
LeatherGorget leg = new LeatherGorget();
|
||||
leg.Movable = false;
|
||||
leg.LootType = LootType.Newbied;
|
||||
leg.Crafter = this;
|
||||
leg.Quality = ArmorQuality.Regular;
|
||||
AddItem( leg );
|
||||
|
||||
LeatherLegs lel = new LeatherLegs();
|
||||
lel.Movable = false;
|
||||
lel.LootType = LootType.Newbied;
|
||||
lel.Crafter = this;
|
||||
lel.Quality = ArmorQuality.Regular;
|
||||
AddItem( lel );
|
||||
|
||||
Sandals snd = new Sandals();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem( snd );
|
||||
|
||||
JesterHat jhat = new JesterHat();
|
||||
jhat.Hue = iHue;
|
||||
AddItem( jhat );
|
||||
|
||||
Doublet dblt = new Doublet();
|
||||
dblt.Hue = iHue;
|
||||
AddItem( dblt );
|
||||
|
||||
// Spells
|
||||
AddSpellAttack( typeof(Spells.First.MagicArrowSpell) );
|
||||
AddSpellAttack( typeof(Spells.First.WeakenSpell) );
|
||||
AddSpellAttack( typeof(Spells.Third.FireballSpell) );
|
||||
AddSpellDefense( typeof(Spells.Third.WallOfStoneSpell) );
|
||||
AddSpellDefense( typeof(Spells.First.HealSpell) );
|
||||
}
|
||||
|
||||
public DummySuper( 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();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyHealer : Dummy
|
||||
{
|
||||
|
||||
[Constructable]
|
||||
public DummyHealer() : base(AIType.AI_Healer, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Healer Mage
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
this.InitStats( 125, 125, 125 );
|
||||
this.Skills[SkillName.Magery].Base = 120;
|
||||
this.Skills[SkillName.EvalInt].Base = 120;
|
||||
this.Skills[SkillName.Anatomy].Base = 120;
|
||||
this.Skills[SkillName.Wrestling].Base = 120;
|
||||
this.Skills[SkillName.Meditation].Base = 120;
|
||||
this.Skills[SkillName.Healing].Base = 100;
|
||||
|
||||
// Name
|
||||
this.Name = "Healer";
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content =0xFFFFFFFFFFFFFFFF;
|
||||
AddItem( book );
|
||||
|
||||
LeatherArms lea = new LeatherArms();
|
||||
lea.Movable = false;
|
||||
lea.LootType = LootType.Newbied;
|
||||
lea.Crafter = this;
|
||||
lea.Quality = ArmorQuality.Regular;
|
||||
AddItem( lea );
|
||||
|
||||
LeatherChest lec = new LeatherChest();
|
||||
lec.Movable = false;
|
||||
lec.LootType = LootType.Newbied;
|
||||
lec.Crafter = this;
|
||||
lec.Quality = ArmorQuality.Regular;
|
||||
AddItem( lec );
|
||||
|
||||
LeatherGorget leg = new LeatherGorget();
|
||||
leg.Movable = false;
|
||||
leg.LootType = LootType.Newbied;
|
||||
leg.Crafter = this;
|
||||
leg.Quality = ArmorQuality.Regular;
|
||||
AddItem( leg );
|
||||
|
||||
LeatherLegs lel = new LeatherLegs();
|
||||
lel.Movable = false;
|
||||
lel.LootType = LootType.Newbied;
|
||||
lel.Crafter = this;
|
||||
lel.Quality = ArmorQuality.Regular;
|
||||
AddItem( lel );
|
||||
|
||||
Sandals snd = new Sandals();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem( snd );
|
||||
|
||||
Cap cap = new Cap();
|
||||
cap.Hue = iHue;
|
||||
AddItem( cap );
|
||||
|
||||
Robe robe = new Robe();
|
||||
robe.Hue = iHue;
|
||||
AddItem( robe );
|
||||
|
||||
}
|
||||
|
||||
public DummyHealer( 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();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyAssassin : Dummy
|
||||
{
|
||||
|
||||
[Constructable]
|
||||
public DummyAssassin() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Hybrid Assassin
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
this.InitStats( 105, 105, 105 );
|
||||
this.Skills[SkillName.Magery].Base = 120;
|
||||
this.Skills[SkillName.EvalInt].Base = 120;
|
||||
this.Skills[SkillName.Swords].Base = 120;
|
||||
this.Skills[SkillName.Tactics].Base = 120;
|
||||
this.Skills[SkillName.Meditation].Base = 120;
|
||||
this.Skills[SkillName.Poisoning].Base = 100;
|
||||
|
||||
// Name
|
||||
this.Name = "Hybrid Assassin";
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content =0xFFFFFFFFFFFFFFFF;
|
||||
AddToBackpack( book );
|
||||
|
||||
Katana kat = new Katana();
|
||||
kat.Movable = false;
|
||||
kat.LootType = LootType.Newbied;
|
||||
kat.Crafter = this;
|
||||
kat.Poison = Poison.Deadly;
|
||||
kat.PoisonCharges = 12;
|
||||
kat.Quality = WeaponQuality.Regular;
|
||||
AddToBackpack( kat );
|
||||
|
||||
LeatherArms lea = new LeatherArms();
|
||||
lea.Movable = false;
|
||||
lea.LootType = LootType.Newbied;
|
||||
lea.Crafter = this;
|
||||
lea.Quality = ArmorQuality.Regular;
|
||||
AddItem( lea );
|
||||
|
||||
LeatherChest lec = new LeatherChest();
|
||||
lec.Movable = false;
|
||||
lec.LootType = LootType.Newbied;
|
||||
lec.Crafter = this;
|
||||
lec.Quality = ArmorQuality.Regular;
|
||||
AddItem( lec );
|
||||
|
||||
LeatherGorget leg = new LeatherGorget();
|
||||
leg.Movable = false;
|
||||
leg.LootType = LootType.Newbied;
|
||||
leg.Crafter = this;
|
||||
leg.Quality = ArmorQuality.Regular;
|
||||
AddItem( leg );
|
||||
|
||||
LeatherLegs lel = new LeatherLegs();
|
||||
lel.Movable = false;
|
||||
lel.LootType = LootType.Newbied;
|
||||
lel.Crafter = this;
|
||||
lel.Quality = ArmorQuality.Regular;
|
||||
AddItem( lel );
|
||||
|
||||
Sandals snd = new Sandals();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem( snd );
|
||||
|
||||
Cap cap = new Cap();
|
||||
cap.Hue = iHue;
|
||||
AddItem( cap );
|
||||
|
||||
Robe robe = new Robe();
|
||||
robe.Hue = iHue;
|
||||
AddItem( robe );
|
||||
|
||||
DeadlyPoisonPotion pota = new DeadlyPoisonPotion();
|
||||
pota.LootType = LootType.Newbied;
|
||||
AddToBackpack( pota );
|
||||
|
||||
DeadlyPoisonPotion potb = new DeadlyPoisonPotion();
|
||||
potb.LootType = LootType.Newbied;
|
||||
AddToBackpack( potb );
|
||||
|
||||
DeadlyPoisonPotion potc = new DeadlyPoisonPotion();
|
||||
potc.LootType = LootType.Newbied;
|
||||
AddToBackpack( potc );
|
||||
|
||||
DeadlyPoisonPotion potd = new DeadlyPoisonPotion();
|
||||
potd.LootType = LootType.Newbied;
|
||||
AddToBackpack( potd );
|
||||
|
||||
Bandage band = new Bandage( 50 );
|
||||
AddToBackpack( band );
|
||||
|
||||
}
|
||||
|
||||
public DummyAssassin( 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();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyTheif : Dummy
|
||||
{
|
||||
|
||||
[Constructable]
|
||||
public DummyTheif() : base(AIType.AI_Thief, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Hybrid Theif
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
this.InitStats( 105, 105, 105 );
|
||||
this.Skills[SkillName.Healing].Base = 120;
|
||||
this.Skills[SkillName.Anatomy].Base = 120;
|
||||
this.Skills[SkillName.Stealing].Base = 120;
|
||||
this.Skills[SkillName.ArmsLore].Base = 100;
|
||||
this.Skills[SkillName.Meditation].Base = 120;
|
||||
this.Skills[SkillName.Wrestling].Base = 120;
|
||||
|
||||
// Name
|
||||
this.Name = "Hybrid Theif";
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content =0xFFFFFFFFFFFFFFFF;
|
||||
AddItem( book );
|
||||
|
||||
LeatherArms lea = new LeatherArms();
|
||||
lea.Movable = false;
|
||||
lea.LootType = LootType.Newbied;
|
||||
lea.Crafter = this;
|
||||
lea.Quality = ArmorQuality.Regular;
|
||||
AddItem( lea );
|
||||
|
||||
LeatherChest lec = new LeatherChest();
|
||||
lec.Movable = false;
|
||||
lec.LootType = LootType.Newbied;
|
||||
lec.Crafter = this;
|
||||
lec.Quality = ArmorQuality.Regular;
|
||||
AddItem( lec );
|
||||
|
||||
LeatherGorget leg = new LeatherGorget();
|
||||
leg.Movable = false;
|
||||
leg.LootType = LootType.Newbied;
|
||||
leg.Crafter = this;
|
||||
leg.Quality = ArmorQuality.Regular;
|
||||
AddItem( leg );
|
||||
|
||||
LeatherLegs lel = new LeatherLegs();
|
||||
lel.Movable = false;
|
||||
lel.LootType = LootType.Newbied;
|
||||
lel.Crafter = this;
|
||||
lel.Quality = ArmorQuality.Regular;
|
||||
AddItem( lel );
|
||||
|
||||
Sandals snd = new Sandals();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem( snd );
|
||||
|
||||
Cap cap = new Cap();
|
||||
cap.Hue = iHue;
|
||||
AddItem( cap );
|
||||
|
||||
Robe robe = new Robe();
|
||||
robe.Hue = iHue;
|
||||
AddItem( robe );
|
||||
|
||||
Bandage band = new Bandage( 50 );
|
||||
AddToBackpack( band );
|
||||
}
|
||||
|
||||
public DummyTheif( 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
140
Scripts/Engines/AI/Creature/OppositionGroup.cs
Normal file
140
Scripts/Engines/AI/Creature/OppositionGroup.cs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class OppositionGroup
|
||||
{
|
||||
private Type[][] m_Types;
|
||||
|
||||
public OppositionGroup( Type[][] types )
|
||||
{
|
||||
m_Types = types;
|
||||
}
|
||||
|
||||
public bool IsEnemy( object from, object target )
|
||||
{
|
||||
int fromGroup = IndexOf( from );
|
||||
int targGroup = IndexOf( target );
|
||||
|
||||
return ( fromGroup != -1 && targGroup != -1 && fromGroup != targGroup );
|
||||
}
|
||||
|
||||
public int IndexOf( object obj )
|
||||
{
|
||||
if ( obj == null )
|
||||
return -1;
|
||||
|
||||
Type type = obj.GetType();
|
||||
|
||||
for ( int i = 0; i < m_Types.Length; ++i )
|
||||
{
|
||||
Type[] group = m_Types[i];
|
||||
|
||||
bool contains = false;
|
||||
|
||||
for ( int j = 0; !contains && j < group.Length; ++j )
|
||||
contains = ( type == group[j] );
|
||||
|
||||
if ( contains )
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static OppositionGroup m_TerathansAndOphidians = new OppositionGroup( new Type[][]
|
||||
{
|
||||
new Type[]
|
||||
{
|
||||
typeof( TerathanAvenger ),
|
||||
typeof( TerathanDrone ),
|
||||
typeof( TerathanMatriarch ),
|
||||
typeof( TerathanWarrior )
|
||||
},
|
||||
new Type[]
|
||||
{
|
||||
typeof( OphidianArchmage ),
|
||||
typeof( OphidianKnight ),
|
||||
typeof( OphidianMage ),
|
||||
typeof( OphidianMatriarch ),
|
||||
typeof( OphidianWarrior )
|
||||
}
|
||||
} );
|
||||
|
||||
public static OppositionGroup TerathansAndOphidians
|
||||
{
|
||||
get{ return m_TerathansAndOphidians; }
|
||||
}
|
||||
|
||||
private static OppositionGroup m_SavagesAndOrcs = new OppositionGroup( new Type[][]
|
||||
{
|
||||
new Type[]
|
||||
{
|
||||
typeof( Orc ),
|
||||
typeof( OrcBomber ),
|
||||
typeof( OrcBrute ),
|
||||
typeof( OrcCaptain ),
|
||||
typeof( OrcishLord ),
|
||||
typeof( OrcishMage ),
|
||||
typeof( SpawnedOrcishLord )
|
||||
},
|
||||
new Type[]
|
||||
{
|
||||
typeof( Savage ),
|
||||
typeof( SavageRider ),
|
||||
typeof( SavageRidgeback ),
|
||||
typeof( SavageShaman )
|
||||
}
|
||||
} );
|
||||
|
||||
public static OppositionGroup SavagesAndOrcs
|
||||
{
|
||||
get{ return m_SavagesAndOrcs; }
|
||||
}
|
||||
|
||||
private static OppositionGroup m_FeyAndUndead = new OppositionGroup( new Type[][]
|
||||
{
|
||||
new Type[]
|
||||
{
|
||||
typeof( Centaur ),
|
||||
typeof( EtherealWarrior ),
|
||||
typeof( Kirin ),
|
||||
typeof( LordOaks ),
|
||||
typeof( Pixie ),
|
||||
typeof( Silvani ),
|
||||
typeof( Unicorn ),
|
||||
typeof( Wisp ),
|
||||
typeof( Treefellow )
|
||||
},
|
||||
new Type[]
|
||||
{
|
||||
typeof( AncientLich ),
|
||||
typeof( Bogle ),
|
||||
typeof( LichLord ),
|
||||
typeof( Shade ),
|
||||
typeof( Spectre ),
|
||||
typeof( Wraith ),
|
||||
typeof( BoneKnight ),
|
||||
typeof( Ghoul ),
|
||||
typeof( Mummy ),
|
||||
typeof( SkeletalKnight ),
|
||||
typeof( Skeleton ),
|
||||
typeof( Zombie ),
|
||||
typeof( ShadowKnight ),
|
||||
typeof( DarknightCreeper ),
|
||||
typeof( RevenantLion ),
|
||||
typeof( LadyOfTheSnow ),
|
||||
typeof( RottingCorpse ),
|
||||
typeof( SkeletalDragon ),
|
||||
typeof( Lich )
|
||||
}
|
||||
} );
|
||||
|
||||
public static OppositionGroup FeyAndUndead
|
||||
{
|
||||
get{ return m_FeyAndUndead; }
|
||||
}
|
||||
}
|
||||
}
|
||||
182
Scripts/Engines/AI/Creature/Paragon.cs
Normal file
182
Scripts/Engines/AI/Creature/Paragon.cs
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Paragon
|
||||
{
|
||||
public static double ChestChance = .10; // Chance that a paragon will carry a paragon chest
|
||||
public static Map[] Maps = new Map[] // Maps that paragons will spawn on
|
||||
{
|
||||
Map.Ilshenar
|
||||
};
|
||||
|
||||
public static Type[] Artifacts = new Type[]
|
||||
{
|
||||
typeof( GoldBricks ), typeof( PhillipsWoodenSteed ),
|
||||
typeof( AlchemistsBauble ), typeof( ArcticDeathDealer ),
|
||||
typeof( BlazeOfDeath ), typeof( BowOfTheJukaKing ),
|
||||
typeof( BurglarsBandana ), typeof( CavortingClub ),
|
||||
typeof( EnchantedTitanLegBone ), typeof( GwennosHarp ),
|
||||
typeof( IolosLute ), typeof( LunaLance ),
|
||||
typeof( NightsKiss ), typeof( NoxRangersHeavyCrossbow ),
|
||||
typeof( OrcishVisage ), typeof( PolarBearMask ),
|
||||
typeof( ShieldOfInvulnerability ), typeof( StaffOfPower ),
|
||||
typeof( VioletCourage ), typeof( HeartOfTheLion ),
|
||||
typeof( WrathOfTheDryad ), typeof( PixieSwatter ),
|
||||
typeof( GlovesOfThePugilist )
|
||||
};
|
||||
|
||||
public static int Hue = 0x501; // Paragon hue
|
||||
|
||||
// Buffs
|
||||
public static double HitsBuff = 5.0;
|
||||
public static double StrBuff = 1.05;
|
||||
public static double IntBuff = 1.20;
|
||||
public static double DexBuff = 1.20;
|
||||
public static double SkillsBuff = 1.20;
|
||||
public static double SpeedBuff = 1.20;
|
||||
public static double FameBuff = 1.40;
|
||||
public static double KarmaBuff = 1.40;
|
||||
public static int DamageBuff = 5;
|
||||
|
||||
public static void Convert( BaseCreature bc )
|
||||
{
|
||||
if ( bc.IsParagon )
|
||||
return;
|
||||
|
||||
bc.Hue = Hue;
|
||||
|
||||
if ( bc.HitsMaxSeed >= 0 )
|
||||
bc.HitsMaxSeed = (int)( bc.HitsMaxSeed * HitsBuff );
|
||||
|
||||
bc.RawStr = (int)( bc.RawStr * StrBuff );
|
||||
bc.RawInt = (int)( bc.RawInt * IntBuff );
|
||||
bc.RawDex = (int)( bc.RawDex * DexBuff );
|
||||
|
||||
bc.Hits = bc.HitsMax;
|
||||
bc.Mana = bc.ManaMax;
|
||||
bc.Stam = bc.StamMax;
|
||||
|
||||
for( int i = 0; i < bc.Skills.Length; i++ )
|
||||
{
|
||||
Skill skill = (Skill)bc.Skills[i];
|
||||
|
||||
if ( skill.Base > 0.0 )
|
||||
skill.Base *= SkillsBuff;
|
||||
}
|
||||
|
||||
bc.PassiveSpeed /= SpeedBuff;
|
||||
bc.ActiveSpeed /= SpeedBuff;
|
||||
|
||||
bc.DamageMin += DamageBuff;
|
||||
bc.DamageMax += DamageBuff;
|
||||
|
||||
if ( bc.Fame > 0 )
|
||||
bc.Fame = (int)( bc.Fame * FameBuff );
|
||||
|
||||
if ( bc.Fame > 32000 )
|
||||
bc.Fame = 32000;
|
||||
|
||||
// TODO: Mana regeneration rate = Sqrt( buffedFame ) / 4
|
||||
|
||||
if ( bc.Karma != 0 )
|
||||
{
|
||||
bc.Karma = (int)( bc.Karma * KarmaBuff );
|
||||
|
||||
if( Math.Abs( bc.Karma ) > 32000 )
|
||||
bc.Karma = 32000 * Math.Sign( bc.Karma );
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnConvert( BaseCreature bc )
|
||||
{
|
||||
if ( !bc.IsParagon )
|
||||
return;
|
||||
|
||||
bc.Hue = 0;
|
||||
|
||||
if ( bc.HitsMaxSeed >= 0 )
|
||||
bc.HitsMaxSeed = (int)( bc.HitsMaxSeed / HitsBuff );
|
||||
|
||||
bc.RawStr = (int)( bc.RawStr / StrBuff );
|
||||
bc.RawInt = (int)( bc.RawInt / IntBuff );
|
||||
bc.RawDex = (int)( bc.RawDex / DexBuff );
|
||||
|
||||
bc.Hits = bc.HitsMax;
|
||||
bc.Mana = bc.ManaMax;
|
||||
bc.Stam = bc.StamMax;
|
||||
|
||||
for( int i = 0; i < bc.Skills.Length; i++ )
|
||||
{
|
||||
Skill skill = (Skill)bc.Skills[i];
|
||||
|
||||
if ( skill.Base > 0.0 )
|
||||
skill.Base /= SkillsBuff;
|
||||
}
|
||||
|
||||
bc.PassiveSpeed *= SpeedBuff;
|
||||
bc.ActiveSpeed *= SpeedBuff;
|
||||
|
||||
bc.DamageMin -= DamageBuff;
|
||||
bc.DamageMax -= DamageBuff;
|
||||
|
||||
if ( bc.Fame > 0 )
|
||||
bc.Fame = (int)( bc.Fame / FameBuff );
|
||||
if ( bc.Karma != 0 )
|
||||
bc.Karma = (int)( bc.Karma / KarmaBuff );
|
||||
}
|
||||
|
||||
public static bool CheckConvert( BaseCreature bc )
|
||||
{
|
||||
return CheckConvert( bc, bc.Location, bc.Map );
|
||||
}
|
||||
|
||||
public static bool CheckConvert( BaseCreature bc, Point3D location, Map m )
|
||||
{
|
||||
if ( !Core.AOS )
|
||||
return false;
|
||||
|
||||
if ( Array.IndexOf( Maps, m ) == -1 )
|
||||
return false;
|
||||
|
||||
if ( bc is BaseChampion || bc is Harrower || bc is BaseVendor || bc is BaseEscortable || bc is Clone )
|
||||
return false;
|
||||
|
||||
int fame = bc.Fame;
|
||||
|
||||
if ( fame > 32000 )
|
||||
fame = 32000;
|
||||
|
||||
double chance = 1 / Math.Round( 20.0 - ( fame / 3200 ));
|
||||
|
||||
return ( chance > Utility.RandomDouble() );
|
||||
}
|
||||
|
||||
public static bool CheckArtifactChance( Mobile m, BaseCreature bc )
|
||||
{
|
||||
if ( !Core.AOS )
|
||||
return false;
|
||||
|
||||
double fame = (double)bc.Fame;
|
||||
|
||||
if ( fame > 32000 )
|
||||
fame = 32000;
|
||||
|
||||
double chance = 1 / ( Math.Max( 10, 100 * ( 0.83 - Math.Round( Math.Log( Math.Round( fame / 6000, 3 ) + 0.001, 10 ), 3 ) ) ) * ( 100 - Math.Sqrt( m.Luck ) ) / 100.0 );
|
||||
|
||||
return chance > Utility.RandomDouble();
|
||||
}
|
||||
|
||||
public static void GiveArtifactTo( Mobile m )
|
||||
{
|
||||
Item item = (Item)Activator.CreateInstance( Artifacts[Utility.Random(Artifacts.Length)] );
|
||||
|
||||
if ( m.AddToBackpack( item ) )
|
||||
m.SendMessage( "As a reward for slaying the mighty paragon, an artifact has been placed in your backpack." );
|
||||
else
|
||||
m.SendMessage( "As your backpack is full, your reward for destroying the legendary paragon has been placed at your feet." );
|
||||
}
|
||||
}
|
||||
}
|
||||
213
Scripts/Engines/AI/Creature/SpeedInfo.cs
Normal file
213
Scripts/Engines/AI/Creature/SpeedInfo.cs
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
using Server.Factions;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class SpeedInfo
|
||||
{
|
||||
// Should we use the new method of speeds?
|
||||
private static bool Enabled = true;
|
||||
|
||||
private double m_ActiveSpeed;
|
||||
private double m_PassiveSpeed;
|
||||
private Type[] m_Types;
|
||||
|
||||
public double ActiveSpeed
|
||||
{
|
||||
get{ return m_ActiveSpeed; }
|
||||
set{ m_ActiveSpeed = value; }
|
||||
}
|
||||
|
||||
public double PassiveSpeed
|
||||
{
|
||||
get{ return m_PassiveSpeed; }
|
||||
set{ m_PassiveSpeed = value; }
|
||||
}
|
||||
|
||||
public Type[] Types
|
||||
{
|
||||
get{ return m_Types; }
|
||||
set{ m_Types = value; }
|
||||
}
|
||||
|
||||
public SpeedInfo( double activeSpeed, double passiveSpeed, Type[] types )
|
||||
{
|
||||
m_ActiveSpeed = activeSpeed;
|
||||
m_PassiveSpeed = passiveSpeed;
|
||||
m_Types = types;
|
||||
}
|
||||
|
||||
public static bool Contains( object obj )
|
||||
{
|
||||
if ( !Enabled )
|
||||
return false;
|
||||
|
||||
if ( m_Table == null )
|
||||
LoadTable();
|
||||
|
||||
SpeedInfo sp = (SpeedInfo)m_Table[obj.GetType()];
|
||||
|
||||
return ( sp != null );
|
||||
}
|
||||
|
||||
public static bool GetSpeeds( object obj, ref double activeSpeed, ref double passiveSpeed )
|
||||
{
|
||||
if ( !Enabled )
|
||||
return false;
|
||||
|
||||
if ( m_Table == null )
|
||||
LoadTable();
|
||||
|
||||
SpeedInfo sp = (SpeedInfo)m_Table[obj.GetType()];
|
||||
|
||||
if ( sp == null )
|
||||
return false;
|
||||
|
||||
activeSpeed = sp.ActiveSpeed;
|
||||
passiveSpeed = sp.PassiveSpeed;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void LoadTable()
|
||||
{
|
||||
m_Table = new Hashtable();
|
||||
|
||||
for ( int i = 0; i < m_Speeds.Length; ++i )
|
||||
{
|
||||
SpeedInfo info = m_Speeds[i];
|
||||
Type[] types = info.Types;
|
||||
|
||||
for ( int j = 0; j < types.Length; ++j )
|
||||
m_Table[types[j]] = info;
|
||||
}
|
||||
}
|
||||
|
||||
private static Hashtable m_Table;
|
||||
|
||||
private static SpeedInfo[] m_Speeds = new SpeedInfo[]
|
||||
{
|
||||
/* Slow */
|
||||
new SpeedInfo( 0.3, 0.6, new Type[]
|
||||
{
|
||||
typeof( AntLion ), typeof( ArcticOgreLord ), typeof( BogThing ),
|
||||
typeof( Bogle ), typeof( BoneKnight ), typeof( EarthElemental ),
|
||||
typeof( Ettin ), typeof( FrostOoze ), typeof( FrostTroll ),
|
||||
typeof( GazerLarva ), typeof( Ghoul ), typeof( Golem ),
|
||||
typeof( HeadlessOne ), typeof( Jwilson ), typeof( Mummy ),
|
||||
typeof( Ogre ), typeof( OgreLord ), typeof( PlagueBeast ),
|
||||
typeof( Quagmire ), typeof( Rat ), typeof( RottingCorpse ),
|
||||
typeof( Sewerrat ), typeof( Skeleton ), typeof( Slime ),
|
||||
typeof( Zombie ), typeof( Walrus ), typeof( RestlessSoul ),
|
||||
typeof( CrystalElemental ), typeof( DarknightCreeper ), typeof( MoundOfMaggots ),
|
||||
typeof( Juggernaut ), typeof( Yamandon ), typeof( Serado )
|
||||
} ),
|
||||
/* Fast */
|
||||
new SpeedInfo( 0.2, 0.4, new Type[]
|
||||
{
|
||||
typeof( LordOaks ), typeof( Silvani ), typeof( AirElemental ),
|
||||
typeof( AncientWyrm ), typeof( Balron ), typeof( BladeSpirits ),
|
||||
typeof( DreadSpider ), typeof( Efreet ), typeof( EtherealWarrior ),
|
||||
typeof( Lich ), typeof( Nightmare ), typeof( OphidianArchmage ),
|
||||
typeof( OphidianMage ), typeof( OphidianWarrior ), typeof( OphidianMatriarch ),
|
||||
typeof( OphidianKnight ), typeof( PoisonElemental ), typeof( Revenant ),
|
||||
typeof( SandVortex ), typeof( SavageRider ), typeof( SavageShaman ),
|
||||
typeof( SnowElemental ), typeof( WhiteWyrm ), typeof( Wisp ),
|
||||
typeof( DemonKnight ), typeof( GiantBlackWidow ), typeof( SummonedAirElemental ),
|
||||
typeof( LesserHiryu ), typeof( Hiryu ), typeof( LadyOfTheSnow ),
|
||||
typeof( RaiJu ), typeof( Ronin )
|
||||
} ),
|
||||
/* Very Fast */
|
||||
new SpeedInfo( 0.175, 0.350, new Type[]
|
||||
{
|
||||
typeof( Barracoon ), typeof( Mephitis ), typeof( Neira ),
|
||||
typeof( Rikktor ), typeof( Semidar ), typeof( EnergyVortex ),
|
||||
typeof( Beetle ), typeof( Pixie ), typeof( SilverSerpent ),
|
||||
typeof( VorpalBunny ), typeof( FleshRenderer ), typeof( KhaldunRevenant ),
|
||||
typeof( FactionDragoon ), typeof( FactionKnight ), typeof( FactionPaladin ),
|
||||
typeof( FactionHenchman ), typeof( FactionMercenary ), typeof( FactionNecromancer ),
|
||||
typeof( FactionSorceress ), typeof( FactionWizard ), typeof( FactionBerserker ),
|
||||
typeof( FactionPaladin ), typeof( Leviathan ), typeof( FireBeetle ),
|
||||
typeof( FanDancer ), typeof( EliteNinja )
|
||||
} ),
|
||||
/* Medium */
|
||||
new SpeedInfo( 0.25, 0.5, new Type[]
|
||||
{
|
||||
typeof( ToxicElemental ), typeof( AgapiteElemental ), typeof( Alligator ),
|
||||
typeof( AncientLich ), typeof( Betrayer ), typeof( Bird ),
|
||||
typeof( BlackBear ), typeof( BlackSolenInfiltratorQueen ), typeof( BlackSolenInfiltratorWarrior ),
|
||||
typeof( BlackSolenQueen ), typeof( BlackSolenWarrior ), typeof( BlackSolenWorker ),
|
||||
typeof( BloodElemental ), typeof( Boar ), typeof( Bogling ),
|
||||
typeof( BoneMagi ), typeof( Brigand ), typeof( BronzeElemental ),
|
||||
typeof( BrownBear ), typeof( Bull ), typeof( BullFrog ),
|
||||
typeof( Cat ), typeof( Centaur ), typeof( ChaosDaemon ),
|
||||
typeof( Chicken ), typeof( GolemController ), typeof( CopperElemental ),
|
||||
typeof( CopperElemental ), typeof( Cougar ), typeof( Cow ),
|
||||
typeof( Cyclops ), typeof( Daemon ), typeof( DeepSeaSerpent ),
|
||||
typeof( DesertOstard ), typeof( DireWolf ), typeof( Dog ),
|
||||
typeof( Dolphin ), typeof( Dragon ), typeof( Drake ),
|
||||
typeof( DullCopperElemental ), typeof( Eagle ), typeof( ElderGazer ),
|
||||
typeof( EvilMage ), typeof( EvilMageLord ), typeof( Executioner ),
|
||||
typeof( Savage ), typeof( FireElemental ), typeof( FireGargoyle ),
|
||||
typeof( FireSteed ), typeof( ForestOstard ), typeof( FrenziedOstard ),
|
||||
typeof( FrostSpider ), typeof( Gargoyle ), typeof( Gazer ),
|
||||
typeof( IceSerpent ), typeof( GiantRat ), typeof( GiantSerpent ),
|
||||
typeof( GiantSpider ), typeof( GiantToad ), typeof( Goat ),
|
||||
typeof( GoldenElemental ), typeof( Gorilla ), typeof( GreatHart ),
|
||||
typeof( GreyWolf ), typeof( GrizzlyBear ), typeof( Guardian ),
|
||||
typeof( Harpy ), typeof( Harrower ), typeof( HellHound ),
|
||||
typeof( Hind ), typeof( HordeMinion ), typeof( Horse ),
|
||||
typeof( Horse ), typeof( IceElemental ), typeof( IceFiend ),
|
||||
typeof( IceSnake ), typeof( Imp ), typeof( JackRabbit ),
|
||||
typeof( Kirin ), typeof( Kraken ), typeof( PredatorHellCat ),
|
||||
typeof( LavaLizard ), typeof( LavaSerpent ), typeof( LavaSnake ),
|
||||
typeof( Lizardman ), typeof( Llama ), typeof( Mongbat ),
|
||||
typeof( StrongMongbat ), typeof( MountainGoat ), typeof( Orc ),
|
||||
typeof( OrcBomber ), typeof( OrcBrute ), typeof( OrcCaptain ),
|
||||
typeof( OrcishLord ), typeof( OrcishMage ), typeof( PackHorse ),
|
||||
typeof( PackLlama ), typeof( Panther ), typeof( Pig ),
|
||||
typeof( PlagueSpawn ), typeof( PolarBear ), typeof( Rabbit ),
|
||||
typeof( Ratman ), typeof( RatmanArcher ), typeof( RatmanMage ),
|
||||
typeof( RedSolenInfiltratorQueen ), typeof( RedSolenInfiltratorWarrior ), typeof( RedSolenQueen ),
|
||||
typeof( RedSolenWarrior ), typeof( RedSolenWorker ), typeof( RidableLlama ),
|
||||
typeof( Ridgeback ), typeof( Scorpion ), typeof( SeaSerpent ),
|
||||
typeof( SerpentineDragon ), typeof( Shade ), typeof( ShadowIronElemental ),
|
||||
typeof( ShadowWisp ), typeof( ShadowWyrm ), typeof( Sheep ),
|
||||
typeof( SilverSteed ), typeof( SkeletalDragon ), typeof( SkeletalMage ),
|
||||
typeof( SkeletalMount ), typeof( HellCat ), typeof( Snake ),
|
||||
typeof( SnowLeopard ), typeof( SpectralArmour ), typeof( Spectre ),
|
||||
typeof( StoneGargoyle ), typeof( StoneHarpy ), typeof( SwampDragon ),
|
||||
typeof( ScaledSwampDragon ), typeof( SwampTentacle ), typeof( TerathanAvenger ),
|
||||
typeof( TerathanDrone ), typeof( TerathanMatriarch ), typeof( TerathanWarrior ),
|
||||
typeof( TimberWolf ), typeof( Titan ), typeof( Troll ),
|
||||
typeof( Unicorn ), typeof( ValoriteElemental ), typeof( VeriteElemental ),
|
||||
typeof( CoMWarHorse ), typeof( MinaxWarHorse ), typeof( SLWarHorse ),
|
||||
typeof( TBWarHorse ), typeof( WaterElemental ), typeof( WhippingVine ),
|
||||
typeof( WhiteWolf ), typeof( Wraith ), typeof( Wyvern ),
|
||||
typeof( KhaldunZealot ), typeof( KhaldunSummoner ), typeof( SavageRidgeback ),
|
||||
typeof( LichLord ), typeof( SkeletalKnight ), typeof( SummonedDaemon ),
|
||||
typeof( SummonedEarthElemental ), typeof( SummonedWaterElemental ), typeof( SummonedFireElemental ),
|
||||
typeof( MeerWarrior ), typeof( MeerEternal ), typeof( MeerMage ),
|
||||
typeof( MeerCaptain ), typeof( JukaLord ), typeof( JukaMage ),
|
||||
typeof( JukaWarrior ), typeof( AbysmalHorror ), typeof( BoneDemon ),
|
||||
typeof( Devourer ), typeof( FleshGolem ), typeof( Gibberling ),
|
||||
typeof( GoreFiend ), typeof( Impaler ), typeof( PatchworkSkeleton ),
|
||||
typeof( Ravager ), typeof( ShadowKnight ), typeof( SkitteringHopper ),
|
||||
typeof( Treefellow ), typeof( VampireBat ), typeof( WailingBanshee ),
|
||||
typeof( WandererOfTheVoid ), typeof( Cursed ), typeof( GrimmochDrummel ),
|
||||
typeof( LysanderGathenwale ), typeof( MorgBergen ), typeof( ShadowFiend ),
|
||||
typeof( SpectralArmour ), typeof( TavaraSewel ), typeof( ArcaneDaemon ),
|
||||
typeof( Doppleganger ), typeof( EnslavedGargoyle ), typeof( ExodusMinion ),
|
||||
typeof( ExodusOverseer ), typeof( GargoyleDestroyer ), typeof( GargoyleEnforcer ),
|
||||
typeof( Moloch ), typeof( BakeKitsune ), typeof( DeathwatchBeetleHatchling ),
|
||||
typeof( Kappa ), typeof( KazeKemono ), typeof( DeathwatchBeetle ),
|
||||
typeof( TsukiWolf ), typeof( YomotsuElder ), typeof( YomotsuPriest ),
|
||||
typeof( YomotsuWarrior ), typeof( RevenantLion ), typeof( Oni ),
|
||||
typeof( RuneBeetle ), typeof( Gaman ), typeof( Crane )
|
||||
} )
|
||||
};
|
||||
}
|
||||
}
|
||||
45
Scripts/Engines/AI/Targets/AIControlMobileTarget.cs
Normal file
45
Scripts/Engines/AI/Targets/AIControlMobileTarget.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Targeting;
|
||||
using Server.Mobiles;
|
||||
using System.Collections;
|
||||
|
||||
namespace Server.Targets
|
||||
{
|
||||
public class AIControlMobileTarget : Target
|
||||
{
|
||||
private ArrayList m_List;
|
||||
private OrderType m_Order;
|
||||
|
||||
public OrderType Order
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Order;
|
||||
}
|
||||
}
|
||||
|
||||
public AIControlMobileTarget( BaseAI ai, OrderType order ) : base( -1, false, ( order == OrderType.Attack ? TargetFlags.Harmful : TargetFlags.None ) )
|
||||
{
|
||||
m_List = new ArrayList();
|
||||
m_Order = order;
|
||||
|
||||
AddAI( ai );
|
||||
}
|
||||
|
||||
public void AddAI( BaseAI ai )
|
||||
{
|
||||
if ( !m_List.Contains( ai ) )
|
||||
m_List.Add( ai );
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object o )
|
||||
{
|
||||
if ( o is Mobile )
|
||||
{
|
||||
for ( int i = 0; i < m_List.Count; ++i )
|
||||
((BaseAI)m_List[i]).EndPickTarget( from, (Mobile)o, m_Order );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Scripts/Engines/AI/Team/Team.cs
Normal file
32
Scripts/Engines/AI/Team/Team.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server.Targeting;
|
||||
using Server.Network;
|
||||
/*
|
||||
* NPC could use a team objets..
|
||||
*
|
||||
* -List of members
|
||||
* -List of ennemy teams
|
||||
* -List of ally team
|
||||
* -Team could be set automaticaly at mobile creation by the region system
|
||||
* -Team could be the owner of a common timer instead of one by creature
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Team
|
||||
{
|
||||
//private ArrayList m_arAlly;
|
||||
//private ArrayList m_arFoe;
|
||||
|
||||
//private ArrayList m_arMember;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Scripts/Engines/AI/Team/TeamRegistry.cs
Normal file
29
Scripts/Engines/AI/Team/TeamRegistry.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server.Targeting;
|
||||
using Server.Network;
|
||||
/*
|
||||
* NPC could use a faction objets..
|
||||
*
|
||||
* -List of members
|
||||
* -List of ennemy factions
|
||||
* -List of neutral factions
|
||||
* -List of ally faction
|
||||
* -Team could be set automaticaly at mobile creation by the region system
|
||||
* -Team could be the owner of a common timer instead of one by creature
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class TeamRegistry
|
||||
{
|
||||
//private ArrayList m_arTeam;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue