113 lines
4.0 KiB
C#
113 lines
4.0 KiB
C#
using UnityEngine;
|
||
|
||
namespace TKS
|
||
{
|
||
/// <summary>
|
||
/// 선택(터치)한 유닛의 사거리 표시 (PD 2026-11-04).
|
||
/// · 모든 병종: 슬링샷 최대 거리 = 얇은 반투명 원 (아군·적군 모두)
|
||
/// · 궁병·책사: 추가로 슬링샷 범위 ~ 슬링샷 범위 × (1 + archerRangeRatio) 까지를 채워진 반투명 붉은 도넛으로 (실제 공격 가능 범위)
|
||
/// — 그 범위 안에 적이 하나도 없으면 회색.
|
||
/// </summary>
|
||
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; }
|
||
}
|
||
|
||
/// <summary>얇은 원의 지름(월드) = 슬링샷 최대 거리 × 2.</summary>
|
||
public float RingDiameter
|
||
{
|
||
get { return ring != null ? ring.transform.localScale.x : 0f; }
|
||
}
|
||
|
||
/// <summary>도넛 바깥 지름(월드) = 슬링샷 최대 거리 × (1 + 비율) × 2.</summary>
|
||
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);
|
||
}
|
||
|
||
/// <summary>궁병 도넛 색: 공격 가능 범위 안에 적이 있으면 붉게, 없으면 회색.</summary>
|
||
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);
|
||
}
|
||
}
|
||
}
|