351 lines
11 KiB
C#
351 lines
11 KiB
C#
#if UNITY_EDITOR
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using Colosseum.Enemy;
|
|
|
|
namespace Colosseum.Editor
|
|
{
|
|
/// <summary>
|
|
/// BossEnemy 커스텀 인스펙터.
|
|
/// 페이즈 정보, HP, 상태를 시각적으로 표시합니다.
|
|
/// </summary>
|
|
[CustomEditor(typeof(BossEnemy))]
|
|
public class BossEnemyEditor : UnityEditor.Editor
|
|
{
|
|
private BossEnemy boss;
|
|
private bool showPhaseDetails = true;
|
|
private bool showThreatInfo = true;
|
|
private bool showDebugTools = true;
|
|
private int selectedPhaseIndex = 0;
|
|
|
|
private void OnEnable()
|
|
{
|
|
boss = (BossEnemy)target;
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
// 기본 인스펙터 그리기
|
|
DrawDefaultInspector();
|
|
|
|
if (!Application.isPlaying)
|
|
{
|
|
EditorGUILayout.HelpBox("런타임 디버그 정보는 플레이 모드에서만 표시됩니다.", MessageType.Info);
|
|
return;
|
|
}
|
|
|
|
EditorGUILayout.Space(10);
|
|
|
|
// 상태 요약
|
|
DrawStatusSummary();
|
|
|
|
EditorGUILayout.Space(10);
|
|
|
|
// 페이즈 정보
|
|
DrawPhaseInfo();
|
|
|
|
EditorGUILayout.Space(10);
|
|
|
|
// 위협 정보
|
|
DrawThreatInfo();
|
|
|
|
EditorGUILayout.Space(10);
|
|
|
|
// 디버그 도구
|
|
DrawDebugTools();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 상태 요약 표시
|
|
/// </summary>
|
|
private void DrawStatusSummary()
|
|
{
|
|
EditorGUILayout.LabelField("상태 요약", EditorStyles.boldLabel);
|
|
EditorGUI.indentLevel++;
|
|
|
|
// HP 바
|
|
float hpPercent = boss.MaxHealth > 0 ? boss.CurrentHealth / boss.MaxHealth : 0f;
|
|
DrawProgressBar("HP", hpPercent, GetHealthColor(hpPercent), $"{boss.CurrentHealth:F0} / {boss.MaxHealth:F0}");
|
|
|
|
// 상태 정보
|
|
EditorGUILayout.LabelField("현재 페이즈", $"{boss.CurrentPhaseIndex + 1} / {boss.TotalPhases}");
|
|
EditorGUILayout.LabelField("상태", GetStatusText());
|
|
|
|
if (boss.CurrentPhase != null)
|
|
{
|
|
EditorGUILayout.LabelField("페이즈명", boss.CurrentPhase.PhaseName);
|
|
}
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 페이즈 상세 정보 표시
|
|
/// </summary>
|
|
private void DrawPhaseInfo()
|
|
{
|
|
showPhaseDetails = EditorGUILayout.Foldout(showPhaseDetails, "페이즈 상세 정보", true);
|
|
|
|
if (!showPhaseDetails)
|
|
return;
|
|
|
|
EditorGUI.indentLevel++;
|
|
|
|
var phasesProp = serializedObject.FindProperty("phases");
|
|
if (phasesProp == null || phasesProp.arraySize == 0)
|
|
{
|
|
EditorGUILayout.HelpBox("등록된 페이즈가 없습니다.", MessageType.Warning);
|
|
EditorGUI.indentLevel--;
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < phasesProp.arraySize; i++)
|
|
{
|
|
var phaseProp = phasesProp.GetArrayElementAtIndex(i);
|
|
var phase = phaseProp.objectReferenceValue as BossPhaseData;
|
|
|
|
if (phase == null)
|
|
continue;
|
|
|
|
bool isCurrentPhase = i == boss.CurrentPhaseIndex;
|
|
bool isCompleted = i < boss.CurrentPhaseIndex;
|
|
|
|
// 페이즈 헤더
|
|
GUIStyle phaseStyle = new GUIStyle(EditorStyles.foldout);
|
|
if (isCurrentPhase)
|
|
phaseStyle.fontStyle = FontStyle.Bold;
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
|
|
// 상태 아이콘
|
|
string statusIcon = isCurrentPhase ? "▶" : (isCompleted ? "✓" : "○");
|
|
GUIContent phaseLabel = new GUIContent($"{statusIcon} Phase {i + 1}: {phase.PhaseName}");
|
|
|
|
EditorGUILayout.LabelField(phaseLabel, GUILayout.Width(200));
|
|
|
|
// 전환 조건
|
|
EditorGUILayout.LabelField($"[{phase.TransitionType}]", EditorStyles.miniLabel, GUILayout.Width(100));
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
if (isCurrentPhase)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
EditorGUILayout.LabelField($"전환 조건: {GetTransitionConditionText(phase)}");
|
|
EditorGUILayout.LabelField($"경과 시간: {boss.PhaseElapsedTime:F1}초");
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
EditorGUILayout.Space(2);
|
|
}
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 위협 정보 표시
|
|
/// </summary>
|
|
private void DrawThreatInfo()
|
|
{
|
|
showThreatInfo = EditorGUILayout.Foldout(showThreatInfo, "위협 정보", true);
|
|
|
|
if (!showThreatInfo)
|
|
return;
|
|
|
|
EditorGUI.indentLevel++;
|
|
|
|
if (!boss.UseThreatSystem)
|
|
{
|
|
EditorGUILayout.HelpBox("위협 시스템이 비활성화되어 있습니다.", MessageType.Info);
|
|
EditorGUI.indentLevel--;
|
|
return;
|
|
}
|
|
|
|
EditorGUILayout.LabelField("위협 테이블", EditorStyles.boldLabel);
|
|
EditorGUILayout.TextArea(boss.GetThreatDebugSummary(), GUILayout.MinHeight(70f));
|
|
|
|
if (GUILayout.Button("위협 초기화"))
|
|
{
|
|
boss.ClearAllThreat();
|
|
}
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 디버그 도구 표시
|
|
/// </summary>
|
|
private void DrawDebugTools()
|
|
{
|
|
showDebugTools = EditorGUILayout.Foldout(showDebugTools, "디버그 도구", true);
|
|
|
|
if (!showDebugTools)
|
|
return;
|
|
|
|
EditorGUI.indentLevel++;
|
|
|
|
EditorGUILayout.HelpBox("이 도구는 서버에서만 작동합니다.", MessageType.Info);
|
|
|
|
// 페이즈 강제 전환
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.LabelField("페이즈 강제 전환", GUILayout.Width(120));
|
|
selectedPhaseIndex = EditorGUILayout.IntSlider(selectedPhaseIndex, 0, Mathf.Max(0, boss.TotalPhases - 1));
|
|
if (GUILayout.Button("전환", GUILayout.Width(60)))
|
|
{
|
|
if (Application.isPlaying)
|
|
{
|
|
boss.ForcePhaseTransition(selectedPhaseIndex);
|
|
}
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUILayout.Space(5);
|
|
|
|
// 현재 페이즈 재시작
|
|
if (GUILayout.Button("현재 페이즈 재시작"))
|
|
{
|
|
if (Application.isPlaying)
|
|
{
|
|
boss.RestartCurrentPhase();
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.Space(5);
|
|
|
|
// HP 조작
|
|
EditorGUILayout.LabelField("HP 조작", EditorStyles.boldLabel);
|
|
EditorGUILayout.BeginHorizontal();
|
|
if (GUILayout.Button("HP 10%"))
|
|
{
|
|
SetBossHP(0.1f);
|
|
}
|
|
if (GUILayout.Button("HP 30%"))
|
|
{
|
|
SetBossHP(0.3f);
|
|
}
|
|
if (GUILayout.Button("HP 50%"))
|
|
{
|
|
SetBossHP(0.5f);
|
|
}
|
|
if (GUILayout.Button("HP 100%"))
|
|
{
|
|
SetBossHP(1f);
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUILayout.Space(5);
|
|
|
|
// 커스텀 조건
|
|
EditorGUILayout.LabelField("커스텀 조건 설정", EditorStyles.boldLabel);
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.LabelField("조건 ID:", GUILayout.Width(60));
|
|
string conditionId = EditorGUILayout.TextField("Enraged");
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
if (GUILayout.Button("활성화"))
|
|
{
|
|
boss.SetCustomCondition(conditionId, true);
|
|
}
|
|
if (GUILayout.Button("비활성화"))
|
|
{
|
|
boss.SetCustomCondition(conditionId, false);
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
/// <summary>
|
|
/// HP 설정 (서버에서만)
|
|
/// </summary>
|
|
private void SetBossHP(float percent)
|
|
{
|
|
if (!Application.isPlaying)
|
|
return;
|
|
|
|
float targetHP = boss.MaxHealth * percent;
|
|
float damage = boss.CurrentHealth - targetHP;
|
|
|
|
if (damage > 0)
|
|
{
|
|
boss.TakeDamage(damage);
|
|
}
|
|
else if (damage < 0)
|
|
{
|
|
boss.Heal(-damage);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 진행 바 그리기
|
|
/// </summary>
|
|
private void DrawProgressBar(string label, float value, Color color, string text = "")
|
|
{
|
|
Rect rect = EditorGUILayout.GetControlRect();
|
|
rect.height = 20f;
|
|
|
|
// 레이블
|
|
Rect labelRect = new Rect(rect.x, rect.y, 60, rect.height);
|
|
EditorGUI.LabelField(labelRect, label);
|
|
|
|
// 바
|
|
Rect barRect = new Rect(rect.x + 65, rect.y, rect.width - 65, rect.height);
|
|
EditorGUI.DrawRect(barRect, new Color(0.2f, 0.2f, 0.2f));
|
|
|
|
Rect fillRect = new Rect(barRect.x, barRect.y, barRect.width * Mathf.Clamp01(value), barRect.height);
|
|
EditorGUI.DrawRect(fillRect, color);
|
|
|
|
// 텍스트
|
|
if (!string.IsNullOrEmpty(text))
|
|
{
|
|
GUIStyle centeredStyle = new GUIStyle(EditorStyles.label)
|
|
{
|
|
alignment = TextAnchor.MiddleCenter
|
|
};
|
|
EditorGUI.LabelField(barRect, text, centeredStyle);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// HP 비율에 따른 색상 반환
|
|
/// </summary>
|
|
private Color GetHealthColor(float percent)
|
|
{
|
|
if (percent > 0.6f)
|
|
return new Color(0.2f, 0.8f, 0.2f); // 녹색
|
|
if (percent > 0.3f)
|
|
return new Color(0.9f, 0.7f, 0.1f); // 노란색
|
|
return new Color(0.9f, 0.2f, 0.2f); // 빨간색
|
|
}
|
|
|
|
/// <summary>
|
|
/// 상태 텍스트 반환
|
|
/// </summary>
|
|
private string GetStatusText()
|
|
{
|
|
if (boss.IsDead)
|
|
return "<color=red>사망</color>";
|
|
if (boss.IsTransitioning)
|
|
return "<color=yellow>페이즈 전환 중</color>";
|
|
return "<color=green>활성</color>";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 전환 조건 텍스트 반환
|
|
/// </summary>
|
|
private string GetTransitionConditionText(BossPhaseData phase)
|
|
{
|
|
return phase.TransitionType switch
|
|
{
|
|
PhaseTransitionType.HealthPercent => $"HP ≤ {phase.HealthPercentThreshold * 100:F0}%",
|
|
PhaseTransitionType.TimeElapsed => $"시간 ≥ {phase.TimeThreshold:F0}초",
|
|
PhaseTransitionType.CustomCondition => $"조건: {phase.CustomConditionId}",
|
|
PhaseTransitionType.Manual => "수동 전환",
|
|
_ => "알 수 없음"
|
|
};
|
|
}
|
|
}
|
|
}
|
|
#endif
|