using System; using System.Collections.Generic; using GamePlay.Fight.Record; using Gameplay.Unit; using UnityEditor; using UnityEngine; namespace FightDebug { public class NormalAttackDetailWindow : EditorWindow { private GameUnit _targetUnit; private Vector2 _scrollPos; private List _expandedStates = new List(); private List _stackTraceExpandedStates = new List(); private void Update() { Repaint(); } private void OnEnable() { UnitDamageRecord.OnDetailWindowOpen(); } private void OnDisable() { UnitDamageRecord.OnDetailWindowClose(); } public static void ShowWindow(GameUnit unit) { var win = GetWindow("伤害详情: " + unit.GetDescString()); win._targetUnit = unit; win.Show(); win.Focus(); } private void OnGUI() { if (_targetUnit == null || _targetUnit.damageRecord == null) { EditorGUILayout.HelpBox("单位已销毁或无伤害记录", MessageType.Warning); return; } var records = _targetUnit.damageRecord.DetailRecords; GUILayout.BeginHorizontal(); if (GUILayout.Button("刷新", GUILayout.Width(60))) { Repaint(); } if (GUILayout.Button("清零", GUILayout.Width(60))) { _targetUnit.damageRecord.DetailRecords.Clear(); _expandedStates.Clear(); _stackTraceExpandedStates.Clear(); } GUILayout.EndHorizontal(); GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); if (records == null || records.Count == 0) { EditorGUILayout.HelpBox("暂无伤害记录", MessageType.Info); return; } _scrollPos = GUILayout.BeginScrollView(_scrollPos); if (_expandedStates.Count != records.Count) { _expandedStates.Clear(); for (int i = 0; i < records.Count; i++) { _expandedStates.Add(false); } } if (_stackTraceExpandedStates.Count != records.Count) { _stackTraceExpandedStates.Clear(); for (int i = 0; i < records.Count; i++) { _stackTraceExpandedStates.Add(false); } } for (int i = 0; i < records.Count; i++) { var record = records[i]; var isPureDamage = record.Source == EDamageDetailSource.PureDamage; var sourceColor = GetSourceColor(record); GUILayout.BeginVertical("box"); GUILayout.BeginHorizontal(); var sourceTag = isPureDamage ? "[真实]" : "[普通]"; var summary = $"{record.Time:F1}s → {record.TargetDesc} "; _expandedStates[i] = EditorGUILayout.Foldout(_expandedStates[i], summary, true); GUI.color = sourceColor; GUILayout.Label($"{sourceTag}伤害:", GUILayout.ExpandWidth(false)); GUI.color = Color.white; var damageStr = record.RealDamage.ToString(); if (record.HitType == "Critical") { damageStr += "(暴击)"; } else if (record.HitType == "SwipeHit") { damageStr += "(擦边)"; } var damageColor = GetHitTypeColor(record.HitType); GUI.color = damageColor; GUILayout.Label(damageStr, GUILayout.ExpandWidth(false)); GUI.color = Color.white; GUILayout.Label($"| 攻击: {record.BaseAttack:F0}", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); if (_expandedStates[i]) { GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.BeginVertical(); if (isPureDamage) { GUILayout.Label($"暴击率: -"); GUILayout.Label($"暴击伤害倍率: -"); GUILayout.Label($"计算前伤害: {record.DamageBeforeCalc:F0}"); GUILayout.Label($"目标防御力: -"); GUILayout.Label($"命中类型: {record.HitType}"); GUILayout.Label($"攻击力等级: -"); GUILayout.Label($"目标防御等级: -"); GUILayout.Label($"护盾减少: {record.ShieldReduced}"); GUILayout.Label($"HP减少: {record.HpReduced}"); } else { GUILayout.Label($"暴击率: {record.CritRate:P0}"); GUILayout.Label($"暴击伤害倍率: {record.CritDamageScale:F2}x"); GUILayout.Label($"计算前伤害: {record.DamageBeforeCalc:F0}"); GUILayout.Label($"目标防御力: {record.Defense:F0}"); GUILayout.Label($"命中类型: {record.HitType}"); GUILayout.Label($"攻击力等级: {record.AttackPowerLevel}"); GUILayout.Label($"目标防御等级: {record.TargetDefensePowerLevel}"); GUILayout.Label($"护盾减少: {record.ShieldReduced}"); GUILayout.Label($"HP减少: {record.HpReduced}"); } GUILayout.Label($"当前平A次数: {record.normalAttackCount}"); if (!string.IsNullOrEmpty(record.StackTrace)) { GUILayout.Space(4); _stackTraceExpandedStates[i] = EditorGUILayout.Foldout(_stackTraceExpandedStates[i], "堆栈信息", true); if (_stackTraceExpandedStates[i]) { EditorGUILayout.HelpBox(record.StackTrace, MessageType.None); } } GUILayout.EndVertical(); GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } GUILayout.EndScrollView(); GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); GUILayout.Label($"共 {records.Count} 条记录"); } private static Color GetSourceColor(DamageDetailRecord record) { if (record.Source == EDamageDetailSource.PureDamage) { return new Color(1f, 0.7f, 0.3f); } return new Color(0.5f, 0.8f, 0.5f); } private static Color GetHitTypeColor(string hitType) { switch (hitType) { case "Critical": return new Color(1f, 0.65f, 0f); case "SwipeHit": return new Color(0.3f, 0.7f, 1f); case "Miss": return Color.gray; case "LowPowerLevel": return Color.gray; case "PureDamage": return new Color(1f, 0.7f, 0.3f); default: return Color.white; } } } }