ThreeKingdomsSlingshot/Assets/Scripts/Runtime/BalanceConfig.cs

119 lines
4.3 KiB
C#
Raw 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 System;
using System.Collections.Generic;
using UnityEngine;
namespace TKS
{
/// <summary>
/// 밸런스·스테이지 데이터의 단일 출처(SOT). 코드에는 수치를 두지 않고 이 자산만 읽는다.
/// 기본값은 에디터 셋업(ProjectSetup)이 최초 1회 시드한다.
/// </summary>
[CreateAssetMenu(menuName = "TKS/Balance Config", fileName = "BalanceConfig")]
public class BalanceConfig : ScriptableObject
{
[Serializable]
public class UnitStats
{
public UnitType type;
public int maxHp;
public int atk;
public int def;
[Tooltip("슬링샷으로 지정할 수 있는 최대 거리(월드 단위)")]
public float slingMaxDistance;
[Tooltip("궁병 사거리 · 창병 대기(견제) 반경")]
public float attackRange;
public float radius;
}
[Serializable]
public class HeroDef
{
public string name;
public UnitType type;
public float hpMult = 1f;
public float atkMult = 1f;
}
[Serializable]
public class EnemySpawn
{
public string name;
public UnitType type;
public Vector2 position;
public float hpMult = 1f;
public float atkMult = 1f;
public bool isBoss;
}
[Serializable]
public class StageDef
{
public string title;
public string subtitle;
[Range(0f, 1f)] public float aiAccuracy = 0.6f;
public List<EnemySpawn> enemies = new List<EnemySpawn>();
}
[Header("병종 기본 능력치")]
public UnitStats[] unitStats = new UnitStats[0];
[Header("상성 배율 (행 = 공격자, 열 = 피격자 · 순서 보병·기병·궁병·창병)")]
public float[] matchup = new float[UnitTypeInfo.Count * UnitTypeInfo.Count];
[Header("전투 공식")]
[Tooltip("피해 = 공격 × 상성 × (크리 배율) − 방어 × defenseFactor")]
public float defenseFactor = 0.5f;
[Tooltip("근접 공격을 받은 쪽이 되돌려주는 반격 피해 비율")]
public float counterRatio = 0.5f;
public float critMultiplier = 2f;
[Tooltip("피해 난수 폭 (0.1 = ±10 %)")]
public float damageVariance = 0.1f;
[Tooltip("창병 대기 상태에서 움직이는 적에게 주는 피해 비율")]
public float overwatchDamageRatio = 1f;
public float bossHpMult = 1.5f;
public float bossRadiusMult = 1.25f;
[Tooltip("기병 관통 시 적을 옆으로 밀어내는 거리")]
public float cavalryKnockback = 0.35f;
[Header("조작")]
[Tooltip("이보다 짧게 당기면 취소")]
public float minDragDistance = 0.35f;
[Tooltip("슬링샷 최종 목표점이 적 원 안에 들어왔다고 보는 여유")]
public float finalHitTolerance = 0.15f;
public float moveSpeed = 9f;
[Header("전장")]
public Vector2 boardSize = new Vector2(12f, 16f);
public Vector2[] playerSpawnPoints = new Vector2[0];
[Header("아군 영웅 (최대 5)")]
public HeroDef[] heroes = new HeroDef[0];
[Header("스테이지")]
public StageDef[] stages = new StageDef[0];
public UnitStats GetStats(UnitType t)
{
for (int i = 0; i < unitStats.Length; i++)
{
if (unitStats[i].type == t) return unitStats[i];
}
throw new InvalidOperationException("BalanceConfig 에 " + t + " 능력치가 없습니다.");
}
public float Matchup(UnitType attacker, UnitType defender)
{
int idx = (int)attacker * UnitTypeInfo.Count + (int)defender;
if (matchup == null || idx >= matchup.Length) return 1f;
return matchup[idx];
}
public void SetMatchup(UnitType attacker, UnitType defender, float value)
{
if (matchup == null || matchup.Length != UnitTypeInfo.Count * UnitTypeInfo.Count)
matchup = new float[UnitTypeInfo.Count * UnitTypeInfo.Count];
matchup[(int)attacker * UnitTypeInfo.Count + (int)defender] = value;
}
}
}