MovingInfo FindUltimateTarget(AWizard self) { var ret = new MovingInfo(null, int.MaxValue, new FinalMove(new Move())); const int threshold = 29; var minTicks = int.MaxValue; AWizard selTarget = null; var selAction = ActionType.None; foreach (var action in new[] { ActionType.Haste, ActionType.Shield }) { if (action == ActionType.Haste && self.HasteSkillLevel < 5 || action == ActionType.Shield && self.ShieldSkillLevel < 5 ) { continue; } var teammates = MyWizards .Where(x => x.Id != self.Id && self.GetDistanceTo(x) <= self.CastRange && x.RemainingStatusByAction(action) <= threshold ). ToArray(); foreach (var teammate in teammates) { var ticks = 0; var my = new AWizard(self); while (Math.Abs(my.GetAngleTo(teammate)) > Game.StaffSector / 2) { ticks++; my.MoveTo(null, teammate); } if (ticks < minTicks && my.CanCastUltimate(action, teammate)) { minTicks = ticks; selTarget = teammate; selAction = action; } } if (selTarget == null && teammates.Length == 0 && self.RemainingStatusByAction(action) <= threshold && self.CanUseUltimate(action) ) { minTicks = 100; selTarget = self; selAction = action; } } if (selTarget == null) { return(ret); } ret.Target = selTarget; ret.TargetId = selTarget.Id; ret.Time = minTicks; if (self.CanCastUltimate(selAction, selTarget)) { ret.Move.Action = selAction; ret.Move.StatusTargetId = selTarget.Id; } else { ret.Move.MoveTo(null, selTarget); } return(ret); }