using System.Collections.Generic;
using TKS.OutGame;
using UnityEngine;
namespace TKS
{
public enum SkillTrigger
{
/// 액티브 · 다음 슬링샷 1회에 붙는다(예약 · 행동 전 다시 탭 = 취소 · 쿨 소모 없음).
NextAction,
/// 액티브 · 즉시 발동(행동 소모 없음).
Instant,
/// 패시브 · 상시.
Always
}
/// 스킬 효과 1개(effect_key 1개 + 값). 키가 하나뿐인 행은 p2·p3 = 그 키의 조건·보조값.
public class SkillEffect
{
public string Key;
public float P;
public float A2;
public float A3;
public bool HasA2;
public bool HasA3;
public SkillEffect Scaled(float factor)
{
SkillKeys.Info info;
if (!SkillKeys.All.TryGetValue(Key, out info)) return this;
return new SkillEffect
{
Key = Key,
P = SkillKeys.Apply(info.Main, P, factor),
A2 = info.ScaleA2 && HasA2 ? A2 * factor : A2,
A3 = A3,
HasA2 = HasA2,
HasA3 = HasA3,
};
}
}
/// skills.csv 1행의 전투용 정의(SkillInfoDb.Skill → effect_key 를 키 규약대로 풀어 둠).
public class SkillDef
{
public string Id;
public string HeroId;
public string NameKo;
public bool IsActive;
public SkillTrigger Trigger;
public int Cooldown;
public int LvMax;
public float LvScale;
public bool NeedsImpl;
public readonly List Effects = new List();
public static SkillDef From(SkillInfoDb.Skill s)
{
var d = new SkillDef
{
Id = s.id,
HeroId = s.heroId,
NameKo = s.nameKo,
IsActive = s.kind == "active",
Trigger = s.trigger == "next_action" ? SkillTrigger.NextAction : s.trigger == "instant" ? SkillTrigger.Instant : SkillTrigger.Always,
Cooldown = s.cooldown,
LvMax = Mathf.Max(1, s.lvMax),
LvScale = s.lvScale,
NeedsImpl = s.needsImpl,
};
var keys = s.EffectKeys;
for (int i = 0; i < keys.Length; i++)
{
if (keys.Length > 1) d.Effects.Add(new SkillEffect { Key = keys[i], P = s.P(i) });
else d.Effects.Add(new SkillEffect { Key = keys[i], P = s.p1, A2 = s.p2, A3 = s.p3, HasA2 = s.HasP(1), HasA3 = s.HasP(2) });
}
return d;
}
/// 레벨 계수 = 1 + lv_scale·(lv−1) (lv 는 1~lv_max 로 자름).
public float LevelFactor(int lv)
{
return 1f + LvScale * (Mathf.Clamp(lv, 1, LvMax) - 1);
}
/// 레벨·★ 배율(패시브 ★5 = evolve.csv passive_x)을 적용한 효과 목록.
public List ScaledEffects(int lv, float starMult)
{
float f = LevelFactor(lv) * (IsActive ? 1f : starMult);
var list = new List();
foreach (var e in Effects) list.Add(e.Scaled(f));
return list;
}
public SkillEffect First(string key)
{
foreach (var e in Effects)
if (e.Key == key) return e;
return null;
}
}
/// 스킬·영웅 표 조회(Resources/OutGame 의 SkillInfoDb · HeroDb = 임포트 자산 · 전투 시작마다 다시 읽음).
public static class SkillCatalog
{
static Dictionary defs;
static SkillInfoDb source;
static int sourceCount;
public static void Invalidate()
{
defs = null;
}
static void Ensure()
{
var db = OutGameData.Default;
var s = db != null ? db.Skills : null;
if (defs != null && s == source && s != null && s.skills.Count == sourceCount) return;
defs = new Dictionary();
source = s;
sourceCount = s != null ? s.skills.Count : 0;
if (s == null) return;
foreach (var row in s.skills)
{
if (string.IsNullOrEmpty(row.id) || defs.ContainsKey(row.id)) continue;
defs[row.id] = SkillDef.From(row);
}
}
public static SkillDef Get(string id)
{
if (string.IsNullOrEmpty(id)) return null;
Ensure();
SkillDef d;
return defs.TryGetValue(id, out d) ? d : null;
}
public static IEnumerable All
{
get
{
Ensure();
return defs.Values;
}
}
public static HeroDb.Hero Hero(string id)
{
var db = OutGameData.Default;
return db != null && db.Heroes != null ? db.Heroes.Get(id) : null;
}
/// 적 무장 → heroes.csv 영웅(아트 id 가 같으면 · 없으면 이름이 같은 영웅) · 병사 유닛 제외 · 없으면 null.
public static HeroDb.Hero HeroForEnemy(string art, string name)
{
var db = OutGameData.Default;
if (db == null || db.Heroes == null) return null;
HeroDb.Hero byName = null;
foreach (var h in db.Heroes.heroes)
{
if (h.isSoldier) continue;
if (!string.IsNullOrEmpty(art) && h.art == art) return h;
if (byName == null && !string.IsNullOrEmpty(name) && h.nameKo == name) byName = h;
}
return byName;
}
}
}