ThreeKingdomsSlingshot/Assets/Scripts/OutGame/Domestic/TrainingRules.cs

117 lines
4.5 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.OutGame
{
/// <summary>
/// 내정 훈련 규칙(기획서 §7 · S9 · PD #1093 C) — 병종마다 HP·공·방 3항목 골드 레벨업(항목당 Lv max) · 비용 = gold_cost(Lv) × cost_mult(랭크) ·
/// 3항목 Max → 랭크 승급(promote_gold · 레벨 리셋 · 랭크 보너스 유지) · train_bonus(병종, 항목) = rank_pct(랭크) + stat_pct(Lv) → §3-2 공식(그 병종 영웅·병사 전원).
/// </summary>
public static class TrainingRules
{
public static int StatIndex(string stat)
{
return System.Array.IndexOf(TrainingTable.Stats, stat);
}
static TrainState Find(SaveData d, UnitType t)
{
if (d == null || d.training == null) return null;
var key = UnitTypeInfo.Key(t);
foreach (var s in d.training)
if (s.type == key) return s;
return null;
}
public static int Rank(SaveData d, UnitType t)
{
var s = Find(d, t);
return s != null ? Mathf.Max(1, s.rank) : 1;
}
public static int Lv(SaveData d, UnitType t, int stat)
{
var s = Find(d, t);
return s != null && s.lv != null && stat >= 0 && stat < s.lv.Length ? s.lv[stat] : 0;
}
/// <summary>훈련 보너스 % = 랭크 보너스 + 항목 Lv 누적 %.</summary>
public static float Bonus(OutGameData db, SaveData d, UnitType t, string stat)
{
if (db == null || db.Training == null || d == null) return 0f;
var rank = db.Training.RankOf(Rank(d, t));
int lv = Lv(d, t, StatIndex(stat));
var row = lv > 0 ? db.Training.Get(t, stat, lv) : null;
return (rank != null ? rank.rankPct : 0f) + (row != null ? row.statPct : 0f);
}
/// <summary>다음 Lv 비용(최고 Lv = 0).</summary>
public static int Cost(OutGameData db, SaveData d, UnitType t, int stat)
{
int lv = Lv(d, t, stat);
var row = db.Training.Get(t, TrainingTable.Stats[stat], lv + 1);
var rank = db.Training.RankOf(Rank(d, t));
if (row == null) return 0;
return Mathf.RoundToInt(row.goldCost * (rank != null ? rank.costMult : 1f));
}
public static string CanLevel(OutGameData db, SaveData d, UnitType t, int stat)
{
if (Lv(d, t, stat) >= db.Training.MaxLevel) return "Max";
int cost = Cost(db, d, t, stat);
if (d.gold < cost) return "골드 부족 " + d.gold.ToString("N0") + " / " + cost.ToString("N0");
return null;
}
public static string Level(OutGameData db, SaveData d, UnitType t, int stat)
{
var why = CanLevel(db, d, t, stat);
if (why != null) return why;
d.gold -= Cost(db, d, t, stat);
d.Train(t).lv[stat]++;
return null;
}
/// <summary>이 랭크에서 남은 레벨 수(3항목 × Max − 합).</summary>
public static int Remaining(OutGameData db, SaveData d, UnitType t)
{
int left = 0;
for (int i = 0; i < TrainingTable.Stats.Length; i++) left += db.Training.MaxLevel - Lv(d, t, i);
return left;
}
public static int PromoteCost(OutGameData db, SaveData d, UnitType t)
{
var r = db.Training.RankOf(Rank(d, t));
return r != null ? r.promoteGold : 0;
}
public static string CanPromote(OutGameData db, SaveData d, UnitType t)
{
if (Rank(d, t) >= db.Training.MaxRank) return "최종 랭크";
int left = Remaining(db, d, t);
if (left > 0) return "남은 레벨 " + left;
int cost = PromoteCost(db, d, t);
if (d.gold < cost) return "골드 부족 " + d.gold.ToString("N0") + " / " + cost.ToString("N0");
return null;
}
/// <summary>랭크 +1 · 3항목 Lv 리셋(랭크 보너스는 새 랭크 값).</summary>
public static string Promote(OutGameData db, SaveData d, UnitType t)
{
var why = CanPromote(db, d, t);
if (why != null) return why;
d.gold -= PromoteCost(db, d, t);
var s = d.Train(t);
s.rank++;
s.lv = new int[TrainingTable.Stats.Length];
return null;
}
public static string RankName(OutGameData db, int rank)
{
var r = db.Training.RankOf(rank);
return r != null ? r.nameKo : "";
}
}
}