using System; using System.Collections.Generic; using System.Linq; using Server; using Server.ContextMenus; using Server.Mobiles; namespace Server.Engines.VoidPool { [PropertyObject] public class Level3Spawner : ISpawner { private bool _Active; [CommandProperty(AccessLevel.GameMaster)] public VoidPoolController Controller { get; set; } public List Spawns { get; set; } [CommandProperty(AccessLevel.GameMaster)] public int EntryCount { get { return Spawns == null ? 0 : Spawns.Count; } } [CommandProperty(AccessLevel.GameMaster)] public bool Active { get { return _Active; } set { bool active = _Active; if (value != active) { _Active = value; if (!_Active) { Deactivate(); } else { if (Spawns != null) { Deactivate(false); } LoadSpawns(); StartSpawn(); } } } } #region ISpawner Stuff public bool UnlinkOnTaming { get { return true; } } public Point3D HomeLocation { get { return Point3D.Zero; } } public int HomeRange { get { return 20; } } public void Remove(ISpawnable spawnable) { RemoveFromSpawner(spawnable); } public virtual void GetSpawnProperties(ISpawnable spawn, ObjectPropertyList list) { } public virtual void GetSpawnContextEntries(ISpawnable spawn, Mobile user, List list) { } #endregion public Level3Spawner(VoidPoolController controller) { Controller = controller; Timer.DelayCall(TimeSpan.FromSeconds(1), () => { Active = true; }); } public override string ToString() { return "..."; } public void LoadSpawns() { if (Spawns != null) Spawns.Clear(); Spawns = new List(); Spawns.Add(new SpawnEntry(this, new Rectangle2D[] { new Rectangle2D(5564, 1888, 26, 31) })); Spawns.Add(new SpawnEntry(this, new Rectangle2D[] { new Rectangle2D(5554, 1888, 8, 28) })); Spawns.Add(new SpawnEntry(this, new Rectangle2D[] { new Rectangle2D(5596, 1888, 8, 28) })); Spawns.Add(new SpawnEntry(this, new Rectangle2D[] { new Rectangle2D(5536, 1876, 8, 8), new Rectangle2D(5552, 1840, 11, 42) })); Spawns.Add(new SpawnEntry(this, new Rectangle2D[] { new Rectangle2D(5600, 1860, 8, 8), new Rectangle2D(5596, 1872, 15, 12) })); Spawns.Add(new SpawnEntry(this, new Rectangle2D[] { new Rectangle2D(5608, 1832, 15, 15), new Rectangle2D(5616, 1848, 11, 34) })); Spawns.Add(new SpawnEntry(this, new Rectangle2D[] { new Rectangle2D(5568, 1852, 22, 14) }, 15)); Spawns.Add(new SpawnEntry(this, new Rectangle2D[] { new Rectangle2D(5568, 1824, 22, 11) })); Spawns.Add(new SpawnEntry(this, new Rectangle2D[] { new Rectangle2D(5501, 1800, 42, 19) }, 15)); } public void RemoveFromSpawner(ISpawnable spawnable) { BaseCreature bc = spawnable as BaseCreature; if (bc != null) { var entry = FindEntryFor(bc); if (entry != null) { entry.Spawn.Remove(bc); bc.Spawner = null; if (entry.CurrentCount == 0) { Timer.DelayCall(TimeSpan.FromMinutes(Utility.RandomMinMax(2, 5)), en => { Reset(en); }, entry); } List list = bc.GetLootingRights(); foreach (var ds in list) { if (ds.m_HasRight) { int points = (bc.Fame / 998) / list.Count; if (points > 0) { AddToOverallTotal(ds.m_Mobile, points); } } } } } } public void AddToOverallTotal(Mobile m, int points) { var stats = VoidPoolStats.GetStats(Controller); if (stats != null) { if (!stats.OverallTotal.ContainsKey(m)) stats.OverallTotal[m] = points; else stats.OverallTotal[m] += points; } } public void Reset(SpawnEntry entry) { if (!Active) return; var type = entry.SpawnType; do { entry.SpawnType = (VoidType)Utility.RandomMinMax(0, 4); } while (entry.SpawnType == type); entry.DoSpawn(); } public void StartSpawn() { foreach (var entry in Spawns) { entry.SpawnType = (VoidType)Utility.RandomMinMax(0, 4); entry.DoSpawn(); } } public SpawnEntry FindEntryFor(BaseCreature bc) { return Spawns.FirstOrDefault(sp => sp.Spawn.Contains(bc)); } public void Deactivate(bool deactivate = true) { if (deactivate) { Active = false; } if (Spawns != null) { foreach (var entry in Spawns) { var list = new List(); foreach (var bc in entry.Spawn) { list.Add(bc); } foreach (var creature in list) creature.Delete(); ColUtility.Free(list); } Spawns.Clear(); } } public Level3Spawner(GenericReader reader, VoidPoolController controller) { Controller = controller; LoadSpawns(); int version = reader.ReadInt(); switch (version) { case 2: case 1: { if (version == 1) Active = controller.Active; _Active = reader.ReadBool(); } goto case 0; case 0: { int count = reader.ReadInt(); for (int i = 0; i < count; i++) { Spawns[i].Deserialize(reader); } } break; } } public void Serialize(GenericWriter writer) { writer.Write(2); writer.Write(_Active); writer.Write(Spawns == null ? 0 : Spawns.Count); if (Spawns != null) { for (int i = 0; i < Spawns.Count; i++) { Spawns[i].Serialize(writer); } } } public class SpawnEntry { public Level3Spawner Spawner { get; set; } public Rectangle2D[] Bounds { get; private set; } public int MaxCount { get; private set; } public int CurrentCount { get { return Spawn.Count; } } public VoidType SpawnType { get; set; } public List Spawn { get; set; } public SpawnEntry(Level3Spawner spawner, Rectangle2D[] bounds, int maxCount = 8) { Bounds = bounds; MaxCount = maxCount; Spawner = spawner; Spawn = new List(); } public void DoSpawn() { if (Spawner == null || Spawner.Controller == null || Spawner.Controller.Map == null || !Spawner.Active) { return; } Map map = Spawner.Controller.Map; Type[] types = VoidPoolController.SpawnTable[(int)SpawnType]; for (int i = 0; i < MaxCount; i++) { BaseCreature bc = Activator.CreateInstance(types[Utility.Random(types.Length)], Utility.RandomMinMax(5, 15), false) as BaseCreature; if (bc != null) { Rectangle2D rec = Bounds[Utility.Random(Bounds.Length)]; Point3D p = Point3D.Zero; for(int j = 0; j < 50; j++) { p = map.GetRandomSpawnPoint(rec); if (map.CanSpawnMobile(p)) break; } if (p != Point3D.Zero) { bc.Spawner = Spawner; bc.Home = p; bc.RangeHome = 20; bc.OnBeforeSpawn(p, map); bc.MoveToWorld(p, map); bc.OnAfterSpawn(); Spawn.Add(bc); } else { bc.Delete(); } } } } public void Serialize(GenericWriter writer) { writer.Write(0); writer.Write(Spawn.Count); Spawn.ForEach(s => writer.Write(s)); } public void Deserialize(GenericReader reader) { int version = reader.ReadInt(); Spawn = new List(); int count = reader.ReadInt(); for (int i = 0; i < count; i++) { BaseCreature bc = reader.ReadMobile() as BaseCreature; if (bc != null) { bc.Spawner = Spawner; Spawn.Add(bc); } } if (Spawn.Count == 0) Timer.DelayCall(DoSpawn); } } } }