250 lines
5.9 KiB
C#
250 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
using Server;
|
|
using Server.Items;
|
|
|
|
namespace Server.Multis
|
|
{
|
|
public class ShipTrackingContext
|
|
{
|
|
private static Dictionary<Mobile, ShipTrackingContext> m_Table = new Dictionary<Mobile, ShipTrackingContext>();
|
|
|
|
private Mobile m_Mobile;
|
|
|
|
public List<BoatTrackingArrow> Arrows { get { return m_Arrows; } }
|
|
private List<BoatTrackingArrow> m_Arrows = new List<BoatTrackingArrow>();
|
|
|
|
public ShipTrackingContext(Mobile mobile, List<BoatTrackingArrow> arrows)
|
|
{
|
|
m_Mobile = mobile;
|
|
m_Arrows = arrows;
|
|
|
|
m_Table.Add(mobile, this);
|
|
}
|
|
|
|
public static bool RemoveContext(Mobile from)
|
|
{
|
|
if(!m_Table.ContainsKey(from))
|
|
return false;
|
|
|
|
m_Table.Remove(from);
|
|
return true;
|
|
}
|
|
|
|
public static bool CanAddContext(Mobile from)
|
|
{
|
|
if(!m_Table.ContainsKey(from))
|
|
return true;
|
|
|
|
if(m_Table[from] != null && m_Table[from].Arrows.Count > 5)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
public static ShipTrackingContext GetContext(Mobile from)
|
|
{
|
|
if(!m_Table.ContainsKey(from))
|
|
return null;
|
|
|
|
return m_Table[from];
|
|
}
|
|
|
|
public bool IsTrackingBoat(Item item)
|
|
{
|
|
if (item is BaseBoat || item is PlunderBeaconAddon)
|
|
{
|
|
foreach (BoatTrackingArrow arrow in m_Arrows)
|
|
{
|
|
if (arrow.Boat == item)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void AddArrow(BoatTrackingArrow arrow)
|
|
{
|
|
m_Arrows.Add(arrow);
|
|
}
|
|
|
|
public void RemoveArrow(BoatTrackingArrow arrow)
|
|
{
|
|
if (m_Arrows.Contains(arrow))
|
|
m_Arrows.Remove(arrow);
|
|
|
|
if(m_Mobile == null)
|
|
return;
|
|
|
|
if (m_Arrows.Count == 0)
|
|
{
|
|
m_Mobile.QuestArrow = null;
|
|
RemoveContext(m_Mobile);
|
|
}
|
|
else
|
|
{
|
|
if (m_Mobile.QuestArrow == arrow)
|
|
m_Mobile.QuestArrow = null;
|
|
|
|
if (m_Arrows.Count > 0)
|
|
m_Mobile.QuestArrow = m_Arrows[0];
|
|
}
|
|
}
|
|
}
|
|
|
|
public class BoatTrackingArrow : QuestArrow
|
|
{
|
|
public static readonly int MaxRange = 200;
|
|
public static readonly int MaxBoats = 5;
|
|
|
|
private Mobile m_From;
|
|
private Timer m_Timer;
|
|
private Item m_Boat;
|
|
|
|
public Mobile From { get { return m_From; } }
|
|
public Timer Timer { get { return m_Timer; } }
|
|
public Item Boat { get { return m_Boat; } }
|
|
|
|
public BoatTrackingArrow(Mobile from, Item boat, int range) : base(from, boat)
|
|
{
|
|
m_Boat = boat;
|
|
m_From = from;
|
|
m_Timer = new BoatTrackingTimer(from, boat, range, this);
|
|
m_Timer.Start();
|
|
}
|
|
|
|
public override void OnClick(bool rightClick)
|
|
{
|
|
if (rightClick && m_From != null)
|
|
{
|
|
ShipTrackingContext st = ShipTrackingContext.GetContext(m_From);
|
|
|
|
if (st != null)
|
|
st.RemoveArrow(this);
|
|
|
|
m_From = null;
|
|
Stop();
|
|
}
|
|
}
|
|
|
|
public override void OnStop()
|
|
{
|
|
if(m_Timer != null)
|
|
m_Timer.Stop();
|
|
|
|
if(m_From != null)
|
|
m_From.SendLocalizedMessage(503177); // You have lost your quarry.
|
|
}
|
|
|
|
public static void StopTracking(Mobile from)
|
|
{
|
|
ShipTrackingContext st = ShipTrackingContext.GetContext(from);
|
|
|
|
if (st != null)
|
|
{
|
|
for (int i = 0; i < st.Arrows.Count; i++)
|
|
st.Arrows[i].Stop();
|
|
|
|
ShipTrackingContext.RemoveContext(from);
|
|
}
|
|
|
|
from.QuestArrow = null;
|
|
}
|
|
|
|
public static void StartTracking(Mobile from)
|
|
{
|
|
if(!ShipTrackingContext.CanAddContext(from))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var targets = new List<Item>();
|
|
Map map = from.Map;
|
|
|
|
if(map == null || map == Map.Internal)
|
|
return;
|
|
|
|
BaseBoat fromBoat = BaseBoat.FindBoatAt(from, map);
|
|
ShipTrackingContext context = ShipTrackingContext.GetContext(from);
|
|
|
|
if(fromBoat == null)
|
|
{
|
|
from.SendMessage("You must be on your boat to use this command.");
|
|
}
|
|
|
|
IPooledEnumerable eable = map.GetItemsInRange(from.Location, MaxRange);
|
|
|
|
foreach(Item item in eable)
|
|
{
|
|
if(context != null && context.IsTrackingBoat(item))
|
|
continue;
|
|
if(!targets.Contains(item) && ((item is BaseBoat && (BaseBoat)item != fromBoat) || item is PlunderBeaconAddon))
|
|
targets.Add(item);
|
|
}
|
|
|
|
eable.Free();
|
|
|
|
List<BoatTrackingArrow> arrows = new List<BoatTrackingArrow>();
|
|
|
|
for(int i = 0; i < targets.Count; i++)
|
|
{
|
|
if(i >= MaxBoats)
|
|
break;
|
|
|
|
BoatTrackingArrow arrow = new BoatTrackingArrow(from, targets[i], MaxRange);
|
|
|
|
if(context == null)
|
|
arrows.Add(arrow);
|
|
else
|
|
context.AddArrow(arrow);
|
|
}
|
|
|
|
if (from.QuestArrow == null && arrows.Count > 0)
|
|
from.QuestArrow = arrows[0];
|
|
|
|
if(context == null)
|
|
new ShipTrackingContext(from, arrows);
|
|
}
|
|
}
|
|
|
|
public class BoatTrackingTimer : Timer
|
|
{
|
|
private Mobile m_From;
|
|
private Item m_Target;
|
|
private int m_Range;
|
|
private int m_LastX, m_LastY;
|
|
private QuestArrow m_Arrow;
|
|
|
|
public BoatTrackingTimer(Mobile from, Item target, int range, QuestArrow arrow) : base( TimeSpan.FromSeconds( 0.25 ), TimeSpan.FromSeconds( 2.5 ) )
|
|
{
|
|
m_From = from;
|
|
m_Target = target;
|
|
m_Range = range;
|
|
m_Arrow = arrow;
|
|
}
|
|
|
|
protected override void OnTick()
|
|
{
|
|
if(!m_Arrow.Running)
|
|
{
|
|
this.Stop();
|
|
return;
|
|
}
|
|
else if (m_From.NetState == null || m_From.Deleted || m_Target.Deleted || m_From.Map != m_Target.Map || !m_From.InRange(m_Target, m_Range))
|
|
{
|
|
m_Arrow.Stop();
|
|
this.Stop();
|
|
return;
|
|
}
|
|
|
|
if(m_LastX != m_Target.X || m_LastY != m_Target.Y)
|
|
{
|
|
m_LastX = m_Target.X;
|
|
m_LastY = m_Target.Y;
|
|
|
|
m_Arrow.Update();
|
|
}
|
|
}
|
|
}
|
|
}
|