Files
abysmal-isle/Scripts/Services/Expansions/High Seas/Regions/SeaMarket.cs
Unstable Kitsune b918192e4e Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
2023-11-28 23:20:26 -05:00

426 lines
14 KiB
C#

using System;
using System.Xml;
using System.Linq;
using Server;
using Server.Mobiles;
using Server.Items;
using Server.Multis;
using System.Collections.Generic;
using Server.Commands;
using Server.Engines.Quests;
using Server.Spells;
namespace Server.Regions
{
public class SeaMarketRegion : BaseRegion
{
private static readonly TimeSpan KickDuration = TimeSpan.FromMinutes(20);
private static SeaMarketRegion m_Region1;
private static SeaMarketRegion m_Region2;
private Timer m_Timer;
private static Timer m_BlabTimer;
private static bool m_RestrictBoats;
private Dictionary<BaseBoat, DateTime> m_BoatTable = new Dictionary<BaseBoat, DateTime>();
public Dictionary<BaseBoat, DateTime> BoatTable { get { return m_BoatTable; } }
public static bool RestrictBoats
{
get { return m_RestrictBoats; }
set
{
m_RestrictBoats = value;
if (value)
{
if (m_Region1 != null)
m_Region1.StartTimer();
if (m_Region2 != null)
m_Region2.StartTimer();
}
else
{
if (m_Region1 != null)
m_Region1.StopTimer();
if (m_Region2 != null)
m_Region2.StopTimer();
}
}
}
public static Rectangle2D[] Bounds { get { return m_Bounds; } }
private static Rectangle2D[] m_Bounds = new Rectangle2D[]
{
new Rectangle2D(4529, 2296, 45, 112),
};
public SeaMarketRegion(XmlElement xml, Map map, Region parent)
: base(xml, map, parent)
{
}
public override void OnRegister()
{
if (m_Region1 == null)
{
m_Region1 = this;
}
else if (m_Region2 == null)
{
m_Region2 = this;
}
}
public override bool CheckTravel(Mobile traveller, Point3D p, TravelCheckType type)
{
switch (type)
{
case TravelCheckType.RecallTo:
case TravelCheckType.GateTo:
{
return BaseBoat.FindBoatAt(p, Map) != null;
}
case TravelCheckType.Mark:
{
return false;
}
}
return base.CheckTravel(traveller, p, type);
}
public override bool AllowHousing(Mobile from, Point3D p)
{
return false;
}
#region Pirate Blabbing
public static Dictionary<Mobile, DateTime> m_PirateBlabTable = new Dictionary<Mobile, DateTime>();
private static readonly TimeSpan BlabDuration = TimeSpan.FromSeconds(60);
public static void TryPirateBlab(Mobile from, Mobile npc)
{
if (m_PirateBlabTable.ContainsKey(from) && m_PirateBlabTable[from] > DateTime.UtcNow || BountyQuestSpawner.Bounties.Count <= 0)
return;
//Make of list of bounties on their map
List<Mobile> bounties = new List<Mobile>();
foreach (Mobile mob in BountyQuestSpawner.Bounties.Keys)
{
if (mob.Map == from.Map && mob is PirateCaptain && !bounties.Contains(mob))
bounties.Add(mob);
}
if (bounties.Count > 0)
{
Mobile bounty = bounties[Utility.Random(bounties.Count)];
if (bounty != null)
{
PirateCaptain capt = (PirateCaptain)bounty;
int xLong = 0, yLat = 0;
int xMins = 0, yMins = 0;
bool xEast = false, ySouth = false;
Point3D loc = capt.Location;
Map map = capt.Map;
string locArgs;
string combine;
if (Sextant.Format(loc, map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth))
locArgs = String.Format("{0}°{1}'{2},{3}°{4}'{5}", yLat, yMins, ySouth ? "S" : "N", xLong, xMins, xEast ? "E" : "W");
else
locArgs = "?????";
combine = String.Format("{0}\t{1}", capt.PirateName > -1 ? String.Format("#{0}", capt.PirateName) : capt.Name, locArgs);
int cliloc = Utility.RandomMinMax(1149856, 1149865);
npc.SayTo(from, cliloc, combine);
m_PirateBlabTable[from] = DateTime.UtcNow + BlabDuration;
}
}
ColUtility.Free(bounties);
}
public static void CheckBlab_Callback()
{
CheckBabble(m_Region1);
CheckBabble(m_Region2);
CheckBabble(TokunoDocksRegion.Instance);
}
public static void CheckBabble(Region r)
{
if (r == null)
return;
foreach (var player in r.GetEnumeratedMobiles().Where(p => p is PlayerMobile &&
p.Alive /*&&
QuestHelper.GetQuest((PlayerMobile)p, typeof(ProfessionalBountyQuest)) != null*/))
{
IPooledEnumerable eable = player.GetMobilesInRange(4);
foreach (Mobile mob in eable)
{
if (mob is BaseVendor || mob is MondainQuester || mob is GalleonPilot)
{
TryPirateBlab(player, mob);
break;
}
}
eable.Free();
}
}
#endregion
#region Boat Restriction
public void StartTimer()
{
if (m_Timer != null)
m_Timer.Stop();
m_Timer = new InternalTimer(this);
m_Timer.Start();
}
public void StopTimer()
{
if (m_Timer != null)
m_Timer.Stop();
m_Timer = null;
}
public List<BaseBoat> GetBoats()
{
List<BaseBoat> list = new List<BaseBoat>();
foreach (BaseBoat boat in this.GetEnumeratedMultis().OfType<BaseBoat>())
list.Add(boat);
return list;
}
public void OnTick()
{
if (!m_RestrictBoats)
{
StopTimer();
return;
}
List<BaseBoat> boats = GetBoats();
List<BaseBoat> toRemove = new List<BaseBoat>();
foreach (KeyValuePair<BaseBoat, DateTime> kvp in m_BoatTable)
{
BaseBoat boat = kvp.Key;
DateTime moveBy = kvp.Value;
if (boat == null || !boats.Contains(boat) || boat.Deleted)
toRemove.Add(boat);
else if (DateTime.UtcNow >= moveBy && KickBoat(boat))
toRemove.Add(boat);
else
{
if (boat.Owner != null && boat.Owner.NetState != null)
{
TimeSpan ts = moveBy - DateTime.UtcNow;
if ((int)ts.TotalMinutes <= 10)
{
int rem = Math.Max(1, (int)ts.TotalMinutes);
boat.Owner.SendLocalizedMessage(1149787 + (rem - 1));
}
}
}
}
foreach (BaseBoat boat in boats)
{
if (!m_BoatTable.ContainsKey(boat) && !boat.IsMoving && boat.Owner != null && boat.Owner.AccessLevel == AccessLevel.Player)
AddToTable(boat);
}
foreach (BaseBoat b in toRemove)
m_BoatTable.Remove(b);
ColUtility.Free(toRemove);
ColUtility.Free(boats);
}
public void AddToTable(BaseBoat boat)
{
if (m_BoatTable.ContainsKey(boat))
return;
m_BoatTable.Add(boat, DateTime.UtcNow + KickDuration);
if (boat.Owner != null && boat.Owner.NetState != null)
boat.Owner.SendMessage("You can only dock your boat here for {0} minutes.", (int)KickDuration.TotalMinutes);
}
private Rectangle2D[] m_KickLocs = new Rectangle2D[]
{
new Rectangle2D(m_Bounds[0].X - 100, m_Bounds[0].X - 100, 200 + m_Bounds[0].Width, 100),
new Rectangle2D(m_Bounds[0].X - 100, m_Bounds[0].Y, 100, m_Bounds[0].Height + 100),
new Rectangle2D(m_Bounds[0].X, m_Bounds[0].Y + m_Bounds[0].Height, m_Bounds[0].Width + 100, 100),
new Rectangle2D(m_Bounds[0].X + m_Bounds[0].Width, m_Bounds[0].Y, 100, m_Bounds[0].Height),
};
public bool KickBoat(BaseBoat boat)
{
if (boat == null || boat.Deleted)
return false;
for (int i = 0; i < 25; i++)
{
Rectangle2D rec = m_KickLocs[Utility.Random(m_KickLocs.Length)];
int x = Utility.RandomMinMax(rec.X, rec.X + rec.Width);
int y = Utility.RandomMinMax(rec.Y, rec.Y + rec.Height);
int z = boat.Z;
Point3D p = new Point3D(x, y, z);
if (boat.CanFit(p, boat.Map, boat.ItemID))
{
boat.Teleport(x - boat.X, y - boat.Y, z - boat.Z);
if (boat.Owner != null && boat.Owner.NetState != null)
boat.SendMessageToAllOnBoard(1149785); //A strong tide comes and carries your boat to deeper water.
return true;
}
}
return false;
}
private class InternalTimer : Timer
{
private SeaMarketRegion m_Region;
public InternalTimer(SeaMarketRegion reg)
: base(TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1))
{
m_Region = reg;
}
protected override void OnTick()
{
if (m_Region != null)
m_Region.OnTick();
}
}
public static void StartTimers_Callback()
{
RestrictBoats = m_RestrictBoats;
m_BlabTimer = Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), new TimerCallback(CheckBlab_Callback));
m_BlabTimer.Priority = TimerPriority.OneSecond;
}
#endregion
public static void Save(GenericWriter writer)
{
writer.Write((int)0);
writer.Write(m_RestrictBoats);
}
public static void Load(GenericReader reader)
{
int version = reader.ReadInt();
m_RestrictBoats = reader.ReadBool();
Timer.DelayCall(TimeSpan.FromSeconds(30), new TimerCallback(StartTimers_Callback));
}
public static void GetBoatInfo_OnCommand(CommandEventArgs e)
{
List<BaseBoat> boats = new List<BaseBoat>(m_Region1.BoatTable.Keys);
List<DateTime> times = new List<DateTime>(m_Region1.BoatTable.Values);
e.Mobile.SendMessage("========Boat Info for Felucca as Follows===========");
e.Mobile.SendMessage("Boats: {0}", boats.Count);
if (!m_RestrictBoats)
e.Mobile.SendMessage("Boat restriction is currenlty disabled.");
Console.WriteLine("========Boat Info as Follows===========");
Console.WriteLine("Boats: {0}", boats.Count);
if (!m_RestrictBoats)
Console.WriteLine("Boat restriction is currenlty disabled.");
for (int i = 0; i < boats.Count; i++)
{
BaseBoat boat = boats[i];
if (boat == null || boat.Deleted)
continue;
e.Mobile.SendMessage("Boat Name: {0}; Boat Owner: {1}; Expires: {2}", boat.ShipName, boat.Owner, times[i]);
Console.WriteLine("Boat Name: {0}; Boat Owner: {1}; Expires: {2}", boat.ShipName, boat.Owner, times[i]);
}
boats.Clear();
times.Clear();
boats = new List<BaseBoat>(m_Region2.BoatTable.Keys);
times = new List<DateTime>(m_Region2.BoatTable.Values);
e.Mobile.SendMessage("========Boat Info for Trammel as Follows===========");
e.Mobile.SendMessage("Boats: {0}", boats.Count);
if (!m_RestrictBoats)
e.Mobile.SendMessage("Boat restriction is currenlty disabled.");
Console.WriteLine("========Boat Info as Follows===========");
Console.WriteLine("Boats: {0}", boats.Count);
if (!m_RestrictBoats)
Console.WriteLine("Boat restriction is currenlty disabled.");
for (int i = 0; i < boats.Count; i++)
{
BaseBoat boat = boats[i];
if (boat == null || boat.Deleted)
continue;
e.Mobile.SendMessage("Boat Name: {0}; Boat Owner: {1}; Expires: {2}", boat.ShipName, boat.Owner, times[i]);
Console.WriteLine("Boat Name: {0}; Boat Owner: {1}; Expires: {2}", boat.ShipName, boat.Owner, times[i]);
}
}
public static void SetRestriction_OnCommand(CommandEventArgs e)
{
if (m_RestrictBoats)
{
RestrictBoats = false;
e.Mobile.SendMessage("Boat restriction in the sea market is no longer active.");
}
else
{
RestrictBoats = true;
e.Mobile.SendMessage("Boat restriction in the sea market is now active.");
}
}
}
}