using UnityEngine; namespace TKS { /// /// 선택(터치)한 유닛의 사거리 표시 (PD 2026-11-04). /// · 모든 병종: 슬링샷 최대 거리 = 얇은 반투명 원 (아군·적군 모두) /// · 궁병·책사: 추가로 슬링샷 범위 ~ 슬링샷 범위 × (1 + archerRangeRatio) 까지를 채워진 반투명 붉은 도넛으로 (실제 공격 가능 범위) /// — 그 범위 안에 적이 하나도 없으면 회색. /// public class RangeIndicator : MonoBehaviour { public static readonly Color RingColor = new Color(1f, 1f, 1f, 0.42f); public static readonly Color DonutColor = new Color(0.95f, 0.25f, 0.2f, 0.3f); public static readonly Color DonutIdleColor = new Color(0.6f, 0.6f, 0.6f, 0.18f); SpriteRenderer ring; SpriteRenderer donut; Unit target; float ratio; public Unit Target { get { return target; } } public bool RingVisible { get { return ring != null && ring.gameObject.activeSelf; } } public bool DonutVisible { get { return donut != null && donut.gameObject.activeSelf; } } /// 얇은 원의 지름(월드) = 슬링샷 최대 거리 × 2. public float RingDiameter { get { return ring != null ? ring.transform.localScale.x : 0f; } } /// 도넛 바깥 지름(월드) = 슬링샷 최대 거리 × (1 + 비율) × 2. public float DonutDiameter { get { return donut != null ? donut.transform.localScale.x : 0f; } } public void Init(float archerRangeRatio) { ratio = Mathf.Max(0f, archerRangeRatio); ring = ProceduralSprites.NewSprite(transform, "SlingRange", ProceduralSprites.ThinRing, RingColor, 1f, -9); // 도넛 안쪽 지름 = 바깥 지름 ÷ (1 + 비율) → 안쪽 테두리가 슬링샷 범위 원과 일치 donut = ProceduralSprites.NewSprite(transform, "ArcherReach", ProceduralSprites.Donut(1f / (1f + ratio)), DonutColor, 1f, -10); ring.gameObject.SetActive(false); donut.gameObject.SetActive(false); } public void Show(Unit u) { target = u; if (u == null) { Hide(); return; } float r = SkillMods.SlingMax(u); // 스킬(동남풍·적토마) 반영 · 없으면 슬링샷 최대 거리 ring.transform.localScale = new Vector3(r * 2f, r * 2f, 1f); ring.gameObject.SetActive(true); bool archer = UnitTypeInfo.IsRanged(u.Type); // 궁병·책사(#1087 ⑤ 같은 사거리 규칙) if (archer) { float ro = SkillMods.Range(u) * (1f + ratio); // 사거리 스킬(단기·대도독) 반영 · 없으면 = 슬링 × (1 + 비율) donut.transform.localScale = new Vector3(ro * 2f, ro * 2f, 1f); donut.color = DonutColor; } if (donut.gameObject.activeSelf != archer) donut.gameObject.SetActive(archer); Follow(); } public void Hide() { target = null; if (ring != null) ring.gameObject.SetActive(false); if (donut != null) donut.gameObject.SetActive(false); } /// 궁병 도넛 색: 공격 가능 범위 안에 적이 있으면 붉게, 없으면 회색. public void SetArcherReachable(bool any) { if (donut != null) donut.color = any ? DonutColor : DonutIdleColor; } void LateUpdate() { if (target == null) return; if (!target.IsAlive) { Hide(); return; } Follow(); } void Follow() { Vector2 p = target.Position; transform.position = new Vector3(p.x, p.y, 0f); } } }