using System.Collections.Generic; using UnityEngine; namespace TKS { /// 적군 슬링샷 결정: 교전 범위 안의 가장 가까운 아군을 향해 당기고, 정확도에 따라 흔들린다. 범위 밖이면 대기(null). public static class EnemyAI { public static Vector2? Decide(Unit e, IReadOnlyList targets, float accuracy, float aggroRange, System.Random rng, Board board) { Unit nearest = null; float best = float.MaxValue; for (int i = 0; i < targets.Count; i++) { var t = targets[i]; if (!t.IsAlive) continue; float d = Vector2.Distance(e.Position, t.Position); if (d < best) { best = d; nearest = t; } } if (nearest == null) return null; if (best > aggroRange) return null; // 넓은 전장: 교전 범위 밖이면 자리 지킴 Vector2 toT = nearest.Position - e.Position; float dist = toT.magnitude; Vector2 dir = dist > 0.001f ? toT / dist : Vector2.up; Vector2 target; if (dist <= e.SlingMaxDistance) { target = nearest.Position; // 최종 목표점 명중 시도 } else { target = e.Position + dir * e.SlingMaxDistance; // 접근(궁병은 사거리 안이면 이동 후 사격) } if (rng.NextDouble() > accuracy) { float ang = ((float)rng.NextDouble() * 2f - 1f) * 22f * Mathf.Deg2Rad; float cs = Mathf.Cos(ang); float sn = Mathf.Sin(ang); Vector2 rd = new Vector2(dir.x * cs - dir.y * sn, dir.x * sn + dir.y * cs); float len = (target - e.Position).magnitude * (0.75f + 0.5f * (float)rng.NextDouble()); target = e.Position + rd * Mathf.Min(len, e.SlingMaxDistance); } Vector2 v = target - e.Position; if (v.magnitude > e.SlingMaxDistance) v = v.normalized * e.SlingMaxDistance; return board.ClampInside(e.Position + v, e.Radius); } } }