ThreeKingdomsSlingshot/Assets/Scripts/Runtime/Skills/SkillDef.cs

170 lines
5.8 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 TKS.OutGame;
using UnityEngine;
namespace TKS
{
public enum SkillTrigger
{
/// <summary>액티브 · 다음 슬링샷 1회에 붙는다(예약 · 행동 전 다시 탭 = 취소 · 쿨 소모 없음).</summary>
NextAction,
/// <summary>액티브 · 즉시 발동(행동 소모 없음).</summary>
Instant,
/// <summary>패시브 · 상시.</summary>
Always
}
/// <summary>스킬 효과 1개(effect_key 1개 + 값). 키가 하나뿐인 행은 p2·p3 = 그 키의 조건·보조값.</summary>
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,
};
}
}
/// <summary>skills.csv 1행의 전투용 정의(SkillInfoDb.Skill → effect_key 를 키 규약대로 풀어 둠).</summary>
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<SkillEffect> Effects = new List<SkillEffect>();
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;
}
/// <summary>레벨 계수 = 1 + lv_scale·(lv−1) (lv 는 1~lv_max 로 자름).</summary>
public float LevelFactor(int lv)
{
return 1f + LvScale * (Mathf.Clamp(lv, 1, LvMax) - 1);
}
/// <summary>레벨·★ 배율(패시브 ★5 = evolve.csv passive_x)을 적용한 효과 목록.</summary>
public List<SkillEffect> ScaledEffects(int lv, float starMult)
{
float f = LevelFactor(lv) * (IsActive ? 1f : starMult);
var list = new List<SkillEffect>();
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;
}
}
/// <summary>스킬·영웅 표 조회(Resources/OutGame 의 SkillInfoDb · HeroDb = 임포트 자산 · 전투 시작마다 다시 읽음).</summary>
public static class SkillCatalog
{
static Dictionary<string, SkillDef> 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<string, SkillDef>();
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<SkillDef> 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;
}
/// <summary>적 무장 → heroes.csv 영웅(아트 id 가 같으면 · 없으면 이름이 같은 영웅) · 병사 유닛 제외 · 없으면 null.</summary>
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;
}
}
}