feat: 빈사/부활 시스템 및 ReviveEffect 추가

- PlayerNetworkController에 Revive(healthPercent) 메서드와 OnRevived 이벤트 추가

- ReviveEffect 스킬 이펙트 구현 (Area/Ally 타겟팅, healthPercent로 체력 복구)

- GameManager가 OnRevived 구독하여 alivePlayers 동적 복구

- GameManager.Update에서 나중에 스폰된 플레이어 자동 구독 (MPP 대응)

- SkillCancelReason에 Revive 추가

- 부활 스킬/이펙트 ScriptableObject 에셋 생성 (치유 클립 임시 사용)

- PlayerSkillDebugMenu에 즉사/부활/리스폰/스폰/Client1 스킬 디버그 메뉴 추가

- PlayerAbnormalityDebugHUD에 부활 버튼 추가

- DebugExecuteSkillAsServer에 실패 원인 로그 추가

- AGENTS.md에 코드 변경 후 force reload 규칙 추가
This commit is contained in:
2026-03-28 21:03:28 +09:00
parent 057b17e6cc
commit 282e4b29c4
12 changed files with 385 additions and 9 deletions

View File

@@ -46,7 +46,7 @@ namespace Colosseum.Player
"Assets/_Game/Data/Skills/Data_Skill_Player_보호막.asset",
"Assets/_Game/Data/Skills/Data_Skill_Player_방어태세.asset",
"Assets/_Game/Data/Skills/Data_Skill_Player_투사체.asset",
"Assets/_Game/Data/Skills/Data_Skill_Player_구르기.asset",
"Assets/_Game/Data/Skills/Data_Skill_Player_부활.asset",
};
private static readonly string[] DpsLoadoutPaths =
@@ -566,27 +566,48 @@ namespace Colosseum.Player
public bool DebugExecuteSkillAsServer(int slotIndex)
{
if (!IsServer)
{
Debug.LogWarning($"[Debug] DebugExecuteSkillAsServer 실패: 서버가 아님 (IsServer=false)");
return false;
}
EnsureRuntimeReferences();
if (slotIndex < 0 || slotIndex >= skillSlots.Length)
{
Debug.LogWarning($"[Debug] DebugExecuteSkillAsServer 실패: 슬롯 인덱스 범위 초과 (slotIndex={slotIndex}, length={skillSlots.Length})");
return false;
}
SkillLoadoutEntry loadoutEntry = GetSkillLoadout(slotIndex);
SkillData skill = loadoutEntry != null ? loadoutEntry.BaseSkill : null;
if (skill == null)
{
Debug.LogWarning($"[Debug] DebugExecuteSkillAsServer 실패: 슬롯 {slotIndex}이 비어있음");
return false;
}
if (actionState != null && !actionState.CanStartSkill(skill))
{
Debug.LogWarning($"[Debug] DebugExecuteSkillAsServer 실패: CanStartSkill=false (IsDead={actionState.IsDead}, CanUseSkills={actionState.CanUseSkills})");
return false;
}
if (skillController == null || skillController.IsExecutingSkill || skillController.IsOnCooldown(skill))
{
string reason = skillController == null ? "skillController=null" :
skillController.IsExecutingSkill ? "스킬 실행 중" :
skillController.IsOnCooldown(skill) ? "쿨다운 중" : "";
Debug.LogWarning($"[Debug] DebugExecuteSkillAsServer 실패: {reason}");
return false;
}
float actualManaCost = GetActualManaCost(loadoutEntry);
if (networkController != null && networkController.Mana < actualManaCost)
{
Debug.LogWarning($"[Debug] DebugExecuteSkillAsServer 실패: MP 부족 (need={actualManaCost:F1}, have={networkController.Mana:F1})");
return false;
}
if (networkController != null && actualManaCost > 0f)
{
@@ -594,6 +615,7 @@ namespace Colosseum.Player
}
BroadcastSkillExecutionRpc(slotIndex);
Debug.Log($"[Debug] DebugExecuteSkillAsServer 성공: Slot={slotIndex}, Skill={skill.SkillName}");
return true;
}