/// <summary> /// Initializes a new instance of the <see cref="PawnList"/> class. /// </summary> /// <param name="throwSyntaxErrors">if set to <c>true</c> [throw syntax errors].</param> /// <param name="search">The search.</param> public PawnList(bool throwSyntaxErrors, params string[] search) { // We want it all done in a single frame. This may hurt FPS. // Make sure the user is aware! using (new FrameLock(true)) { // Set our search args. And parse everything. SearchArguments = new PawnSearchArgs(throwSyntaxErrors, search); _lst = new List <Pawn>(); // This is our main 'search' function. RefreshList(); } }
/// <summary> /// Refreshes this <see cref="PawnList"/> based on the <see cref="SearchArguments"/> provided when creating this class. /// </summary> private void _RefreshList() { _lst.Clear(); // Really sad that we need to do this... but oh well... int pawnCount = new VG().PawnCount; int limit = int.MaxValue; // Laziness. // Just to shorten stuff a bit. PawnSearchArgs a = SearchArguments; // Set our limit ONCE. If limit has no value, it defaults to int.MaxValue. // Which pretty much removes the limit :P if (a.Limit.HasValue) { limit = a.Limit.Value; } float meZ = new Character().Z; for (int i = 0; i < pawnCount; i++) { // We hit the 'limit'. So just stop even going through stuff! if (_lst.Count >= limit) { break; } // Store our pawn so we don't need to get a new one 50-60 times per iteration. Pawn p = new Pawn(i); PawnType ptype = p.PawnType; // And now...... the long.... long... search method. Oh boy! if (a.AggroNpc.HasValue) { // If we only wnat NPCs that are aggroed, and the current is not. Skip it. if (a.AggroNpc.Value && !p.IsAggro) { continue; } // Opposite of the above. if (!a.AggroNpc.Value && p.IsAggro) { continue; } } if (a.Attackable.HasValue) { if (a.Attackable.Value && !p.IsAttackable) { continue; } if (!a.Attackable.Value && p.IsAttackable) { continue; } } if (a.Clickable.HasValue) { if (a.Clickable.Value && !p.IsClickable) { continue; } if (!a.Clickable.Value && p.IsClickable) { continue; } } if (a.Corpse.HasValue) { if (a.Corpse.Value && ptype != PawnType.Corpse) { continue; } if (!a.Corpse.Value && ptype == PawnType.Corpse) { continue; } } if (a.CraftingStation.HasValue) { if (a.CraftingStation.Value && ptype != PawnType.CraftingStation) { continue; } if (!a.CraftingStation.Value && ptype == PawnType.CraftingStation) { continue; } } if (a.Distance.HasValue) { if (a.Distance.Value > p.Distance) { continue; } } if (!string.IsNullOrEmpty(a.Name)) { // If the Name property is set, a simple contains should suffice. // Also, if the Name and ExactName are BOTH set. If this fails, // the exact name check would fail also. So just do the check now. // Note: We're doing this via .ToLower() strings. It's just a contains, so casing should have no input on the matter. if (!p.Name.ToLower().Contains(a.Name.ToLower())) { continue; } } if (!string.IsNullOrEmpty(a.ExactName)) { // Literal match. if (a.ExactName != p.Name) { continue; } } if (a.GroupMember.HasValue) { if (a.GroupMember.Value && ptype != PawnType.GroupMember) { continue; } if (!a.GroupMember.Value && ptype == PawnType.GroupMember) { continue; } } // NotID takes precedence over ID. if (a.NotID.HasValue) { if (a.NotID.Value == p.ID) { continue; } } if (a.ID.HasValue) { if (a.ID.Value != p.ID) { continue; } } // If OuterRadius has a value. InnerRadius will have one too. // But since only InnerRadius differing from OutRadius changes // the search, we'll use that within the a.OuterRadius.HasValue check. if (a.OuterRadius.HasValue) { float distance = p.Distance; if (a.InnerRadius.Value != a.OuterRadius.Value) { // Means we need to check for a distance 'within'. if (a.InnerRadius.Value <= distance || a.OuterRadius.Value >= distance) { continue; } } else { if (a.OuterRadius.Value > distance) { continue; } } } // Do both checks. if (a.MaxLevel.HasValue || a.MinLevel.HasValue) { int lvl = p.Level; if (a.MaxLevel.HasValue) { if (a.MaxLevel <= lvl) { continue; } } if (a.MinLevel.HasValue) { if (a.MinLevel >= lvl) { continue; } } } if (a.Merchant.HasValue) { if (a.Merchant.Value && ptype != PawnType.Merchant) { continue; } if (!a.Merchant.Value && ptype == PawnType.Merchant) { continue; } } if (a.MyPet.HasValue) { if (a.MyPet.Value && ptype != PawnType.MyPet) { continue; } if (!a.MyPet.Value && ptype == PawnType.MyPet) { continue; } } if (a.NoOwner.HasValue) { if (a.NoOwner.HasValue && p.Owner.IsValid) { continue; } } if (a.Npc.HasValue) { if (a.Npc.Value && ptype != PawnType.NPC) { continue; } if (!a.Npc.Value && ptype == PawnType.NPC) { continue; } } if (a.Pc.HasValue) { if (a.Pc.Value && ptype != PawnType.PC) { continue; } if (!a.Pc.Value && ptype == PawnType.PC) { continue; } } if (a.Pet.HasValue) { if (a.Pet.Value && ptype != PawnType.Pet) { continue; } if (!a.Pet.Value && ptype == PawnType.Pet) { continue; } } if (a.QuestNpc.HasValue) { if (a.QuestNpc.Value && !p.HasQuestFlag) { continue; } if (!a.QuestNpc.Value && p.HasQuestFlag) { continue; } } if (!string.IsNullOrEmpty(a.Race)) { if (p.Race.ToLower() != a.Race.ToLower()) { continue; } } if (a.Resource.HasValue) { if (a.Resource.Value && ptype != PawnType.Resource) { continue; } if (!a.Resource.Value && ptype == PawnType.Resource) { continue; } } if (a.Trainer.HasValue) { if (a.Trainer.Value && ptype != PawnType.Trainer) { continue; } if (!a.Trainer.Value && ptype == PawnType.Trainer) { continue; } } if (!string.IsNullOrEmpty(a.Type)) { if (a.Type.ToLower() != p.Type.ToLower()) { continue; } } if (a.ZRange.HasValue) { // Should be right.... right? float zdist = Math.Abs(meZ - p.Z); if (zdist >= a.ZRange.Value) { continue; } } // FINALLY! THE END! All our checks passed. So we can FINALLY add the pawn to the list. // Holy christ that took forever! _lst.Add(p); } }