458 lines
15 KiB
C#
458 lines
15 KiB
C#
using System;
|
|
using System.Collections;
|
|
using Server.Targeting;
|
|
using Server.Network;
|
|
using Server.Mobiles;
|
|
using System.Collections.Generic;
|
|
using Server.ContextMenus;
|
|
using Server.Spells;
|
|
|
|
namespace Server.Engines.Despise
|
|
{
|
|
public class DespiseMeleeAI : MeleeAI
|
|
{
|
|
private long _NextAggressorCheck;
|
|
|
|
private DespiseCreature m_Creature;
|
|
|
|
public DespiseMeleeAI(DespiseCreature m) : base(m)
|
|
{
|
|
m_Creature = m;
|
|
}
|
|
|
|
public override bool Obey()
|
|
{
|
|
if (m_Creature.Orb == null || !m_Creature.Controlled)
|
|
return base.Obey();
|
|
|
|
switch (m_Creature.Orb.Aggression)
|
|
{
|
|
default:
|
|
{
|
|
m_Creature.ControlOrder = OrderType.Follow;
|
|
DoOrderFollow();
|
|
}
|
|
break;
|
|
case Aggression.Defensive:
|
|
{
|
|
if (m_Creature.Combatant != null)
|
|
{
|
|
if (m_Creature.ControlOrder == OrderType.Follow)
|
|
{
|
|
m_Creature.ControlOrder = OrderType.Attack;
|
|
Action = ActionType.Combat;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (_NextAggressorCheck <= Core.TickCount)
|
|
{
|
|
IPoint3D p = m_Creature.Orb.GetAnchorActual();
|
|
double range = m_Creature.RangePerception;
|
|
|
|
IPooledEnumerable eable = m_Creature.Map.GetMobilesInRange(new Point3D(p), (int)range);
|
|
Mobile closest = null;
|
|
|
|
foreach (Mobile m in eable)
|
|
{
|
|
if (m.Combatant == m_Creature || m.Combatant == m_Creature.ControlMaster)
|
|
{
|
|
double dist = closest == null ? range : closest.GetDistanceToSqrt(m_Creature);
|
|
if (closest == null || dist < range)
|
|
{
|
|
range = dist;
|
|
closest = m;
|
|
}
|
|
}
|
|
}
|
|
|
|
eable.Free();
|
|
|
|
if (closest != null)
|
|
{
|
|
m_Creature.ControlTarget = closest;
|
|
m_Creature.ControlOrder = OrderType.Attack;
|
|
m_Creature.Combatant = closest;
|
|
m_Creature.DebugSay("But -that- is not dead. Here we go again...");
|
|
|
|
Action = ActionType.Combat;
|
|
}
|
|
|
|
_NextAggressorCheck = Core.TickCount + 1000;
|
|
}
|
|
}
|
|
break;
|
|
case Aggression.Aggressive:
|
|
{
|
|
if (m_Creature.Combatant != null)
|
|
{
|
|
if (m_Creature.ControlOrder == OrderType.Follow)
|
|
{
|
|
m_Creature.ControlOrder = OrderType.Attack;
|
|
Action = ActionType.Combat;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (AcquireFocusMob(m_Creature.RangePerception, m_Creature.FightMode, false, false, true))
|
|
{
|
|
if (m_Creature.FocusMob == m_Creature.ControlMaster)
|
|
break;
|
|
|
|
if (m_Creature.Debug)
|
|
m_Creature.DebugSay("I have detected {0}, attacking", m_Creature.FocusMob.Name);
|
|
|
|
m_Creature.ControlOrder = OrderType.Attack;
|
|
m_Creature.Combatant = m_Creature.FocusMob;
|
|
|
|
Action = ActionType.Combat;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (m_Creature.Combatant == null)
|
|
{
|
|
m_Creature.ControlOrder = OrderType.Follow;
|
|
m_Creature.ControlTarget = m_Creature.ControlMaster;
|
|
Action = ActionType.Guard;
|
|
DoOrderFollow();
|
|
}
|
|
|
|
Think();
|
|
return true;
|
|
}
|
|
|
|
public override bool DoOrderFollow()
|
|
{
|
|
if (m_Creature.Orb != null)
|
|
m_Creature.Orb.InvalidateHue();
|
|
|
|
return base.DoOrderFollow();
|
|
}
|
|
|
|
public override bool AcquireFocusMob(int iRange, FightMode acqType, bool bPlayerOnly, bool bFacFriend, bool bFacFoe)
|
|
{
|
|
if (m_Creature.Orb == null || m_Creature.ControlMaster == null)
|
|
{
|
|
return base.AcquireFocusMob(iRange, acqType, bPlayerOnly, bFacFriend, bFacFoe);
|
|
}
|
|
|
|
if (m_Creature.Orb.Aggression != Aggression.Aggressive)
|
|
return false;
|
|
|
|
if (Core.TickCount - m_Creature.NextReacquireTime < 0)
|
|
{
|
|
m_Creature.FocusMob = null;
|
|
return false;
|
|
}
|
|
|
|
m_Creature.NextReacquireTime = Core.TickCount + (int)m_Creature.ReacquireDelay.TotalMilliseconds;
|
|
|
|
int range = m_Creature.RangePerception;
|
|
IPoint3D p = m_Creature.Orb.Anchor as IPoint3D;
|
|
|
|
if (p == null)
|
|
p = m_Creature;
|
|
|
|
Mobile focus = GetFocus(p, range);
|
|
|
|
if (focus != null)
|
|
{
|
|
m_Creature.FocusMob = focus;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private Mobile GetFocus(IPoint3D p, int range)
|
|
{
|
|
IPooledEnumerable eable = m_Creature.Map.GetMobilesInRange(new Point3D(p), range);
|
|
Mobile focus = null;
|
|
int dist = range;
|
|
|
|
foreach (Mobile m in eable)
|
|
{
|
|
if (m is DespiseCreature || m is DespiseBoss)
|
|
{
|
|
DespiseCreature dc = m as DespiseCreature;
|
|
|
|
if(m is DespiseBoss || (dc != null && (dc.Orb == null && !dc.Controlled) || (dc.Alignment != m_Creature.Alignment)))
|
|
{
|
|
int distance = (int)m_Creature.GetDistanceToSqrt(m);
|
|
|
|
if (focus == null || distance < dist)
|
|
{
|
|
focus = m;
|
|
dist = distance;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
eable.Free();
|
|
return focus;
|
|
}
|
|
|
|
public override bool WalkMobileRange(IPoint3D p, int iSteps, bool bRun, int iWantDistMin, int iWantDistMax)
|
|
{
|
|
if (m_Creature.Orb == null || m_Creature.ControlMaster == null)
|
|
{
|
|
return base.WalkMobileRange(p, iSteps, bRun, iWantDistMin, iWantDistMax);
|
|
}
|
|
|
|
int range = m_Creature.GetLeashLength();
|
|
|
|
if (p is Mobile && (Mobile)p == m_Creature.ControlMaster)
|
|
{
|
|
p = m_Creature.Orb.GetAnchorActual();
|
|
|
|
if (m_Creature.InRange(p, range))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return base.WalkMobileRange(p, iSteps, bRun, range, range);
|
|
}
|
|
}
|
|
|
|
return base.WalkMobileRange(p, iSteps, bRun, iWantDistMin, iWantDistMax);
|
|
}
|
|
|
|
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
|
|
{
|
|
}
|
|
|
|
public override void OnSpeech(SpeechEventArgs e)
|
|
{
|
|
}
|
|
}
|
|
|
|
public class DespiseMageAI : MageAI
|
|
{
|
|
private long _NextAggressorCheck;
|
|
|
|
private DespiseCreature m_Creature;
|
|
|
|
public DespiseMageAI(DespiseCreature m)
|
|
: base(m)
|
|
{
|
|
m_Creature = m;
|
|
}
|
|
|
|
public override bool Obey()
|
|
{
|
|
if (m_Creature.Orb == null || !m_Creature.Controlled)
|
|
return base.Obey();
|
|
|
|
switch (m_Creature.Orb.Aggression)
|
|
{
|
|
default:
|
|
{
|
|
m_Creature.ControlOrder = OrderType.Follow;
|
|
DoOrderFollow();
|
|
}
|
|
break;
|
|
case Aggression.Defensive:
|
|
{
|
|
if (m_Creature.Combatant != null)
|
|
{
|
|
if (m_Creature.ControlOrder == OrderType.Follow)
|
|
{
|
|
m_Creature.ControlOrder = OrderType.Attack;
|
|
Action = ActionType.Combat;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (_NextAggressorCheck <= Core.TickCount)
|
|
{
|
|
IPoint3D p = m_Creature.Orb.GetAnchorActual();
|
|
double range = m_Creature.RangePerception;
|
|
|
|
IPooledEnumerable eable = m_Creature.Map.GetMobilesInRange(new Point3D(p), (int)range);
|
|
Mobile closest = null;
|
|
|
|
foreach (Mobile m in eable)
|
|
{
|
|
if (m.Combatant == m_Creature || m.Combatant == m_Creature.ControlMaster)
|
|
{
|
|
double dist = closest == null ? range : closest.GetDistanceToSqrt(m_Creature);
|
|
if (closest == null || dist < range)
|
|
{
|
|
range = dist;
|
|
closest = m;
|
|
}
|
|
}
|
|
}
|
|
|
|
eable.Free();
|
|
|
|
if (closest != null)
|
|
{
|
|
m_Creature.ControlTarget = closest;
|
|
m_Creature.ControlOrder = OrderType.Attack;
|
|
m_Creature.Combatant = closest;
|
|
m_Creature.DebugSay("But -that- is not dead. Here we go again...");
|
|
|
|
Action = ActionType.Combat;
|
|
}
|
|
|
|
_NextAggressorCheck = Core.TickCount + 1000;
|
|
}
|
|
}
|
|
break;
|
|
case Aggression.Aggressive:
|
|
{
|
|
if (m_Creature.Combatant != null)
|
|
{
|
|
if (m_Creature.ControlOrder == OrderType.Follow)
|
|
{
|
|
m_Creature.ControlOrder = OrderType.Attack;
|
|
Action = ActionType.Combat;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (AcquireFocusMob(m_Creature.RangePerception, m_Creature.FightMode, false, false, true))
|
|
{
|
|
if (m_Creature.FocusMob == m_Creature.ControlMaster)
|
|
break;
|
|
|
|
if (m_Creature.Debug)
|
|
m_Creature.DebugSay("I have detected {0}, attacking", m_Creature.FocusMob.Name);
|
|
|
|
m_Creature.ControlOrder = OrderType.Attack;
|
|
m_Creature.Combatant = m_Creature.FocusMob;
|
|
|
|
Action = ActionType.Combat;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (m_Creature.Combatant == null)
|
|
{
|
|
m_Creature.ControlOrder = OrderType.Follow;
|
|
m_Creature.ControlTarget = m_Creature.ControlMaster;
|
|
Action = ActionType.Guard;
|
|
DoOrderFollow();
|
|
}
|
|
|
|
Think();
|
|
return true;
|
|
}
|
|
|
|
public override bool DoOrderFollow()
|
|
{
|
|
if (m_Creature.Orb != null)
|
|
m_Creature.Orb.InvalidateHue();
|
|
|
|
return base.DoOrderFollow();
|
|
}
|
|
|
|
public override bool AcquireFocusMob(int iRange, FightMode acqType, bool bPlayerOnly, bool bFacFriend, bool bFacFoe)
|
|
{
|
|
if (m_Creature.Orb == null || m_Creature.ControlMaster == null)
|
|
{
|
|
return base.AcquireFocusMob(iRange, acqType, bPlayerOnly, bFacFriend, bFacFoe);
|
|
}
|
|
|
|
if (m_Creature.Orb.Aggression != Aggression.Aggressive)
|
|
return false;
|
|
|
|
if (Core.TickCount - m_Creature.NextReacquireTime < 0)
|
|
{
|
|
m_Creature.FocusMob = null;
|
|
return false;
|
|
}
|
|
|
|
m_Creature.NextReacquireTime = Core.TickCount + (int)m_Creature.ReacquireDelay.TotalMilliseconds;
|
|
|
|
int range = m_Creature.RangePerception;
|
|
IPoint3D p = m_Creature.Orb.Anchor as IPoint3D;
|
|
|
|
if (p == null)
|
|
p = m_Creature;
|
|
|
|
Mobile focus = GetFocus(p, range);
|
|
|
|
if (focus != null)
|
|
{
|
|
m_Creature.FocusMob = focus;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private Mobile GetFocus(IPoint3D p, int range)
|
|
{
|
|
IPooledEnumerable eable = m_Creature.Map.GetMobilesInRange(new Point3D(p), range);
|
|
Mobile focus = null;
|
|
int dist = range;
|
|
|
|
foreach (Mobile m in eable)
|
|
{
|
|
if (m is DespiseCreature || m is DespiseBoss)
|
|
{
|
|
DespiseCreature dc = m as DespiseCreature;
|
|
|
|
if (m is DespiseBoss || (dc != null && (dc.Orb == null && !dc.Controlled) || (dc.Alignment != m_Creature.Alignment)))
|
|
{
|
|
int distance = (int)m_Creature.GetDistanceToSqrt(m);
|
|
|
|
if (focus == null || distance < dist)
|
|
{
|
|
focus = m;
|
|
dist = distance;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
eable.Free();
|
|
return focus;
|
|
}
|
|
|
|
public override bool WalkMobileRange(IPoint3D p, int iSteps, bool bRun, int iWantDistMin, int iWantDistMax)
|
|
{
|
|
if (m_Creature.Orb == null || m_Creature.ControlMaster == null)
|
|
{
|
|
return base.WalkMobileRange(p, iSteps, bRun, iWantDistMin, iWantDistMax);
|
|
}
|
|
|
|
int range = m_Creature.GetLeashLength();
|
|
|
|
if (p is Mobile && (Mobile)p == m_Creature.ControlMaster)
|
|
{
|
|
p = m_Creature.Orb.GetAnchorActual();
|
|
|
|
if (m_Creature.InRange(p, range))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return base.WalkMobileRange(p, iSteps, bRun, range, range);
|
|
}
|
|
}
|
|
|
|
return base.WalkMobileRange(p, iSteps, bRun, iWantDistMin, iWantDistMax);
|
|
}
|
|
|
|
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
|
|
{
|
|
}
|
|
|
|
public override void OnSpeech(SpeechEventArgs e)
|
|
{
|
|
}
|
|
}
|
|
} |