feat: 피격 반응 면역을 경직/넉백/다운으로 분리

- 상태이상 데이터와 관리자에서 단일 피격 면역을 경직, 넉백, 다운 개별 면역으로 분리

- 플레이어 프리팹과 디버그 메뉴, 공용 경직 애니메이션을 갱신해 분리된 면역 상태를 테스트 가능하게 정리

- PlayMode 테스트를 추가해 각 면역이 대응하는 반응만 차단하는지 검증
This commit is contained in:
2026-04-09 23:22:02 +09:00
parent 7776f7ed05
commit 0fa23d4389
17 changed files with 42220 additions and 32 deletions

View File

@@ -71,8 +71,14 @@ namespace Colosseum.Abnormalities
[Tooltip("보호막 계열 상태인지 여부 (보호막 인스턴스 동기화용)")]
public bool isShieldState = false;
[Tooltip("활성 중에는 일반 피격 반응(경직, 넉백, 다운)을 무시할지 여부")]
public bool ignoreHitReaction = false;
[Tooltip("활성 중에는 경직을 무시할지 여부")]
public bool ignoreStagger = false;
[Tooltip("활성 중에는 넉백을 무시할지 여부")]
public bool ignoreKnockback = false;
[Tooltip("활성 중에는 다운을 무시할지 여부")]
public bool ignoreDown = false;
[Header("시각 효과")]
[Tooltip("이상 상태가 유지되는 동안 대상에 붙일 루핑 VFX 프리팹")]

View File

