Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
330
Scripts/Mobiles/AI/OrcScoutAI.cs
Normal file
330
Scripts/Mobiles/AI/OrcScoutAI.cs
Normal file
@@ -0,0 +1,330 @@
|
||||
#region References
|
||||
using System;
|
||||
|
||||
using Server.Items;
|
||||
using Server.Spells;
|
||||
using Server.Targeting;
|
||||
#endregion
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class OrcScoutAI : BaseAI
|
||||
{
|
||||
private static readonly double teleportChance = 0.04;
|
||||
private static readonly int[] m_Offsets = {0, 0, -1, -1, 0, -1, 1, -1, -1, 0, 1, 0, -1, -1, 0, 1, 1, 1};
|
||||
|
||||
public OrcScoutAI(BaseCreature m)
|
||||
: base(m)
|
||||
{ }
|
||||
|
||||
public override bool DoActionWander()
|
||||
{
|
||||
m_Mobile.DebugSay("I have no combatant");
|
||||
|
||||
PerformHide();
|
||||
|
||||
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
|
||||
{
|
||||
if (m_Mobile.Combatant != null)
|
||||
{
|
||||
Action = ActionType.Combat;
|
||||
return true;
|
||||
}
|
||||
|
||||
base.DoActionWander();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool DoActionCombat()
|
||||
{
|
||||
var c = m_Mobile.Combatant as Mobile;
|
||||
|
||||
if (c == null || c.Deleted || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet)
|
||||
{
|
||||
m_Mobile.DebugSay("My combatant is gone, so my guard is up");
|
||||
|
||||
Action = ActionType.Guard;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Utility.RandomDouble() < teleportChance)
|
||||
{
|
||||
TryToTeleport();
|
||||
}
|
||||
|
||||
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 as Mobile;
|
||||
|
||||
if (c == null)
|
||||
{
|
||||
m_Mobile.DebugSay("My combatant has fled, so I am on guard");
|
||||
Action = ActionType.Guard;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (MoveTo(c, true, m_Mobile.RangeFight))
|
||||
{
|
||||
if (!DirectionLocked)
|
||||
m_Mobile.Direction = m_Mobile.GetDirectionTo(c);
|
||||
}
|
||||
else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
|
||||
{
|
||||
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(c) > m_Mobile.RangePerception + 1)
|
||||
{
|
||||
m_Mobile.DebugSay("I cannot find {0}, so my guard is up", c.Name);
|
||||
|
||||
Action = ActionType.Guard;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mobile.DebugSay("I should be closer to {0}", c.Name);
|
||||
}
|
||||
|
||||
if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee)
|
||||
{
|
||||
/* // When we have no ammo, we flee
|
||||
Container pack = m_Mobile.Backpack;
|
||||
|
||||
if (pack == null || pack.FindItemByType(typeof(Arrow)) == null)
|
||||
{
|
||||
Action = ActionType.Flee;
|
||||
if (Utility.RandomDouble() < teleportChance + 0.1)
|
||||
{
|
||||
TryToTeleport();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100)
|
||||
{
|
||||
// We are low on health, should we flee?
|
||||
if (Utility.Random(100) <= Math.Max(10, 10 + c.Hits - m_Mobile.Hits))
|
||||
{
|
||||
m_Mobile.DebugSay("I am going to flee from {0}", c.Name);
|
||||
Action = ActionType.Flee;
|
||||
if (Utility.RandomDouble() < teleportChance + 0.1)
|
||||
{
|
||||
TryToTeleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
var c = m_Mobile.Combatant as Mobile;
|
||||
|
||||
// Container pack = m_Mobile.Backpack;
|
||||
// bool hasAmmo = !(pack == null || pack.FindItemByType(typeof(Arrow)) == null);
|
||||
// They can shoot even with no ammo!
|
||||
|
||||
if ( /*hasAmmo && */m_Mobile.Hits > m_Mobile.HitsMax / 2)
|
||||
{
|
||||
// If I have a target, go back and fight them
|
||||
if (c != null && m_Mobile.GetDistanceToSqrt(c) <= m_Mobile.RangePerception * 2)
|
||||
{
|
||||
m_Mobile.DebugSay("I am stronger now, reengaging {0}", c.Name);
|
||||
Action = ActionType.Combat;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mobile.DebugSay("I am stronger now, my guard is up");
|
||||
Action = ActionType.Guard;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PerformHide();
|
||||
|
||||
base.DoActionFlee();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Mobile FindNearestAggressor()
|
||||
{
|
||||
Mobile nearest = null;
|
||||
|
||||
var dist = 9999.0;
|
||||
|
||||
IPooledEnumerable eable = m_Mobile.GetMobilesInRange(m_Mobile.RangePerception);
|
||||
|
||||
foreach (Mobile m in eable)
|
||||
{
|
||||
if (m.Player && !m.Hidden && m.IsPlayer() && m.Combatant == m_Mobile)
|
||||
{
|
||||
if (dist > m.GetDistanceToSqrt(m_Mobile))
|
||||
{
|
||||
nearest = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
private void TryToTeleport()
|
||||
{
|
||||
var m = FindNearestAggressor();
|
||||
|
||||
if (m == null || m.Map == null || m_Mobile.Map == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Mobile.GetDistanceToSqrt(m) > m_Mobile.RangePerception + 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var px = m_Mobile.X;
|
||||
var py = m_Mobile.Y;
|
||||
|
||||
var dx = m_Mobile.X - m.X;
|
||||
var dy = m_Mobile.Y - m.Y;
|
||||
|
||||
// get vector's length
|
||||
|
||||
var l = Math.Sqrt((dx * dx + dy * dy));
|
||||
|
||||
if (l == 0)
|
||||
{
|
||||
var rand = Utility.Random(8) + 1;
|
||||
rand *= 2;
|
||||
dx = m_Offsets[rand];
|
||||
dy = m_Offsets[rand + 1];
|
||||
l = Math.Sqrt((dx * dx + dy * dy));
|
||||
}
|
||||
|
||||
// normalize vector
|
||||
var dpx = (dx) / l;
|
||||
var dpy = (dy) / l;
|
||||
// move
|
||||
px += (int)(dpx * (4 + Utility.Random(3)));
|
||||
py += (int)(dpy * (4 + Utility.Random(3)));
|
||||
|
||||
for (var i = 0; i < m_Offsets.Length; i += 2)
|
||||
{
|
||||
int x = m_Offsets[i], y = m_Offsets[i + 1];
|
||||
|
||||
var p = new Point3D(px + x, py + y, 0);
|
||||
|
||||
var lt = new LandTarget(p, m_Mobile.Map);
|
||||
|
||||
if (m_Mobile.InLOS(lt) && m_Mobile.Map.CanSpawnMobile(px + x, py + y, lt.Z) &&
|
||||
!SpellHelper.CheckMulti(p, m_Mobile.Map))
|
||||
{
|
||||
m_Mobile.FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
|
||||
m_Mobile.PlaySound(0x1FE);
|
||||
|
||||
m_Mobile.Location = new Point3D(lt.X, lt.Y, lt.Z);
|
||||
m_Mobile.ProcessDelta();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HideSelf()
|
||||
{
|
||||
if (Core.TickCount >= m_Mobile.NextSkillTime)
|
||||
{
|
||||
Effects.SendLocationParticles(
|
||||
EffectItem.Create(m_Mobile.Location, m_Mobile.Map, EffectItem.DefaultDuration),
|
||||
0x3728,
|
||||
10,
|
||||
10,
|
||||
2023);
|
||||
|
||||
m_Mobile.PlaySound(0x22F);
|
||||
m_Mobile.Hidden = true;
|
||||
|
||||
m_Mobile.UseSkill(SkillName.Stealth);
|
||||
}
|
||||
}
|
||||
|
||||
private void PerformHide()
|
||||
{
|
||||
if (!m_Mobile.Alive || m_Mobile.Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_Mobile.Hidden)
|
||||
{
|
||||
var chance = 0.05;
|
||||
|
||||
if (m_Mobile.Hits < 20)
|
||||
{
|
||||
chance = 0.1;
|
||||
}
|
||||
|
||||
if (m_Mobile.Poisoned)
|
||||
{
|
||||
chance = 0.01;
|
||||
}
|
||||
|
||||
if (Utility.RandomDouble() < chance)
|
||||
{
|
||||
HideSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user