public BestTargetResult GetBestTargets(uint battleId, ICombatObject attacker, out List <Target> result, int maxCount, uint round) { result = new List <Target>(); var objectsByScore = new List <CombatScoreItem>(Count); var objsInRange = (from combatGroup in this from defender in combatGroup where !defender.IsWaitingToJoinBattle && !defender.IsDead && defender.InRange(attacker) && attacker.InRange(defender) select new Target { Group = combatGroup, CombatObject = defender }).ToList(); if (objsInRange.Count == 0) { return(BestTargetResult.NoneInRange); } uint lowestRow = objsInRange.Min(target => target.CombatObject.Stats.Stl); Target bestTarget = null; decimal bestTargetScore = 0; foreach (var target in objsInRange) { if (!attacker.CanSee(target.CombatObject, lowestRow)) { continue; } // Calculate dmg against each target as base score decimal score = battleFormulas.GetAttackScore(attacker, target.CombatObject, round); if (bestTarget == null || score > bestTargetScore) { bestTarget = target; bestTargetScore = score; } objectsByScore.Add(new CombatScoreItem { Target = target, Score = score }); } if (objectsByScore.Count == 0) { return(BestTargetResult.Ok); } // Shuffle to get some randomization in the attack order. We pass the battleId as a seed in order to // make it so the attacker doesn't switch targets once it starts attacking them but this way // they won't attack the stacks in the order they joined the battle, which usually would mean // they will attack the same type of units one after another // then sort by score descending var shuffled = objectsByScore.Shuffle((int)battleId); shuffled.Sort(new CombatScoreItemComparer(attacker, tileLocator)); var numberOfTargetsToHit = Math.Min(maxCount, objectsByScore.Count); // Get top results specified by the maxCount param result = shuffled.Take(numberOfTargetsToHit).Select(scoreItem => scoreItem.Target).ToList(); return(BestTargetResult.Ok); }
public bool HasInRange(ICombatObject attacker) { return(AllAliveCombatObjects().Any(obj => obj.InRange(attacker) && attacker.InRange(obj))); }