ThreeKingdomsSlingshot/Assets/Scripts/Editor/BalanceDefaults.cs

159 lines
9.0 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.Collections.Generic;
using UnityEngine;
namespace TKS.EditorTools
{
/// <summary>
/// BalanceConfig 자산의 최초 1회 시드 값(프로토타입 초안). 이후 수치 조정은 자산(Inspector)에서 한다 — 코드가 SOT 가 아니다.
/// 전장 = 가로 20 × 세로 32 (x −10~10 · y −16~16) · 화면에는 세로 18 만 보여 스크롤한다. 아군은 아래(y −13) · 적은 전위/중군/후군으로 흩어 배치.
/// 아트 id = Resources/Units/&lt;id&gt;/ (아군 = 스켈레탈 세션 리그 프레임 liubei·guanyu·zhangfei · 적 = 일러 세션 납품 이름 &lt;세력&gt;_&lt;병종&gt; · 없으면 도형).
/// </summary>
public static class BalanceDefaults
{
public static void Apply(BalanceConfig c)
{
c.unitStats = new[]
{
Stats(UnitType.Infantry, 100, 30, 10, 4.5f, 0f, 0.45f),
Stats(UnitType.Cavalry, 110, 28, 8, 6.5f, 0f, 0.45f),
Stats(UnitType.Archer, 70, 26, 4, 4.0f, 0f, 0.42f), // 궁병 사거리 = slingMaxDistance (attackRange 미사용 · #1080)
Stats(UnitType.Spear, 100, 30, 10, 4.5f, 2.2f, 0.45f),
};
// 상성: 보병 > 창병 > 기병 > 보병 · 궁병은 모두에게 약함(받는 피해 1.5)
c.matchup = new float[UnitTypeInfo.Count * UnitTypeInfo.Count];
for (int i = 0; i < c.matchup.Length; i++) c.matchup[i] = 1f;
c.SetMatchup(UnitType.Infantry, UnitType.Spear, 1.5f);
c.SetMatchup(UnitType.Infantry, UnitType.Cavalry, 0.7f);
c.SetMatchup(UnitType.Spear, UnitType.Cavalry, 1.5f);
c.SetMatchup(UnitType.Spear, UnitType.Infantry, 0.7f);
c.SetMatchup(UnitType.Cavalry, UnitType.Infantry, 1.5f);
c.SetMatchup(UnitType.Cavalry, UnitType.Spear, 0.7f);
c.SetMatchup(UnitType.Infantry, UnitType.Archer, 1.5f);
c.SetMatchup(UnitType.Cavalry, UnitType.Archer, 1.5f);
c.SetMatchup(UnitType.Spear, UnitType.Archer, 1.5f);
c.defenseFactor = 0.5f;
c.counterRatio = 0.5f;
c.critMultiplier = 2f;
c.damageVariance = 0.1f;
c.overwatchDamageRatio = 1f;
c.bossHpMult = 1.6f;
c.bossRadiusMult = 1.25f;
c.cavalryKnockback = 0.35f;
c.archerRangeRatio = 0.2f; // PD 2026-11-04: 사거리(슬링샷 범위) 밖 +20 % 안의 적에게 다가가 사격
c.archerMeleeDealtRatio = 0.5f; // PD 2026-11-04 #1080: 궁수 근접 전투 피해 50 %
c.archerMeleeTakenRatio = 1.5f; // PD 2026-11-04 #1080: 궁수 근접 피격 +50 %
c.collisionPushRatio = 1f; // PD 2026-11-04 #1080: 보병 알까기 밀어내기 = 남은 거리 그대로
c.unitArtHeight = 1.5f;
c.boardArt = "battlefield_01"; // 원화 세션 1차 납품(2026-11-04) · Resources/Board/
c.minDragDistance = 0.35f;
c.finalHitTolerance = 0.15f;
c.moveSpeed = 9f;
c.boardSize = new Vector2(20f, 32f);
c.cameraViewHeight = 18f;
c.cameraMinViewHeight = 10f;
c.cameraMaxViewHeight = 36f;
c.playerSpawnPoints = new[]
{
new Vector2(-4f, -13f), new Vector2(-2f, -13f), new Vector2(0f, -13f), new Vector2(2f, -13f), new Vector2(4f, -13f),
};
c.heroes = new[]
{
Hero("유비", UnitType.Infantry, 1.1f, 1.0f, "liubei"),
Hero("관우", UnitType.Spear, 1.1f, 1.25f, "guanyu"),
Hero("장비", UnitType.Cavalry, 1.0f, 1.2f, "zhangfei"),
Hero("조운", UnitType.Cavalry, 1.1f, 1.1f, ""), // 아트 미제작 → 도형
Hero("황충", UnitType.Archer, 1.0f, 1.25f, ""), // 아트 미제작 → 도형
};
c.stages = new[]
{
Stage("황건적의 난", "184년", 0.5f, 11f,
// 전위
E("hgj", "황건적 보병", UnitType.Infantry, -3f, -6f),
E("hgj", "황건적 보병", UnitType.Infantry, 3f, -6f),
E("hgj", "황건적 창병", UnitType.Spear, 0f, -4.5f),
// 중군
E("hgj", "황건적 궁병", UnitType.Archer, -4f, 1f),
E("hgj", "황건적 궁병", UnitType.Archer, 4f, 1f),
E("hgj", "황건적 보병", UnitType.Infantry, 0f, 2.5f),
// 후군
E("hgj", "황건적 창병", UnitType.Spear, -2.5f, 8f),
Boss("hgj", "zhangjiao", "장각", UnitType.Infantry, 0f, 10f, 1.3f, 1.2f)),
Stage("호로관 전투", "190년", 0.6f, 11f,
E("dz", "동탁군 창병", UnitType.Spear, -2.5f, -5f),
E("dz", "동탁군 창병", UnitType.Spear, 2.5f, -5f),
E("dz", "동탁군 기병", UnitType.Cavalry, -6f, -1f),
E("dz", "동탁군 기병", UnitType.Cavalry, 6f, -1f),
E("dz", "동탁군 보병", UnitType.Infantry, 0f, 1f),
E("dz", "동탁군 궁병", UnitType.Archer, -3f, 3f),
E("dz", "동탁군 궁병", UnitType.Archer, 3f, 3f),
E("dz", "동탁군 기병", UnitType.Cavalry, 0f, 7f),
Boss("dz", "lvbu", "여포", UnitType.Cavalry, 0f, 11f, 1.6f, 1.5f)),
Stage("적벽대전", "208년", 0.65f, 12f,
E("cc", "조조군 보병", UnitType.Infantry, -5f, -6f),
E("cc", "조조군 보병", UnitType.Infantry, 0f, -5f),
E("cc", "조조군 보병", UnitType.Infantry, 5f, -6f),
E("cc", "조조군 기병", UnitType.Cavalry, -3f, 0f),
E("cc", "조조군 기병", UnitType.Cavalry, 3f, 0f),
E("cc", "조조군 궁병", UnitType.Archer, -4f, 5f),
E("cc", "조조군 궁병", UnitType.Archer, 4f, 5f),
E("cc", "조조군 창병", UnitType.Spear, 0f, 7f),
Boss("cc", "caocao", "조조", UnitType.Infantry, 0f, 12f, 1.5f, 1.3f)),
Stage("오장원 전투", "234년", 0.7f, 12f,
E("wei", "위군 창병", UnitType.Spear, -3f, -6f),
E("wei", "위군 창병", UnitType.Spear, 3f, -6f),
E("wei", "위군 보병", UnitType.Infantry, -7f, -2f),
E("wei", "위군 보병", UnitType.Infantry, 7f, -2f),
E("wei", "위군 기병", UnitType.Cavalry, -2f, 2f),
E("wei", "위군 기병", UnitType.Cavalry, 2f, 2f),
E("wei", "위군 궁병", UnitType.Archer, -4f, 7f),
E("wei", "위군 궁병", UnitType.Archer, 4f, 7f),
E("wei", "위군 창병", UnitType.Spear, 0f, 9f),
Boss("wei", "simayi", "사마의", UnitType.Infantry, 0f, 13f, 1.6f, 1.3f)),
};
}
static BalanceConfig.UnitStats Stats(UnitType t, int hp, int atk, int def, float sling, float range, float radius)
{
return new BalanceConfig.UnitStats { type = t, maxHp = hp, atk = atk, def = def, slingMaxDistance = sling, attackRange = range, radius = radius };
}
static BalanceConfig.HeroDef Hero(string name, UnitType t, float hpMult, float atkMult, string art)
{
return new BalanceConfig.HeroDef { name = name, type = t, hpMult = hpMult, atkMult = atkMult, art = art };
}
/// <summary>적 병사 아트 id = &lt;세력 접두&gt;_&lt;병종&gt; (일러 세션 납품 이름 규칙 · 예 hgj_infantry).</summary>
static string ArtKey(UnitType t)
{
switch (t)
{
case UnitType.Infantry: return "infantry";
case UnitType.Cavalry: return "cavalry";
case UnitType.Archer: return "archer";
case UnitType.Spear: return "spear";
}
return "unit";
}
static BalanceConfig.EnemySpawn E(string faction, string name, UnitType t, float x, float y)
{
return new BalanceConfig.EnemySpawn { name = name, type = t, position = new Vector2(x, y), hpMult = 1f, atkMult = 1f, isBoss = false, art = faction + "_" + ArtKey(t) };
}
static BalanceConfig.EnemySpawn Boss(string faction, string roman, string name, UnitType t, float x, float y, float hpMult, float atkMult)
{
return new BalanceConfig.EnemySpawn { name = name, type = t, position = new Vector2(x, y), hpMult = hpMult, atkMult = atkMult, isBoss = true, art = faction + "_boss_" + roman };
}
static BalanceConfig.StageDef Stage(string title, string subtitle, float accuracy, float aggro, params BalanceConfig.EnemySpawn[] enemies)
{
return new BalanceConfig.StageDef { title = title, subtitle = subtitle, aiAccuracy = accuracy, aiAggroRange = aggro, enemies = new List<BalanceConfig.EnemySpawn>(enemies) };
}
}
}