162 lines
6.2 KiB
C#
162 lines
6.2 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace EerieVillage.Skills
|
|
{
|
|
/// <summary>
|
|
/// SkillDataAsset 캐시 로드 + ISkillRuntime 인스턴스 생성 팩토리.
|
|
/// BT12-Dev v1 §3-3 정합.
|
|
/// - Resolve(cardId): Resources/Skills/ 에서 CardId 기준 조회
|
|
/// - Create(data): 타입 분기 후 런타임 인스턴스 반환
|
|
/// Phase 2-C에서 .asset 60종 추가 시 자동 적재.
|
|
/// </summary>
|
|
public static class SkillRuntimeFactory
|
|
{
|
|
private static Dictionary<string, SkillDataAsset> _cache;
|
|
|
|
/// <summary>
|
|
/// Resources/Skills/ 하위 SkillDataAsset 전체 캐시 적재.
|
|
/// 최초 Resolve 호출 시 자동 실행.
|
|
/// Phase 2-C .asset 추가 전까지 _cache.Count == 0 정상 상태.
|
|
/// </summary>
|
|
public static void EnsureLoaded()
|
|
{
|
|
if (_cache != null) return;
|
|
|
|
_cache = new Dictionary<string, SkillDataAsset>();
|
|
var assets = Resources.LoadAll<SkillDataAsset>("Skills");
|
|
if (assets == null) return;
|
|
|
|
foreach (var a in assets)
|
|
{
|
|
if (a != null && !string.IsNullOrEmpty(a.CardId) && !_cache.ContainsKey(a.CardId))
|
|
{
|
|
_cache[a.CardId] = a;
|
|
}
|
|
}
|
|
|
|
Debug.Log($"[SkillRuntimeFactory] SkillDataAsset {_cache.Count}종 캐시 적재 완료.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// cardId로 SkillDataAsset 조회. 없으면 null 반환.
|
|
/// </summary>
|
|
public static SkillDataAsset Resolve(string cardId)
|
|
{
|
|
EnsureLoaded();
|
|
if (string.IsNullOrEmpty(cardId)) return null;
|
|
return _cache.TryGetValue(cardId, out var data) ? data : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// SkillDataAsset 타입 분기 후 ISkillRuntime 인스턴스 생성.
|
|
/// BT12-Dev v1 §3-3 Factory 패턴.
|
|
/// </summary>
|
|
public static ISkillRuntime Create(SkillDataAsset data)
|
|
{
|
|
if (data == null) return null;
|
|
|
|
return data switch
|
|
{
|
|
ActiveSkillData a => new ActiveSkillRuntime(a),
|
|
PassiveSkillData p => new PassiveSkillRuntimeStub(p),
|
|
AwakeningSkillData w => new AwakeningSkillRuntimeStub(w),
|
|
_ => null
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// PD 지시 2026-05-13 — 레벨업 카드 풀 영역 완성·구현 5종만 한정.
|
|
/// A02 파이어볼·A13 저주 구체·A04 번개 충격·A05 좌/우 베기·A_Laser 용염 레이저.
|
|
/// 미완성 placeholder (A01·A03·A08·A14·A15) 영역 카드 풀 제외.
|
|
/// </summary>
|
|
static readonly HashSet<string> AvailableCardIds = new HashSet<string>
|
|
{
|
|
"A02", "A13", "A04", "A05", "A_Laser",
|
|
// PD 지시 2026-05-13 Phase A — A08 저주의 화살·A12 정화의 빛 신규 추가
|
|
"A08", "A12",
|
|
// PD 지시 2026-05-13 Phase B — A06 독 늪·A11 정령불 신규 추가
|
|
"A06", "A11"
|
|
};
|
|
|
|
/// <summary>
|
|
/// 레벨업 시 카드 3장 무작위 추출. Active 카테고리만. Phase 2-D 영역 BT12-MVP-A 통합.
|
|
/// PD 지시 2026-05-13 — AvailableCardIds 화이트리스트 필터 영역.
|
|
/// </summary>
|
|
public static List<ActiveSkillData> RandomDraw3()
|
|
{
|
|
EnsureLoaded();
|
|
var actives = new List<ActiveSkillData>();
|
|
foreach (var kvp in _cache)
|
|
{
|
|
if (kvp.Value is ActiveSkillData ad && AvailableCardIds.Contains(ad.CardId))
|
|
actives.Add(ad);
|
|
}
|
|
if (actives.Count == 0) return new List<ActiveSkillData>();
|
|
|
|
// 무작위 3장 (중복 X)
|
|
var pool = new List<ActiveSkillData>(actives);
|
|
var result = new List<ActiveSkillData>();
|
|
int draw = Mathf.Min(3, pool.Count);
|
|
for (int i = 0; i < draw; i++)
|
|
{
|
|
int idx = Random.Range(0, pool.Count);
|
|
result.Add(pool[idx]);
|
|
pool.RemoveAt(idx);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>캐시 강제 리셋 (에디터 툴·테스트용)</summary>
|
|
public static void InvalidateCache()
|
|
{
|
|
_cache = null;
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Phase 2 범위 외 stub 구현체
|
|
// PassiveSkillRuntime·AwakeningSkillRuntime은 Phase 2-C 이후 정식 구현 예정.
|
|
// -------------------------------------------------------------------------
|
|
|
|
/// <summary>
|
|
/// 패시브 스킬 런타임 stub. Phase 2-C에서 정식 구현으로 교체 예정.
|
|
/// </summary>
|
|
internal class PassiveSkillRuntimeStub : IPassiveSkill
|
|
{
|
|
private readonly PassiveSkillData _data;
|
|
public PassiveSkillRuntimeStub(PassiveSkillData data) { _data = data; }
|
|
|
|
public SkillDataAsset Data => _data;
|
|
public int StackLevel => 1;
|
|
public bool IsAlwaysOn => _data.IsAlwaysOn;
|
|
|
|
public void OnEquip(PlayerSkillInventory inventory) { }
|
|
public void OnUnequip() { }
|
|
public void Upgrade() { }
|
|
public void ApplyModifier(PlayerStats stats) { }
|
|
public void RemoveModifier(PlayerStats stats) { }
|
|
public void OnTrigger(PassiveTriggerContext ctx) { }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 각성 스킬 런타임 stub. Phase 2-E에서 정식 구현으로 교체 예정.
|
|
/// </summary>
|
|
internal class AwakeningSkillRuntimeStub : IAwakeningSkill
|
|
{
|
|
private readonly AwakeningSkillData _data;
|
|
public AwakeningSkillRuntimeStub(AwakeningSkillData data) { _data = data; }
|
|
|
|
public SkillDataAsset Data => _data;
|
|
public int StackLevel => 1;
|
|
public ActiveSkillData OriginalActive => _data.OriginalActive;
|
|
public PassiveSkillData[] RequiredPassives => _data.RequiredPassives;
|
|
public AwakeningPattern Pattern => _data.Pattern;
|
|
|
|
public void OnEquip(PlayerSkillInventory inventory) { }
|
|
public void OnUnequip() { }
|
|
public void Upgrade() { }
|
|
public void Awaken(PlayerSkillInventory inventory) { }
|
|
}
|
|
}
|