@@ -32,7 +32,9 @@ namespace Colosseum.Abnormalities
private int stunCount;
private int silenceCount;
private int invincibleCount;
private int hitReactionImmuneCount;
private int staggerImmuneCount;
private int knockbackImmuneCount;
private int downImmuneCount;
private float slowMultiplier = 1f;
private float incomingDamageMultiplier = 1f;
@@ -40,7 +42,9 @@ namespace Colosseum.Abnormalities
private NetworkVariable<int> syncedStunCount = new NetworkVariable<int>(0);
private NetworkVariable<int> syncedSilenceCount = new NetworkVariable<int>(0);
private NetworkVariable<int> syncedInvincibleCount = new NetworkVariable<int>(0);
private NetworkVariable<int> syncedHitReactionImmuneCount = new NetworkVariable<int>(0);
private NetworkVariable<int> syncedStaggerImmuneCount = new NetworkVariable<int>(0);
private NetworkVariable<int> syncedKnockbackImmuneCount = new NetworkVariable<int>(0);
private NetworkVariable<int> syncedDownImmuneCount = new NetworkVariable<int>(0);
private NetworkVariable<float> syncedSlowMultiplier = new NetworkVariable<float>(1f);
// 네트워크 동기화용 데이터
@@ -62,9 +66,19 @@ namespace Colosseum.Abnormalities
public bool IsInvincible => GetCurrentInvincibleCount() > 0;
/// <summary>
/// 일반 피격 반응 무시 상태 여부
/// 경직 면역 상태 여부
/// </summary>
public bool IsHitReactionImmune => GetCurrentHitReactionImmuneCount() > 0;
public bool IsStaggerImmune => GetCurrentStaggerImmuneCount() > 0;
/// <summary>
/// 넉백 면역 상태 여부
/// </summary>
public bool IsKnockbackImmune => GetCurrentKnockbackImmuneCount() > 0;
/// <summary>
/// 다운 면역 상태 여부
/// </summary>
public bool IsDownImmune => GetCurrentDownImmuneCount() > 0;
/// <summary>
/// 이동 속도 배율 (1.0 = 기본, 0.5 = 50% 감소)
@@ -139,7 +153,9 @@ namespace Colosseum.Abnormalities
syncedStunCount.OnValueChanged += HandleSyncedStunChanged;
syncedSilenceCount.OnValueChanged += HandleSyncedSilenceChanged;
syncedInvincibleCount.OnValueChanged += HandleSyncedInvincibleChanged;
syncedHitReactionImmuneCount.OnValueChanged += HandleSyncedHitReactionImmuneChanged;
syncedStaggerImmuneCount.OnValueChanged += HandleSyncedStaggerImmuneChanged;
syncedKnockbackImmuneCount.OnValueChanged += HandleSyncedKnockbackImmuneChanged;
syncedDownImmuneCount.OnValueChanged += HandleSyncedDownImmuneChanged;
syncedSlowMultiplier.OnValueChanged += HandleSyncedSlowChanged;
if (networkController != null)
@@ -161,7 +177,9 @@ namespace Colosseum.Abnormalities
syncedStunCount.OnValueChanged -= HandleSyncedStunChanged;
syncedSilenceCount.OnValueChanged -= HandleSyncedSilenceChanged;
syncedInvincibleCount.OnValueChanged -= HandleSyncedInvincibleChanged;
syncedHitReactionImmuneCount.OnValueChanged -= HandleSyncedHitReactionImmuneChanged;
syncedStaggerImmuneCount.OnValueChanged -= HandleSyncedStaggerImmuneChanged;
syncedKnockbackImmuneCount.OnValueChanged -= HandleSyncedKnockbackImmuneChanged;
syncedDownImmuneCount.OnValueChanged -= HandleSyncedDownImmuneChanged;
syncedSlowMultiplier.OnValueChanged -= HandleSyncedSlowChanged;
if (networkController != null)
@@ -447,10 +465,14 @@ namespace Colosseum.Abnormalities
{
bool enteredStun = false;
if (data.ignoreHitReaction)
{
hitReactionImmuneCount++;
}
if (data.ignoreStagger)
staggerImmuneCount++;
if (data.ignoreKnockback)
knockbackImmuneCount++;
if (data.ignoreDown)
downImmuneCount++;
switch (data.controlType)
{
@@ -482,10 +504,14 @@ namespace Colosseum.Abnormalities
private void RemoveControlEffect(AbnormalityData data)
{
if (data.ignoreHitReaction)
{
hitReactionImmuneCount = Mathf.Max(0, hitReactionImmuneCount - 1);
}
if (data.ignoreStagger)
staggerImmuneCount = Mathf.Max(0, staggerImmuneCount - 1);
if (data.ignoreKnockback)
knockbackImmuneCount = Mathf.Max(0, knockbackImmuneCount - 1);
if (data.ignoreDown)
downImmuneCount = Mathf.Max(0, downImmuneCount - 1);
switch (data.controlType)
{
@@ -542,7 +568,11 @@ namespace Colosseum.Abnormalities
private int GetCurrentInvincibleCount() => IsServer ? invincibleCount : syncedInvincibleCount.Value;
private int GetCurrentHitReactionImmuneCount() => IsServer ? hitReactionImmuneCount : syncedHitReactionImmuneCount.Value;
private int GetCurrentStaggerImmuneCount() => IsServer ? staggerImmuneCount : syncedStaggerImmuneCount.Value;
private int GetCurrentKnockbackImmuneCount() => IsServer ? knockbackImmuneCount : syncedKnockbackImmuneCount.Value;
private int GetCurrentDownImmuneCount() => IsServer ? downImmuneCount : syncedDownImmuneCount.Value;
private float GetCurrentSlowMultiplier() => IsServer ? slowMultiplier : syncedSlowMultiplier.Value;
@@ -554,7 +584,9 @@ namespace Colosseum.Abnormalities
syncedStunCount.Value = stunCount;
syncedSilenceCount.Value = silenceCount;
syncedInvincibleCount.Value = invincibleCount;
syncedHitReactionImmuneCount.Value = hitReactionImmuneCount;
syncedStaggerImmuneCount.Value = staggerImmuneCount;
syncedKnockbackImmuneCount.Value = knockbackImmuneCount;
syncedDownImmuneCount.Value = downImmuneCount;
syncedSlowMultiplier.Value = slowMultiplier;
}
@@ -636,7 +668,23 @@ namespace Colosseum.Abnormalities
OnAbnormalitiesChanged?.Invoke();
}
private void HandleSyncedHitReactionImmuneChanged(int oldValue, int newValue)
private void HandleSyncedStaggerImmuneChanged(int oldValue, int newValue)
{
if (oldValue == newValue)
return;
OnAbnormalitiesChanged?.Invoke();
}
private void HandleSyncedKnockbackImmuneChanged(int oldValue, int newValue)
{
if (oldValue == newValue)
return;
OnAbnormalitiesChanged?.Invoke();
}
private void HandleSyncedDownImmuneChanged(int oldValue, int newValue)
{
if (oldValue == newValue)
return;