/// <summary> /// Select the best target (in <targetType> order) satisfying <predicate> from the threat list. /// If <offset> is nonzero, the first <offset> entries in <targetType> order (or MAXTHREAT order, if <targetType> is RANDOM) are skipped. /// </summary> public Unit SelectTarget(SelectAggroTarget targetType, uint offset, ISelector selector) { ThreatManager mgr = GetThreatManager(); // shortcut: if we ignore the first <offset> elements, and there are at most <offset> elements, then we ignore ALL elements if (mgr.GetThreatListSize() <= offset) { return(null); } List <Unit> targetList = SelectTargetList((uint)mgr.GetThreatListSize(), targetType, offset, selector); // maybe nothing fulfills the predicate if (targetList.Empty()) { return(null); } switch (targetType) { case SelectAggroTarget.MaxThreat: case SelectAggroTarget.MinThreat: case SelectAggroTarget.MaxDistance: case SelectAggroTarget.MinDistance: return(targetList[0]); case SelectAggroTarget.Random: return(targetList.SelectRandom()); default: return(null); } }
/// <summary> /// Select the best (up to) <num> targets (in <targetType> order) satisfying <predicate> from the threat list and stores them in <targetList> (which is cleared first). /// If <offset> is nonzero, the first <offset> entries in <targetType> order (or MAXTHREAT order, if <targetType> is RANDOM) are skipped. /// </summary> public List <Unit> SelectTargetList(uint num, SelectAggroTarget targetType, uint offset, ISelector selector) { var targetList = new List <Unit>(); ThreatManager mgr = GetThreatManager(); // shortcut: we're gonna ignore the first <offset> elements, and there's at most <offset> elements, so we ignore them all - nothing to do here if (mgr.GetThreatListSize() <= offset) { return(targetList); } if (targetType == SelectAggroTarget.MaxDistance || targetType == SelectAggroTarget.MinDistance) { foreach (HostileReference refe in mgr.GetThreatList()) { if (!refe.IsOnline()) { continue; } targetList.Add(refe.GetTarget()); } } else { Unit currentVictim = mgr.GetCurrentVictim(); if (currentVictim != null) { targetList.Add(currentVictim); } foreach (HostileReference refe in mgr.GetThreatList()) { if (!refe.IsOnline()) { continue; } Unit thisTarget = refe.GetTarget(); if (thisTarget != currentVictim) { targetList.Add(thisTarget); } } } // shortcut: the list isn't gonna get any larger if (targetList.Count <= offset) { targetList.Clear(); return(targetList); } // right now, list is unsorted for DISTANCE types - re-sort by MAXDISTANCE if (targetType == SelectAggroTarget.MaxDistance || targetType == SelectAggroTarget.MinDistance) { SortByDistance(targetList, targetType == SelectAggroTarget.MinDistance); } // now the list is MAX sorted, reverse for MIN types if (targetType == SelectAggroTarget.MinThreat) { targetList.Reverse(); } // ignore the first <offset> elements while (offset != 0) { targetList.RemoveAt(0); --offset; } // then finally filter by predicate targetList.RemoveAll(target => { return(!selector.Check(target)); }); if (targetList.Count <= num) { return(targetList); } if (targetType == SelectAggroTarget.Random) { targetList = targetList.SelectRandom(num).ToList(); } else { targetList.Resize(num); } return(targetList); }