using Server.Commands; using Server.Engines.Quests; using Server.Gumps; using Server.Items; using Server.Mobiles; using Server.Multis; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using Server.Regions; /* This script has a purpose, and please adhere to the advice before adding versions. * This is used for modifying, removing, adding existing spawners, etc for existing shards, * used for modifying, removing, adding existing spawners, etc for existing shards. * As this is a collaborative effort for ServUO, it's important that any modifications to * existing shards be handled for new shards. For example, if your swapping out some spawners, * common practice will be to edit the spawner files for fresh-loaded servers. Please refer to * ServUO.com community with any questions or concerns. */ namespace Server { public class SpawnerPersistence { [Flags] public enum SpawnerVersion { None = 0x00000000, Initial = 0x00000001, Sphinx = 0x00000002, IceHoundRemoval = 0x00000004, PaladinAndKrakin = 0x00000008, TrinsicPaladins = 0x00000010, HonestyItems = 0x00000020, TramKhaldun = 0x00000040, FixAddonDeco = 0x00000080, LifeStealers = 0x00000100, LootNerf2 = 0x00000200, RemoveUnused = 0x00000400, RemoveUnused2 = 0x00000800, RemoveTeleporters = 0x00001000, DestardSpawners = 0x00002000, DoomSpawners = 0x00004000 } public static string FilePath = Path.Combine("Saves/Misc", "SpawnerPresistence.bin"); private static bool _FirstRun = true; private static int _Version; public static int Version => _Version; public static SpawnerVersion VersionFlag { get; set; } private static bool _SpawnsConverted; public static bool SpawnsConverted => _SpawnsConverted; public static void Configure() { EventSink.WorldSave += OnSave; EventSink.WorldLoad += OnLoad; } public static void Initialize() { if (!_FirstRun) { CheckVersion(); } else if (_Version == 0) // new server, no need to run the new stuff. { // This way, fresh servers won't duplicate any spawners that should have already been adjusted for a fresh server foreach (int i in Enum.GetValues(typeof(SpawnerVersion))) { if (i == 0x00000000) continue; VersionFlag |= (SpawnerVersion)i; } } #region Commands CommandSystem.Register("ConvertSpawners", AccessLevel.Administrator, e => { string str = "By selecting OK, you will wipe all XmlSpawners that were placed via World Load, and will replace " + "with standard spawners. Any existing spawner with special symbols, such as , <> / will not be converted. " + "Be advised, this process will take several minutes to complete."; if (_SpawnsConverted) str += "

You have already ran this conversion. Run Again?"; e.Mobile.SendGump(new WarningGump(1019005, 30720, str, 0xFFFFFF, 400, 300, (from, ok, state) => { if (ok) { from.SendMessage("Stand by while spawners are converted. This may take a few minutes..."); Timer.DelayCall(ConvertXmlToSpawners); } }, null, true)); }); CommandSystem.Register("RevertXmlSpawners", AccessLevel.Administrator, e => { string str = "By selecting OK, you will wipe all XmlSpawners that were left over from conversion to " + "standard spawners. All standard spawners will be deleted, and xmlspawners will be re-added. " + "Be advised, this process will take several minutes to complete."; e.Mobile.SendGump(new WarningGump(1019005, 30720, str, 0xFFFFFF, 400, 300, (from, ok, state) => { if (ok) { from.SendMessage("Stand by while spawners are converted back to XmlSpawners. This may take a few minutes..."); Timer.DelayCall(() => RevertToXmlSpawners(e.Mobile)); } }, null, true)); }); CommandSystem.Register("WipeAllXmlSpawners", AccessLevel.Administrator, e => { WipeSpawnersFromFile(); }); #endregion } public static void OnSave(WorldSaveEventArgs e) { Persistence.Serialize( FilePath, writer => { writer.Write(12); writer.Write((int)VersionFlag); writer.Write(false); writer.Write(_SpawnsConverted); }); } public static void OnLoad() { Persistence.Deserialize( FilePath, reader => { _Version = reader.ReadInt(); if (_Version > 10) VersionFlag = (SpawnerVersion)reader.ReadInt(); if (_Version > 2) { _FirstRun = reader.ReadBool(); _SpawnsConverted = reader.ReadBool(); } }); } /// /// Checks version, and calls code appropriately. Version 10 implements SpawnerFlag so servers don't miss out and skip versions. /// After this point, there is no need to increase version anymore unless any changes /// public static void CheckVersion() { switch (_Version) { case 12: case 11: if ((VersionFlag & SpawnerVersion.DoomSpawners) == 0) { UpdateDoomSpawners(); VersionFlag |= SpawnerVersion.DoomSpawners; } if ((VersionFlag & SpawnerVersion.DestardSpawners) == 0) { UpdateDestardSpawners(); VersionFlag |= SpawnerVersion.DestardSpawners; } if ((VersionFlag & SpawnerVersion.RemoveTeleporters) == 0) { RemoveTeleporters(); VersionFlag |= SpawnerVersion.RemoveTeleporters; } if ((VersionFlag & SpawnerVersion.RemoveUnused2) == 0) { RemoveUnused2(); VersionFlag |= SpawnerVersion.RemoveUnused2; } if ((VersionFlag & SpawnerVersion.RemoveUnused) == 0) { RemoveUnused(); VersionFlag |= SpawnerVersion.RemoveUnused; } if ((VersionFlag & SpawnerVersion.LootNerf2) == 0) { LootNerf2(); VersionFlag |= SpawnerVersion.LootNerf2; } if ((VersionFlag & SpawnerVersion.LifeStealers) == 0) { SpawnLifeStealers(); VersionFlag |= SpawnerVersion.LifeStealers; } if ((VersionFlag & SpawnerVersion.FixAddonDeco) == 0) { FixAddonDeco(); VersionFlag |= SpawnerVersion.FixAddonDeco; } if ((VersionFlag & SpawnerVersion.TramKhaldun) == 0) { GenerateTramKhaldun(); VersionFlag |= SpawnerVersion.TramKhaldun; } if ((VersionFlag & SpawnerVersion.HonestyItems) == 0) { ConvertHonestyItems(); VersionFlag |= SpawnerVersion.HonestyItems; } if ((VersionFlag & SpawnerVersion.TrinsicPaladins) == 0) { SpawnTrinsicPaladins(); VersionFlag |= SpawnerVersion.TrinsicPaladins; } if ((VersionFlag & SpawnerVersion.PaladinAndKrakin) == 0) { RemovePaladinsAndKrakens(); VersionFlag |= SpawnerVersion.PaladinAndKrakin; } if ((VersionFlag & SpawnerVersion.IceHoundRemoval) == 0) { RemoveIceHounds(); VersionFlag |= SpawnerVersion.IceHoundRemoval; } if ((VersionFlag & SpawnerVersion.Sphinx) == 0) { AddSphinx(); VersionFlag |= SpawnerVersion.Sphinx; } goto case 10; case 10: if ((VersionFlag & SpawnerVersion.Initial) == 0) VersionFlag |= SpawnerVersion.Initial; break; case 9: LoadFromXmlSpawner("Spawns/twistedweald.xml", Map.Ilshenar, "TwistedWealdTrigger1"); LoadFromXmlSpawner("Spawns/twistedweald.xml", Map.Ilshenar, "TwistedWealdTrigger2"); LoadFromXmlSpawner("Spawns/twistedweald.xml", Map.Ilshenar, "TwistedWealdTrigger3"); LoadFromXmlSpawner("Spawns/twistedweald.xml", Map.Ilshenar, "TwistedWealdTrigger4"); ReplaceUnderworldVersion9(); break; case 8: ReplaceSolenHivesVersion8(); break; case 7: case 6: ReplaceTwistedWealdVersion7(); RunicReforging.ItemNerfVersion6(); break; case 5: HonestyItemsVersion5(); break; case 4: BrigandsVersion4(); break; case 3: FixCampSpawnersVersion3(); break; case 2: // Nothing break; case 1: RemoveSpawnVersion1(); break; case 0: CheckSmartSpawn(typeof(BaseVendor), true); CheckQuestQuesters(); break; } } public static void ToConsole(string str, ConsoleColor color = ConsoleColor.Green) { Utility.PushColor(color); Console.WriteLine("[Spawner Persistence v{0}] {1}", _Version.ToString(), str); Utility.PopColor(); } #region Update Doom Spawners public static void UpdateDoomSpawners() { ReplaceSpawnersByRegionName("Doom", Map.Malas, "doom"); } #endregion #region Update Destard Spawners public static void UpdateDestardSpawners() { ReplaceSpawnersByRegionName("Destard", Map.Trammel, "Destard"); ReplaceSpawnersByRegionName("Destard", Map.Felucca, "Destard"); } #endregion #region Remove Teleporters public static void RemoveTeleporters() { WeakEntityCollection.Delete("tel"); var delCount = 0; Timer.DelayCall(TimeSpan.FromSeconds(1), () => { IPooledEnumerable eable = null; foreach (var reg in Region.Regions.OfType()) { foreach (var rec in reg.Area) { eable = reg.Map.GetItemsInBounds(new Rectangle2D(rec.Start.X, rec.Start.Y, rec.Width, rec.Height)); foreach (var tele in eable.OfType()) { delCount++; tele.Delete(); } } } ToConsole(string.Format("{0} additional Teleporters deleted.", delCount)); }); } #endregion #region Remove Unused 2 public static void RemoveUnused2() { Remove("xmlquestnpc"); Remove("HiddenFigure"); Remove("JedahEntille"); Remove("EnshroudedFigure"); Remove("MilitiaFighter"); Remove("Seekerofadventure"); Remove("Noble"); Remove("peasant"); Remove("orderguard"); Remove("Chaosguard"); Remove("bridegroom"); Remove("merchant"); Remove("baseescortable"); } #endregion #region Remove Unused public static void RemoveUnused() { Remove("Emino"); Remove("FierceDragon"); Remove("HaochisGuardsman"); Remove("Mardoth"); Remove("DeadlyImp"); Remove("Relnia"); Remove("Zoel"); Remove("Horus"); Remove("Haochi"); } #endregion #region Loot Nerf 2 public static void LootNerf2() { RunicReforging.LootNerf2(); } #endregion #region Spawn Lifestealers public static void SpawnLifeStealers() { LoadFromXmlSpawner("Spawns/termur.xml", Map.TerMur, "LifeStealer"); } #endregion #region Addon Decoraction Fix public static void FixAddonDeco() { Type t = typeof(AddonComponent); Decorate.GenerateRestricted("deco", "Data/Decoration/Britannia", t, true, Map.Trammel, Map.Felucca); Decorate.GenerateRestricted("deco", "Data/Decoration/Trammel", t, true, Map.Trammel); Decorate.GenerateRestricted("deco", "Data/Decoration/Felucca", t, true, Map.Felucca); Decorate.GenerateRestricted("deco", "Data/Decoration/Ilshenar", t, true, Map.Ilshenar); Decorate.GenerateRestricted("deco", "Data/Decoration/Malas", t, true, Map.Malas); Decorate.GenerateRestricted("deco", "Data/Decoration/Tokuno", t, true, Map.Tokuno); } #endregion #region Tram Khaldun Generation public static void GenerateTramKhaldun() { Region region = Region.Regions.FirstOrDefault(r => r.Map == Map.Felucca && r.Name == "Khaldun"); if (region != null) { int spawners = 0; int teleporters = 0; foreach (XmlSpawner spawner in region.GetEnumeratedItems().OfType()) { CopyAndPlaceItem(spawner, spawner.Location, Map.Trammel); spawners++; } foreach (Teleporter teleporter in region.GetEnumeratedItems().OfType()) { CopyAndPlaceItem(teleporter, teleporter.Location, Map.Trammel); teleporters++; } ToConsole(string.Format("Copied {0} khaldun spawners, {1} teleporters and placed in trammel!", spawners, teleporters)); } else { ToConsole("No region -Khaldun- Found!", ConsoleColor.Red); } Decorate.GenerateFromFile("deco", Path.Combine("Data/Decoration/Trammel", "khaldun.cfg"), Map.Trammel); KhaldunEntranceAddon entAddon = new KhaldunEntranceAddon(); entAddon.MoveToWorld(new Point3D(6013, 3785, 18), Map.Trammel); KhaldunCampAddon campAddon = new KhaldunCampAddon(); campAddon.MoveToWorld(new Point3D(6003, 3772, 24), Map.Trammel); KhaldunWorkshop workshop = new KhaldunWorkshop(); workshop.MoveToWorld(new Point3D(6020, 3747, 18), Map.Trammel); Teleporter tele = new Teleporter(new Point3D(5571, 1299, 0), Map.Trammel); tele.MoveToWorld(new Point3D(6011, 3787, 23), Map.Trammel); tele = new Teleporter(new Point3D(5571, 1299, 0), Map.Trammel); tele.MoveToWorld(new Point3D(6012, 3787, 23), Map.Trammel); tele = new Teleporter(new Point3D(5572, 1299, 0), Map.Trammel); tele.MoveToWorld(new Point3D(6013, 3787, 23), Map.Trammel); tele = new Teleporter(new Point3D(5572, 1299, 0), Map.Trammel); tele.MoveToWorld(new Point3D(6014, 3787, 23), Map.Trammel); } #endregion #region Honesty Item Conversion public static void ConvertHonestyItems() { int convert = 0; foreach (Item item in World.Items.Values.Where(i => i.HonestyItem)) { if (!item.HasSocket()) { item.AttachSocket(new HonestyItemSocket()); convert++; } } ToConsole(string.Format("Converted {0} honesty items and attached Honesty Item Socket!", convert)); } #endregion #region Trinny Paladins public static void SpawnTrinsicPaladins() { LoadFromXmlSpawner("Spawns/trammel.xml", Map.Trammel, "TrinsicPaladinSpawner"); LoadFromXmlSpawner("Spawns/felucca.xml", Map.Felucca, "TrinsicPaladinSpawner"); } #endregion #region Remove Paladins And Krakens public static void RemovePaladinsAndKrakens() { Remove("HirePaladin"); Remove("Kraken", sp => !Region.Find(sp.Location, sp.Map).IsPartOf("Shame")); ToConsole("Paladins and Krakens removed from spawners."); } #endregion #region Remove Ice Hounds public static void RemoveIceHounds() { Remove("icehound"); ToConsole("Ice Hounds removed from spawners."); } #endregion #region Version 11 public static void AddSphinx() { Engines.GenerateForgottenPyramid.Generate(null); ToConsole("Generated Fortune Sphinx."); } #endregion #region Version 9 public static void ReplaceUnderworldVersion9() { ReplaceSpawnersByRegionName("Underworld", Map.TerMur, "underworld"); ReplaceSpawnersByRectangle(new Rectangle2D(5640, 1776, 295, 263), Map.Trammel, null); ReplaceSpawnersByRectangle(new Rectangle2D(5640, 1776, 295, 263), Map.Felucca, "solenhives"); QuestHintItem hint = new DuganMissingQuestCorpse(); hint.MoveToWorld(new Point3D(1038, 1182, -52), Map.TerMur); Static item = new Static(7400); item.MoveToWorld(new Point3D(1040, 1181, -53), Map.TerMur); item = new Static(7390); item.MoveToWorld(new Point3D(1041, 1185, -50), Map.TerMur); item = new Static(7390); item.MoveToWorld(new Point3D(1036, 1185, -52), Map.TerMur); hint = new FlintLostLogbookHint(); hint.MoveToWorld(new Point3D(1044, 976, -30), Map.TerMur); hint = new FlintLostBarrelHint(); hint.MoveToWorld(new Point3D(1043, 1003, -43), Map.TerMur); hint = new FlintLostBarrelHint(); hint.MoveToWorld(new Point3D(1048, 1027, -32), Map.TerMur); GenerateUnderworldRooms.GenerateRevealTiles(); ToConsole("Placed Quest Statics."); } #endregion #region Version 8 public static void ReplaceSolenHivesVersion8() { ReplaceSpawnersByRectangle(new Rectangle2D(5640, 1776, 295, 263), Map.Trammel, null); ReplaceSpawnersByRectangle(new Rectangle2D(5640, 1776, 295, 263), Map.Felucca, "solenhives"); } #endregion #region Version 6 & 7 public static void ReplaceTwistedWealdVersion7() { ReplaceSpawnersByRegionName("Twisted Weald", Map.Ilshenar, "twistedweald"); } #endregion #region Version 5 public static void HonestyItemsVersion5() { Timer.DelayCall(TimeSpan.FromSeconds(10), () => { int count = 0; foreach (Item item in World.Items.Values.Where(i => i.HonestyItem && !ItemFlags.GetTaken(i))) { RunicReforging.GenerateRandomItem(item, 0, 100, 1000); count++; } ToConsole(string.Format("Honesty items given magical properties: {0}", count.ToString())); }); } #endregion #region Version 4 public static void BrigandsVersion4() { Replace("humanbrigand", "brigand", null); Replace("humanbrigandcamp", "brigandcamp", null); } #endregion #region Version 3 private static void FixCampSpawnersVersion3() { ActionOnSpawner(typeof(BaseCamp), null, null, null, spawner => { if (spawner is XmlSpawner) { XmlSpawner s = spawner as XmlSpawner; s.MinDelay = TimeSpan.FromMinutes(5); s.MaxDelay = TimeSpan.FromMinutes(10); } else if (spawner is Spawner) { Spawner s = spawner as Spawner; s.MinDelay = TimeSpan.FromMinutes(5); s.MaxDelay = TimeSpan.FromMinutes(10); } }, true); } #endregion #region Version 1 private static void RemoveSpawnVersion1() { Remove("SeaHorse"); Delete("Valem"); } #endregion #region Version 0 private static Dictionary QuestQuesterTypes; /// /// Any quests that have questers as null, will assign the quester. Some quests don't have questers... /// public static void CheckQuestQuesters() { ToConsole("Assigning Questers where null..."); QuestQuesterTypes = new Dictionary(); foreach (MondainQuester quester in World.Mobiles.Values.OfType()) { Type t = quester.GetType(); if (QuestQuesterTypes.ContainsKey(t)) continue; Type[] quests = quester.Quests; if (quests != null && quests.Length > 0) QuestQuesterTypes[t] = quests; } foreach (BaseQuestItem item in World.Items.Values.OfType()) { Type t = item.GetType(); if (QuestQuesterTypes.ContainsKey(t)) continue; Type[] quests = item.Quests; if (quests != null && quests.Length > 0) QuestQuesterTypes[t] = quests; } int count = 0; foreach (PlayerMobile pm in World.Mobiles.Values.OfType()) { foreach (BaseQuest quest in pm.Quests.Where(q => q.QuesterType == null)) { foreach (KeyValuePair kvp in QuestQuesterTypes) { if (quest.QuesterType != null) break; foreach (Type type in kvp.Value) { if (type == quest.GetType()) { quest.QuesterType = kvp.Key; count++; break; } } } } } ToConsole(string.Format("Quester Re-assignment: {0} quests re-assigned quester type. Some quester types may still be null. These quests will need to be quit.", count.ToString()), ConsoleColor.DarkRed); } /// /// Disables SmartSpawning on XmlSpawners for any spawners that have paramater 'check' as a spawn object type /// /// System.Type to look for in SpawnObject lines /// Can the spawn object type derive from check? private static void CheckSmartSpawn(Type check, bool subclasses) { int count = 0; List spawners = World.Items.Values.OfType().Where(s => s.SmartSpawning).ToList(); foreach (XmlSpawner spawner in spawners) { if (CheckSmartSpawn(spawner, check, subclasses)) count++; } ColUtility.Free(spawners); ToConsole(string.Format("Smart Spawn Removal: {0} spawners [type {1}] smart spawning disabled.", count.ToString(), check.Name)); } private static bool CheckSmartSpawn(XmlSpawner spawner, Type check, bool subclasses) { foreach (XmlSpawner.SpawnObject obj in spawner.SpawnObjects) { if (obj.TypeName != null) { Type t = ScriptCompiler.FindTypeByName(BaseXmlSpawner.ParseObjectType(obj.TypeName)); if (t != null && (t == check || (subclasses && t.IsSubclassOf(check)))) { spawner.SmartSpawning = false; if (spawner.CurrentCount == 0) spawner.DoRespawn = true; return true; } } } return false; } #endregion /// /// Deletes the entire spawner if 'current' if found as an spawn object /// /// public static void Delete(string current) { List toDelete = new List(); foreach (XmlSpawner spawner in World.Items.Values.OfType()) { foreach (XmlSpawner.SpawnObject obj in spawner.SpawnObjects) { if (obj == null || obj.TypeName == null) continue; string typeName = obj.TypeName.ToLower(); string lookingFor = current.ToLower(); if (typeName != null && typeName.IndexOf(lookingFor) >= 0) { toDelete.Add(spawner); break; } } } foreach (XmlSpawner spawner in toDelete) { spawner.Delete(); } ToConsole(string.Format("Spawner Deletion: deleted {0} spawners containing -{1}-.", toDelete.Count.ToString(), current)); ColUtility.Free(toDelete); } /// /// Replaces a certain string value with another in any XmlSpawner SpawnObject line /// /// What we're looing for /// What we're replacing it with /// if the SpawnObject line contains check, we ignore this line altogether public static void Replace(string current, string replace, string check) { int count = 0; foreach (ISpawner spawner in World.Items.Values.OfType()) { if (Replace(spawner, current, replace, check)) count++; } ToConsole(string.Format("Spawn Replacement: {0} spawners replaced [{1} replaced with {2}].", count.ToString(), current, replace)); } /// /// Replaces a certain string value with another in any XmlSpawner SpawnObject line /// /// What we're looing for /// What we're replacing it with /// executes replace only if spawner name contains parameter /// if the SpawnObject line contains check, we ignore this line altogether public static void Replace(string current, string replace, string name, string check) { int count = 0; foreach (ISpawner spawner in World.Items.Values.OfType().Where(s => s is Item && ((Item)s).Name != null && ((Item)s).Name.ToLower().IndexOf(name.ToLower()) >= 0)) { if (Replace(spawner, current, replace, check)) count++; } ToConsole(string.Format("Spawn Replacement: {0} spawners named {1} replaced [{2} replaced with {3}].", count.ToString(), name, current, replace)); } public static bool Replace(ISpawner spwner, string current, string replace, string check) { bool replaced = false; if (spwner is XmlSpawner) { XmlSpawner spawner = (XmlSpawner)spwner; foreach (XmlSpawner.SpawnObject obj in spawner.SpawnObjects) { if (obj == null || obj.TypeName == null) continue; string typeName = obj.TypeName.ToLower(); string lookingFor = current.ToLower(); if (typeName != null && typeName.IndexOf(lookingFor) >= 0) { if (string.IsNullOrEmpty(check) || typeName.IndexOf(check) < 0) { obj.TypeName = typeName.Replace(lookingFor, replace); if (!replaced) replaced = true; } } } } else if (spwner is Spawner) { Spawner spawner = (Spawner)spwner; for (int i = 0; i < spawner.SpawnObjects.Count; i++) { SpawnObject so = spawner.SpawnObjects[i]; string typeName = so.SpawnName.ToLower(); string lookingFor = current.ToLower(); if (typeName != null && typeName.IndexOf(lookingFor) >= 0) { if (string.IsNullOrEmpty(check) || typeName.IndexOf(check) < 0) { so.SpawnName = typeName.Replace(lookingFor, replace); if (!replaced) replaced = true; } } } } return replaced; } /// /// Removes a SpawnerObject string, either the string or entire line /// /// string to remove from line public static void Remove(string toRemove, Func predicate = null) { int count = 0; int deleted = 0; List list = new List(World.Items.Values.OfType()); foreach (XmlSpawner spawner in list) { if (predicate == null || predicate(spawner)) { count += Remove(spawner, toRemove, ref deleted); } } ColUtility.Free(list); ToConsole(string.Format("Spawn Removal: {0} spawn lines removed containing -{1}-. [{2} deleted].", count.ToString(), toRemove, deleted)); } public static int Remove(XmlSpawner spawner, string toRemove, ref int deleted) { List remove = new List(); foreach (XmlSpawner.SpawnObject obj in spawner.SpawnObjects) { if (obj == null || obj.TypeName == null) continue; string typeName = obj.TypeName.ToLower(); string lookingFor = toRemove.ToLower(); if (typeName != null && typeName.IndexOf(lookingFor) >= 0) { remove.Add(obj); } } int count = remove.Count; foreach (XmlSpawner.SpawnObject obj in remove) { spawner.RemoveSpawnObject(obj); foreach (IEntity e in obj.SpawnedObjects.OfType()) { e.Delete(); deleted++; } } ColUtility.Free(remove); return count; } public static void CopyAndPlaceItem(Item oldItem, Point3D p, Map map) { Item newItem = Activator.CreateInstance(oldItem.GetType()) as Item; Dupe.CopyProperties(oldItem, newItem); oldItem.OnAfterDuped(newItem); newItem.MoveToWorld(p, map); if (newItem is XmlSpawner) { ((XmlSpawner)newItem).DoRespawn = true; } else if (newItem is Teleporter) { ((Teleporter)newItem).MapDest = map; } } /// /// performs a pre-specified action (use lamba with action) if the conditions are met /// /// Condition for a specific string in the spawn object line /// Condition for the spawner name /// Condition to prevent action being performed on spawner /// action to be performed, setup in calling method /*public static void ActionOnSpawner(string lineCheck, string nameCheck, string exempt, Action action, bool inherits = false) { int count = 0; if (action != null) { List list = World.Items.Values.OfType().Where(s => nameCheck == null || s.Name.ToLower().IndexOf(nameCheck.ToLower()) >= 0).ToList(); foreach (var spawner in list) { if (ActionOnSpawner(spawner, lineCheck, exempt, action, inherits)) count++; } ColUtility.Free(list); } ToConsole(String.Format("Spawner Action: Performed action to {0} spawners{1}.", count.ToString(), lineCheck != null ? " containing " + lineCheck + "." : ".")); } public static bool ActionOnSpawner(XmlSpawner spawner, string lineCheck, string exempt, Action action, bool inherits) { foreach (var obj in spawner.SpawnObjects.Where(o => !String.IsNullOrEmpty(o.TypeName))) { if (obj == null || obj.TypeName == null) continue; string spawnObject = obj.TypeName.ToLower(); string lookFor = lineCheck != null ? lineCheck.ToLower() : null; if ((lookFor == null || spawnObject.IndexOf(lookFor) >= 0) && (exempt == null || spawnObject.IndexOf(exempt.ToLower()) >= 0)) { action(spawner); return true; } } return false; }*/ /// /// performs a pre-specified action (use lamba with action) if the conditions are met /// /// Condition for a specific string in the spawn object line /// Condition for the spawner name /// Condition to prevent action being performed on spawner /// action to be performed, setup in calling method public static void ActionOnSpawner(Type typeCheck, string lineCheck, string nameCheck, string exempt, Action action, bool inherits = false) { int count = 0; if (action != null) { List list = World.Items.Values.OfType().Where(s => nameCheck == null || (s is Item && ((Item)s).Name != null && ((Item)s).Name.ToLower().IndexOf(nameCheck.ToLower()) >= 0)).ToList(); foreach (ISpawner spawner in list) { if (ActionOnSpawner(spawner, typeCheck, lineCheck, exempt, action, inherits)) count++; } ColUtility.Free(list); } ToConsole(string.Format("Spawner Action: Performed action to {0} spawners{1}", count.ToString(), lineCheck != null ? " containing " + lineCheck + "." : typeCheck != null ? " containing " + typeCheck.Name + "." : ".")); } public static bool ActionOnSpawner(ISpawner spawner, Type typeCheck, string lineCheck, string exempt, Action action, bool inherits) { string[] list = GetSpawnList(spawner); if (list == null) return false; foreach (string str in list) { if (string.IsNullOrEmpty(str)) continue; string spawnObject = str.ToLower(); if (typeCheck != null) { Type t; if (spawner is Spawner) t = ScriptCompiler.FindTypeByName(spawnObject); else t = ScriptCompiler.FindTypeByName(BaseXmlSpawner.ParseObjectType(spawnObject)); if (t == typeCheck || (t != null && inherits && t.IsSubclassOf(typeCheck))) { if (action != null) action(spawner); return true; } } else { string lookFor = lineCheck != null ? lineCheck.ToLower() : null; if ((lookFor == null || spawnObject.IndexOf(lookFor) >= 0) && (exempt == null || spawnObject.IndexOf(exempt.ToLower()) <= 0)) { if (action != null) action(spawner); return true; } } } return false; } private static string[] GetSpawnList(ISpawner spawner) { string[] list = null; if (spawner is XmlSpawner && ((XmlSpawner)spawner).SpawnObjects != null && ((XmlSpawner)spawner).SpawnObjects.Length > 0) { list = ((XmlSpawner)spawner).SpawnObjects.Select(obj => obj.TypeName).ToArray(); } else if (spawner is Spawner && ((Spawner)spawner).SpawnObjects != null && ((Spawner)spawner).SpawnObjects.Count > 0) { List names = ((Spawner)spawner).SpawnObjects; list = new string[names.Count]; for (int i = 0; i < names.Count; i++) { list[i] = names[i].SpawnName; } } return list; } public static void ReplaceSpawnersByRegionName(string region, Map map, string file) { string path = null; if (file != null) { path = string.Format("Spawns/{0}.xml", file); if (!File.Exists(path)) { ToConsole(string.Format("Cannot proceed. {0} does not exist.", file), ConsoleColor.Red); return; } } foreach (Region r in Region.Regions.Where(reg => reg.Map == map && reg.Name == region)) { List list = r.GetEnumeratedItems().Where(i => i is XmlSpawner || i is Spawner).ToList(); foreach (Item item in list) { item.Delete(); } ToConsole(string.Format("Deleted {0} Spawners in {1}.", list.Count, region)); ColUtility.Free(list); } if (path != null) { LoadFromXmlSpawner(path, map); } } public static void ReplaceSpawnersByRectangle(Rectangle2D rec, Map map, string file) { string path = null; if (file != null) { path = string.Format("Spawns/{0}.xml", file); if (!File.Exists(path)) { ToConsole(string.Format("Cannot proceed. {0} does not exist.", file), ConsoleColor.Red); return; } } IPooledEnumerable eable = map.GetItemsInBounds(rec); List list = new List(); foreach (Item item in eable) { if (item is XmlSpawner || item is Spawner) { list.Add(item); } } foreach (Item item in list) item.Delete(); ToConsole(string.Format("Deleted {0} Spawners in {1}.", list.Count, map.ToString())); ColUtility.Free(list); eable.Free(); if (path != null) { LoadFromXmlSpawner(path, map); } } public static void LoadFromXmlSpawner(string location, Map map, string prefix = null) { string filename = XmlSpawner.LocateFile(location); string SpawnerPrefix = prefix == null ? string.Empty : prefix; int processedmaps; int processedspawners; XmlSpawner.XmlLoadFromFile(filename, SpawnerPrefix, null, Point3D.Zero, map, false, 0, false, out processedmaps, out processedspawners); ToConsole(string.Format("Created {0} spawners from {1} with -{2}- prefix.", processedspawners, location, SpawnerPrefix == string.Empty ? "NO" : SpawnerPrefix)); } #region XmlSpawner to Spawner Conversion public static void ConvertXmlToSpawners() { string filename = "Spawns"; if (Directory.Exists(filename) == true) { List files = null; string[] dirs = null; try { files = new List(Directory.GetFiles(filename, "*.xml")); dirs = Directory.GetDirectories(filename); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (dirs != null && dirs.Length > 0) { foreach (string dir in dirs) { try { string[] dirFiles = Directory.GetFiles(dir, "*.xml"); files.AddRange(dirFiles); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } } } ToConsole(string.Format("Found {0} Xmlspawner files for conversion.", files.Count), files != null && files.Count > 0 ? ConsoleColor.Green : ConsoleColor.Red); if (files != null && files.Count > 0) { int converted = 0; int failed = 0; int keep = 0; foreach (string file in files) { FileStream fs = null; try { fs = File.Open(file, FileMode.Open, FileAccess.Read); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (fs == null) { ToConsole(string.Format("Unable to open {0} for loading", filename), ConsoleColor.Red); continue; } DataSet ds = new DataSet("Spawns"); try { ds.ReadXml(fs); } catch { fs.Close(); ToConsole(string.Format("Error reading xml file {0}", filename), ConsoleColor.Red); continue; } if (ds.Tables != null && ds.Tables.Count > 0) { if (ds.Tables["Points"] != null && ds.Tables["Points"].Rows.Count > 0) { foreach (DataRow dr in ds.Tables["Points"].Rows) { string id = null; try { id = (string)dr["UniqueId"]; } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } bool convert = id != null && ConvertSpawner(id, dr); if (!convert) { Point3D loc = Point3D.Zero; Map spawnMap = null; try { loc = new Point3D(int.Parse((string)dr["CentreX"]), int.Parse((string)dr["CentreY"]), int.Parse((string)dr["CentreZ"])); spawnMap = Map.Parse((string)dr["Map"]); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (loc != Point3D.Zero && spawnMap != null && spawnMap != Map.Internal) { if (!ConvertSpawnerByLocation(loc, spawnMap, dr, ref keep)) { failed++; } else { converted++; } } } else { converted++; } } } } fs.Close(); } if (converted > 0) ToConsole(string.Format("Converted {0} XmlSpawners to standard spawners.", converted), ConsoleColor.Green); if (failed > 0) ToConsole(string.Format("Failed to convert {0} XmlSpawners to standard spawners. {1} kept due to XmlSpawner Functionality", failed, keep), ConsoleColor.Red); _SpawnsConverted = true; } else { ToConsole(string.Format("Directory Not Found: {0}", filename), ConsoleColor.Red); } } } private static bool ConvertSpawnerByLocation(Point3D p, Map map, DataRow dr, ref int keep) { XmlSpawner spawner = World.Items.Values.OfType().FirstOrDefault(s => s.Location == p && s.Map == map); return ConvertSpawner(spawner, dr, ref keep); } private static bool ConvertSpawner(string id, DataRow dr) { XmlSpawner spawner = World.Items.Values.OfType().FirstOrDefault(s => s.UniqueId == id); int c = 0; return ConvertSpawner(spawner, dr, ref c); } private static bool DeleteSpawner(string id) { if (id == null) return false; XmlSpawner spawner = World.Items.Values.OfType().FirstOrDefault(s => s.UniqueId == id); if (spawner != null) { spawner.Delete(); return true; } return false; } private static bool ConvertSpawner(XmlSpawner spawner, DataRow d, ref int keep) { if (spawner != null) { SpawnObject[] spawns = new SpawnObject[spawner.SpawnObjects.Length]; for (int i = 0; i < spawner.SpawnObjects.Length; i++) { XmlSpawner.SpawnObject obj = spawner.SpawnObjects[i]; if (obj == null || obj.TypeName == null) continue; spawns[i] = new SpawnObject(obj.TypeName, obj.MaxCount); } if (HasSpecialXmlSpawnerString(spawns)) { keep++; return false; } Spawner newSpawner = new Spawner(spawner.MaxCount, spawner.MinDelay, spawner.MaxDelay, spawner.Team, spawner.SpawnRange, spawns.ToList()) { Group = spawner.Group, Running = spawner.Running }; newSpawner.MoveToWorld(spawner.Location, spawner.Map); spawner.Delete(); return true; } return false; } private static bool HasSpecialXmlSpawnerString(SpawnObject[] spawns) { foreach (SpawnObject obj in spawns) { if (obj.SpawnName != null) { foreach (string s in _SpawnerSymbols) { if (obj.SpawnName.Contains(s)) return true; } } } return false; } private static readonly string[] _SpawnerSymbols = { "/", "<", ">", ",", "{", "}" }; public static void RevertToXmlSpawners(Mobile from) { string filename = "Spawns"; if (Directory.Exists(filename) == true) { List files = null; string[] dirs = null; try { files = new List(Directory.GetFiles(filename, "*.xml")); dirs = Directory.GetDirectories(filename); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (dirs != null && dirs.Length > 0) { foreach (string dir in dirs) { try { string[] dirFiles = Directory.GetFiles(dir, "*.xml"); files.AddRange(dirFiles); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } } } ToConsole(string.Format("Found {0} Xmlspawner files for removal.", files == null ? 0 : files.Count), files != null && files.Count > 0 ? ConsoleColor.Green : ConsoleColor.Red); ToConsole("Deleting spawners...", ConsoleColor.Cyan); long start = Core.TickCount; if (files != null && files.Count > 0) { int deletedxml = 0; int nospawner = 0; foreach (string file in files) { FileStream fs = null; try { fs = File.Open(file, FileMode.Open, FileAccess.Read); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (fs == null) { ToConsole(string.Format("Unable to open {0} for loading", filename), ConsoleColor.Red); continue; } DataSet ds = new DataSet("Spawns"); try { ds.ReadXml(fs); } catch { fs.Close(); ToConsole(string.Format("Error reading xml file {0}", filename), ConsoleColor.Red); continue; } if (ds.Tables != null && ds.Tables.Count > 0) { if (ds.Tables["Points"] != null && ds.Tables["Points"].Rows.Count > 0) { foreach (DataRow dr in ds.Tables["Points"].Rows) { string id = null; try { id = (string)dr["UniqueId"]; } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (DeleteSpawner(id)) { deletedxml++; } else { nospawner++; } } } } fs.Close(); } ToConsole(string.Format("Deleted {0} XmlSpawners [{1} no id] in {2} seconds.", deletedxml, nospawner, ((Core.TickCount - start) / 1000).ToString()), ConsoleColor.Cyan); } else { ToConsole(string.Format("Directory Not Found: {0}", filename), ConsoleColor.Red); } } } #endregion /// /// Deletes all spawners from a specific file. This can be used to delete spawners from a specific system where the spawner wasn't /// Generated from the Spawn Folder. /// /// /// public static void RemoveSpawnsFromXmlFile(string directory, string filename) { if (Directory.Exists(directory) == true) { List files = null; try { files = new List(Directory.GetFiles(directory, filename + ".xml")); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } ToConsole(string.Format("Found {0} Xmlspawner files for removal.", files == null ? "0" : files.Count.ToString()), files != null && files.Count > 0 ? ConsoleColor.Green : ConsoleColor.Red); ToConsole("Deleting spawners...", ConsoleColor.Cyan); if (files != null && files.Count > 0) { int deletedxml = 0; foreach (string file in files) { FileStream fs = null; try { fs = File.Open(file, FileMode.Open, FileAccess.Read); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (fs == null) { ToConsole(string.Format("Unable to open {0} for loading", filename), ConsoleColor.Red); continue; } DataSet ds = new DataSet("Spawns"); try { ds.ReadXml(fs); } catch { fs.Close(); ToConsole(string.Format("Error reading xml file {0}", filename), ConsoleColor.Red); continue; } if (ds.Tables != null && ds.Tables.Count > 0) { if (ds.Tables["Points"] != null && ds.Tables["Points"].Rows.Count > 0) { foreach (DataRow dr in ds.Tables["Points"].Rows) { string id = null; try { id = (string)dr["UniqueId"]; } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (DeleteSpawner(id)) { deletedxml++; } } } } fs.Close(); } ToConsole(string.Format("Deleted {0} XmlSpawners from {1}/{2}.xml.", deletedxml, directory, filename), ConsoleColor.Cyan); } else { ToConsole(string.Format("File Not Found: {0}", filename), ConsoleColor.Red); } } } /// /// Used in place of XmlSpawner wipe all spawners. This iterates through the Spawn Folder and deletes those spawners only. /// This will keep spawners for seprate systems in place. This is called in DeleteWorld gump. /// public static void WipeSpawnersFromFile() { string filename = "Spawns"; if (Directory.Exists(filename) == true) { List files = null; string[] dirs = null; try { files = new List(Directory.GetFiles(filename, "*.xml")); dirs = Directory.GetDirectories(filename); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (dirs != null && dirs.Length > 0) { foreach (string dir in dirs) { try { string[] dirFiles = Directory.GetFiles(dir, "*.xml"); files.AddRange(dirFiles); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } } } ToConsole(string.Format("Found {0} Xmlspawner files for conversion.", files.Count), files != null && files.Count > 0 ? ConsoleColor.Green : ConsoleColor.Red); ToConsole("Deleting spawners...", ConsoleColor.Cyan); long start = Core.TickCount; if (files != null && files.Count > 0) { int deletedxml = 0; int nodelelete = 0; foreach (string file in files) { FileStream fs = null; try { fs = File.Open(file, FileMode.Open, FileAccess.Read); } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (fs == null) { ToConsole(string.Format("Unable to open {0} for loading", filename), ConsoleColor.Red); continue; } DataSet ds = new DataSet("Spawns"); try { ds.ReadXml(fs); } catch { fs.Close(); ToConsole(string.Format("Error reading xml file {0}", filename), ConsoleColor.Red); continue; } if (ds.Tables != null && ds.Tables.Count > 0) { if (ds.Tables["Points"] != null && ds.Tables["Points"].Rows.Count > 0) { foreach (DataRow dr in ds.Tables["Points"].Rows) { string id = null; try { id = (string)dr["UniqueId"]; } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (DeleteSpawner(id)) { deletedxml++; } else { bool deleted = false; try { Point3D loc = new Point3D(int.Parse((string)dr["CentreX"]), int.Parse((string)dr["CentreY"]), int.Parse((string)dr["CentreZ"])); Map spawnMap = Map.Parse((string)dr["Map"]); string name = (string)dr["Name"]; if (spawnMap != null) { IPooledEnumerable eable = spawnMap.GetItemsInRange(loc, 0); foreach (Item item in eable) { if (item is XmlSpawner && item.Name == name) { item.Delete(); deletedxml++; deleted = true; break; } } eable.Free(); } } catch (Exception e) { Diagnostics.ExceptionLogging.LogException(e); } if (!deleted) { nodelelete++; ToConsole(string.Format("Failed to Delete: {0} in {1}", (string)dr["Name"], file)); } } } } } fs.Close(); } ToConsole(string.Format("Deleted {0} XmlSpawners [{1} failed] in {2} seconds.", deletedxml, nodelelete, ((Core.TickCount - start) / 1000).ToString()), ConsoleColor.Cyan); } else { ToConsole(string.Format("Directory Not Found: {0}", filename), ConsoleColor.Red); } } } } }