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 m_BoatTable = new Dictionary(); public Dictionary 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 m_PirateBlabTable = new Dictionary(); 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 bounties = new List(); 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 GetBoats() { List list = new List(); foreach (BaseBoat boat in this.GetEnumeratedMultis().OfType()) list.Add(boat); return list; } public void OnTick() { if (!m_RestrictBoats) { StopTimer(); return; } List boats = GetBoats(); List toRemove = new List(); foreach (KeyValuePair 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 boats = new List(m_Region1.BoatTable.Keys); List times = new List(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(m_Region2.BoatTable.Keys); times = new List(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."); } } } }