ThreeKingdomsSlingshot/Assets/Scripts/Runtime/RangeIndicator.cs

113 lines
4.0 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}
}