130 lines
7.1 KiB
C#
130 lines
7.1 KiB
C#
// ─────────────────────────────────────────────────────────────────────────────
|
|
// WLReactionSettings.cs — 전투 반응(연쇄 처치 · 군집 폭발 · 데미지 합산 윈도우) 값의 단일 출처(SOT · C45)
|
|
//
|
|
// PD 지시 #813 · 발주서 WL-811def §1-2 · 설계안 WL-811a §C 811e 행 · 기준서 v1 §B 요소 2 (2026-09-09)
|
|
//
|
|
// 에셋 경로(고정): Assets/WL/Combat/Settings/Resources/WL/WLReactionSettings.asset
|
|
// → Resources.Load<WLReactionSettings>("WL/WLReactionSettings") 로 1회 로드 후 캐시.
|
|
// 에셋이 없거나 enabled = false 또는 RuntimeDisabled 면 KillChain · DamageAggregator 가 아무 것도 하지 않는다(C8).
|
|
// HUD 표시는 하지 않는다 — 이 파일의 시스템은 이벤트(KillChain.TierReached · DamageAggregator.Flushed)만 낸다(표시 = 813g U).
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
using System;
|
|
using UnityEngine;
|
|
|
|
namespace WL.Combat.Reaction
|
|
{
|
|
[Serializable]
|
|
public struct KillChainTier
|
|
{
|
|
[Tooltip("티어 이름(데이터 · HUD 문구는 813g 가 이 이름을 키로 쓴다).")]
|
|
public string name;
|
|
[Tooltip("이 티어에 도달하는 연쇄 처치 수.")]
|
|
public int kills;
|
|
}
|
|
|
|
[CreateAssetMenu(fileName = "WLReactionSettings", menuName = "WL/Reaction Settings", order = 322)]
|
|
public sealed class WLReactionSettings : ScriptableObject
|
|
{
|
|
public const string ResourcesPath = "WL/WLReactionSettings";
|
|
|
|
static WLReactionSettings s_cached;
|
|
static bool s_lookupDone;
|
|
|
|
/// <summary>설정 에셋(1회 로드 후 캐시). 없으면 null.</summary>
|
|
public static WLReactionSettings Instance
|
|
{
|
|
get
|
|
{
|
|
if (!s_lookupDone)
|
|
{
|
|
s_cached = Resources.Load<WLReactionSettings>(ResourcesPath);
|
|
s_lookupDone = true;
|
|
}
|
|
return s_cached;
|
|
}
|
|
}
|
|
|
|
/// <summary>진단·A/B 전용 런타임 스위치. 에셋을 건드리지 않고 이 반응만 끈다. Play 종료 시 자동 false.</summary>
|
|
public static bool RuntimeDisabled;
|
|
|
|
public static bool Enabled
|
|
{
|
|
get { var i = Instance; return i != null && i.enabled && !RuntimeDisabled; }
|
|
}
|
|
|
|
public static void ClearCache() { s_cached = null; s_lookupDone = false; }
|
|
|
|
// ─────────────────────────────────────────── 전체 스위치
|
|
[Header("전체 스위치")]
|
|
[Tooltip("끄면 연쇄 처치 카운터 · 군집 폭발 · 데미지 합산이 전부 비활성(이벤트 0). 롤백 1순위.")]
|
|
public bool enabled = true;
|
|
|
|
[Tooltip("티어 도달 · 폭발 · 합산 플러시를 Console 에 남긴다(검증용 · GC 발생).")]
|
|
public bool verboseLog = false;
|
|
|
|
// ─────────────────────────────────────────── 연쇄 처치
|
|
[Header("연쇄 처치 (Killed · 윈도우 안 연속 처치 카운터)")]
|
|
[Tooltip("연쇄 처치 카운터 사용 여부.")]
|
|
public bool killChainEnabled = true;
|
|
|
|
[Tooltip("연쇄 유지 시간(초 · unscaled). 마지막 처치로부터 이 시간 안에 다음 처치가 오면 연쇄가 이어진다. 기준서 §B 요소 2 = 3 s.")]
|
|
public float killChainWindowSeconds = 3f;
|
|
|
|
[Tooltip("메인 PC 가 직접 처치한 것만 센다(killer == 메인 PC). off 면 도트·펫·소환수 처치도 센다.")]
|
|
public bool killChainRequireMainPCKiller = false;
|
|
|
|
[Tooltip("몬스터 소환수(eSubRol.Summon) 처치도 센다.")]
|
|
public bool killChainCountSummons = true;
|
|
|
|
[Tooltip("연쇄 위치(무게중심) 계산에 기억하는 최근 처치 수(버퍼 용량 · 첫 사용 때 할당).")]
|
|
public int killChainBufferSize = 16;
|
|
|
|
[Tooltip("티어 표(오름차순). 연쇄 수가 kills 와 같아지는 순간 TierReached 를 1회 낸다. 기준서 제안 2/3/5/8.")]
|
|
public KillChainTier[] tiers = new KillChainTier[]
|
|
{
|
|
new KillChainTier { name = "DOUBLE", kills = 2 },
|
|
new KillChainTier { name = "TRIPLE", kills = 3 },
|
|
new KillChainTier { name = "RAMPAGE", kills = 5 },
|
|
new KillChainTier { name = "MASSACRE", kills = 8 },
|
|
};
|
|
|
|
// ─────────────────────────────────────────── 군집 폭발
|
|
[Header("군집 폭발 (티어 도달 → 처치 무게중심에 VFX 1개 · EffectBudget.ClusterBurst 상한 1)")]
|
|
[Tooltip("군집 폭발 사용 여부.")]
|
|
public bool clusterBurstEnabled = true;
|
|
|
|
[Tooltip("폭발을 내는 최소 티어 인덱스(tiers 배열 기준 · 0 = DOUBLE · 1 = TRIPLE).")]
|
|
public int clusterBurstMinTier = 1;
|
|
|
|
[Tooltip("Assets/Res_Addr/Effect/<이름>.prefab — InGameInfo.Show_Effect 로 풀에서 꺼낸다(에셋 인벤토리 실존 확인 = BoomHit · 대안 FireballHit · Effect_STR_EXTRA_SPLASH).")]
|
|
public string clusterBurstPrefab = "BoomHit";
|
|
|
|
[Tooltip("폭발 슬롯(EffectBudget.ClusterBurst)을 잡아 두는 시간(초 · unscaled). 이 시간 안의 다음 폭발은 스킵(동시 ≤ 1).")]
|
|
public float clusterBurstHoldSeconds = 1f;
|
|
|
|
[Tooltip("무게중심에서 위로 띄우는 높이(m).")]
|
|
public float clusterBurstHeightOffset = 0.3f;
|
|
|
|
[Tooltip("무게중심이 화면 밖(EffectBudget.IsInView)이면 스킵.")]
|
|
public bool clusterBurstRequireInView = true;
|
|
|
|
// ─────────────────────────────────────────── 데미지 합산
|
|
[Header("데미지 합산 윈도우 (HitConfirmed → 대상별 합산 → Flushed 이벤트 · 표시는 813g)")]
|
|
[Tooltip("합산 사용 여부.")]
|
|
public bool damageMergeEnabled = true;
|
|
|
|
[Tooltip("첫 타격부터 이 시간(초 · unscaled) 안의 같은 대상 타격을 하나로 합쳐 Flushed 를 낸다. 기준서 §B 요소 2 = 0.25 s.")]
|
|
public float damageMergeWindowSeconds = 0.25f;
|
|
|
|
[Tooltip("처치 타격(isKill)은 윈도우를 기다리지 않고 즉시 플러시한다.")]
|
|
public bool damageMergeFlushOnKill = true;
|
|
|
|
[Tooltip("동시에 합산 중일 수 있는 대상 수(슬롯 · 첫 사용 때 할당). 초과하면 가장 오래된 슬롯을 먼저 플러시한다.")]
|
|
public int damageMergeSlots = 32;
|
|
|
|
[Tooltip("메인 PC 가 때린 것만 합산한다. off 면 모든 타격(PC 피격 포함)을 대상별로 합산.")]
|
|
public bool damageMergeMainPCOnly = false;
|
|
}
|
|
}
|