diff --git a/Assets/PerfectWorld/Scripts/Common/DebugSessionLog.cs b/Assets/PerfectWorld/Scripts/Common/DebugSessionLog.cs index f18fbd16bc..d7b0eb0327 100644 --- a/Assets/PerfectWorld/Scripts/Common/DebugSessionLog.cs +++ b/Assets/PerfectWorld/Scripts/Common/DebugSessionLog.cs @@ -1,59 +1,59 @@ -#if UNITY_EDITOR || DEVELOPMENT_BUILD -using System; -using System.IO; -using System.Text; -using UnityEngine; - -namespace BrewMonster -{ - /// NDJSON debug session logger (agent instrumentation). - public static class DebugSessionLog - { - const string LogPath = @"c:\Hoang\PW\debug-a9c674.log"; - const string SessionId = "a9c674"; - - public static void Write(string location, string message, string hypothesisId, object data, string runId = "pre-fix") - { - try - { - var ts = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); - var dataJson = data != null ? JsonUtility.ToJson(data) : "{}"; - var line = $"{{\"sessionId\":\"{SessionId}\",\"runId\":\"{runId}\",\"hypothesisId\":\"{hypothesisId}\",\"location\":\"{Escape(location)}\",\"message\":\"{Escape(message)}\",\"data\":{dataJson},\"timestamp\":{ts}}}\n"; - File.AppendAllText(LogPath, line, Encoding.UTF8); - } - catch { /* ignore */ } - } - - static string Escape(string s) => (s ?? "").Replace("\\", "\\\\").Replace("\"", "\\\""); - } - - [Serializable] - public class DebugSessionPayload - { - public int skillId; - public int hostId; - public int castTargetId; - public int targetId; - public int targetCount; - public bool castInTargets; - public bool alreadyFired; - public int flyClusterCount; - public int flyDelayMs; - public int eventId; - public string flyGfx; - public string prevState; - public string newState; - public int frame; - public float spawnX; - public float spawnY; - public float spawnZ; - public float targetX; - public float targetY; - public float targetZ; - public float radius; - public float offsetMag; - public bool isCluster; - public bool isArea; - } -} -#endif +#if UNITY_EDITOR || DEVELOPMENT_BUILD +using System; +using System.IO; +using System.Text; +using UnityEngine; + +namespace BrewMonster +{ + /// NDJSON debug session logger (agent instrumentation). + public static class DebugSessionLog + { + const string LogPath = @"c:\Hoang\PW\debug-a9c674.log"; + const string SessionId = "a9c674"; + + public static void Write(string location, string message, string hypothesisId, DebugSessionPayload data, string runId = "pre-fix") + { + try + { + var ts = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); + var dataJson = data != null ? JsonUtility.ToJson(data) : "{}"; + var line = $"{{\"sessionId\":\"{SessionId}\",\"runId\":\"{runId}\",\"hypothesisId\":\"{hypothesisId}\",\"location\":\"{Escape(location)}\",\"message\":\"{Escape(message)}\",\"data\":{dataJson},\"timestamp\":{ts}}}\n"; + File.AppendAllText(LogPath, line, Encoding.UTF8); + } + catch { /* ignore */ } + } + + static string Escape(string s) => (s ?? "").Replace("\\", "\\\\").Replace("\"", "\\\""); + } + + [Serializable] + public class DebugSessionPayload + { + public int skillId; + public int hostId; + public int castTargetId; + public int targetId; + public int targetCount; + public bool castInTargets; + public bool alreadyFired; + public int flyClusterCount; + public int flyDelayMs; + public int eventId; + public string flyGfx; + public string prevState; + public string newState; + public int frame; + public float spawnX; + public float spawnY; + public float spawnZ; + public float targetX; + public float targetY; + public float targetZ; + public float radius; + public float offsetMag; + public bool isCluster; + public bool isArea; + } +} +#endif diff --git a/Assets/PerfectWorld/Scripts/Skills/EC_HostSkillModel.cs b/Assets/PerfectWorld/Scripts/Skills/EC_HostSkillModel.cs index 97be7203c8..329051fecf 100644 --- a/Assets/PerfectWorld/Scripts/Skills/EC_HostSkillModel.cs +++ b/Assets/PerfectWorld/Scripts/Skills/EC_HostSkillModel.cs @@ -191,6 +191,10 @@ namespace BrewMonster.Scripts.Skills m_bInitialized = true; + // #region agent log + BMLogger.LogError($"[SkillSubList][H-A] CECHostSkillModel.Initialize prof={professionOverride ?? (CECGameRun.Instance?.GetHostPlayer()?.GetProfession() ?? -1)} profSkills={m_allProfSkills.Count} rankBuckets={m_allRankProfSkills.Count} hostNull={CECGameRun.Instance?.GetHostPlayer() == null}"); + // #endregion + // ÖØÐ´¦ÀíNPCLIST ProcessServiceList(); } @@ -544,6 +548,9 @@ namespace BrewMonster.Scripts.Skills public void InitAllSkillsOfCurProf(int? professionOverride) { + int npcSkillsCount = 0; + int matchedSkillsCount = 0; + int playerProfession = -1; // --- B1: Thu thập toàn bộ skill từ các NPC có cung cấp dịch vụ học skill --- HashSet npcSkills = new HashSet(); { @@ -574,20 +581,24 @@ namespace BrewMonster.Scripts.Skills } } + npcSkillsCount = npcSkills.Count; + var hostPlayer = CECGameRun.Instance?.GetHostPlayer(); + playerProfession = professionOverride ?? (hostPlayer != null ? hostPlayer.GetProfession() : -1); + // --- B2: Duyệt tất cả skill, lọc skill theo class hiện tại của người chơi --- uint curID = 0; while ((curID = ElementSkill.NextSkill(curID)) != 0) { ElementSkill pSkill = ElementSkill.Create(curID, 1); int cls = pSkill.GetCls(); - int playerCls = professionOverride ?? - CECGameRun.Instance.GetHostPlayer().GetProfession(); + int playerCls = playerProfession; bool isSameClass = (cls == playerCls || cls == 255); bool isProvidedByNPC = npcSkills.Contains(curID); if (isSameClass && isProvidedByNPC) { + matchedSkillsCount++; m_allProfSkills[(int)curID] = pSkill; if (!m_allRankProfSkills.ContainsKey(pSkill.GetRank())) m_allRankProfSkills[pSkill.GetRank()] = new List(); @@ -595,6 +606,10 @@ namespace BrewMonster.Scripts.Skills } } + // #region agent log + BMLogger.LogError($"[SkillSubList][H-B] InitAllSkillsOfCurProf npcSkills={npcSkillsCount} matched={matchedSkillsCount} profSkills={m_allProfSkills.Count} rankBuckets={m_allRankProfSkills.Count} profession={playerProfession} hostNull={hostPlayer == null}"); + // #endregion + foreach (var kvp in m_allRankProfSkills) { kvp.Value.Sort((lhs, rhs) => diff --git a/Assets/PerfectWorld/Scripts/UI/Dialogs/CDlgSkillSubList.cs b/Assets/PerfectWorld/Scripts/UI/Dialogs/CDlgSkillSubList.cs index bd749400e9..12eb0d1cfa 100644 --- a/Assets/PerfectWorld/Scripts/UI/Dialogs/CDlgSkillSubList.cs +++ b/Assets/PerfectWorld/Scripts/UI/Dialogs/CDlgSkillSubList.cs @@ -105,6 +105,9 @@ namespace BrewMonster.UI { if (m_bAllocRankDlgs || m_pSubRank == null || m_contentRoot == null) { + // #region agent log + BMLogger.LogError($"[SkillSubList][H-E] InitRankDlgs skipped reason={(m_bAllocRankDlgs ? "already_alloc" : (m_pSubRank == null ? "no_sub_rank" : "no_content_root"))} allocRank={m_bAllocRankDlgs} subSkill={m_pSubSkill != null} contentRoot={m_contentRoot != null}"); + // #endregion return; } m_bAllocRankDlgs = true; @@ -159,7 +162,13 @@ namespace BrewMonster.UI skill.Show(false); } - IReadOnlyDictionary> allRankProfSkills = CECHostSkillModel.Instance?.GetAllRankProfSkills(); + var skillModel = CECHostSkillModel.Instance; + IReadOnlyDictionary> allRankProfSkills = skillModel?.GetAllRankProfSkills(); + + // #region agent log + int totalCatalogSkills = allRankProfSkills != null ? allRankProfSkills.Values.Sum(l => l?.Count ?? 0) : -1; + BMLogger.LogError($"[SkillSubList][H-A] ResetDialog start modelNull={skillModel == null} rankBuckets={allRankProfSkills?.Count ?? -1} catalogSkills={totalCatalogSkills} isEvil={IsEvil()} allocRank={m_bAllocRankDlgs} subSkillTpl={m_pSubSkill != null} contentRoot={m_contentRoot != null} hostNull={GetHostPlayer() == null}"); + // #endregion for (CECTaoistRank taoistRank = CECTaoistRank.GetBaseRankBegin(); taoistRank != CECTaoistRank.GetBaseRankEnd(); @@ -191,6 +200,10 @@ namespace BrewMonster.UI ShowLastSelectedSkill(); } UpdateTotalSPText(); + + // #region agent log + BMLogger.LogError($"[SkillSubList][H-E] ResetDialog end shownSkills={m_skillSubCount} rankBuckets={allRankProfSkills?.Count ?? -1} isEvil={IsEvil()} allocRank={m_bAllocRankDlgs}"); + // #endregion } public void UpdateTotalSPText() @@ -280,29 +293,43 @@ namespace BrewMonster.UI if (allRankProfSkills == null) { + // #region agent log + BMLogger.LogError($"[SkillSubList][H-A] AddDlgsOfOneRank skip reason=allRankProfSkills_null rankId={rankID}"); + // #endregion return; } if (IsEvil() && taoistRank.IsGodRank()) { + // #region agent log + BMLogger.LogError($"[SkillSubList][H-C] AddDlgsOfOneRank skip reason=evil_hides_god rankId={rankID}"); + // #endregion return; } else if (!IsEvil() && taoistRank.IsEvilRank()) { + // #region agent log + BMLogger.LogError($"[SkillSubList][H-C] AddDlgsOfOneRank skip reason=non_evil_hides_evil rankId={rankID}"); + // #endregion return; } if (!allRankProfSkills.TryGetValue(rankID, out var rankItr) || rankItr == null || rankItr.Count == 0) { + // #region agent log + BMLogger.LogError($"[SkillSubList][H-A] AddDlgsOfOneRank skip reason=rank_empty rankId={rankID}"); + // #endregion return; } List rankSkills = new List(); + int overriddenSkipped = 0; foreach (var skillID in rankItr) { if (ElementSkill.IsOverridden((uint)skillID)) { - BMLogger.LogError("HoangDev: AddDlgsOfOneRank ElementSkill.IsOverridden for skillID " + skillID); + overriddenSkipped++; + BMLogger.LogError($"[SkillSubList][H-D] skill overridden skillId={skillID} rankId={rankID}"); continue; } /* bool bOnlyShowSkillCanLearn = GetGameUIMan()->m_pDlgSkillAction->IsOnlyShowSkillCanLearn(); @@ -323,10 +350,16 @@ namespace BrewMonster.UI } if (rankSkills.Count == 0) { - BMLogger.LogError("HoangDev: AddDlgsOfOneRank rankSkills.Count == 0"); + // #region agent log + BMLogger.LogError($"[SkillSubList][H-D] AddDlgsOfOneRank skip reason=all_overridden rankId={rankID} raw={rankItr.Count} overriddenSkipped={overriddenSkipped}"); + // #endregion return; } + // #region agent log + BMLogger.LogError($"[SkillSubList][H-E] AddDlgsOfOneRank adding rankId={rankID} raw={rankItr.Count} shown={rankSkills.Count} overriddenSkipped={overriddenSkipped} isEvil={IsEvil()}"); + // #endregion + AddRankSubDig(rankID); rankSkills.Sort(); foreach (int skillID in rankSkills)