From fa98c5b76c114c3027026b18b8b8a81ddb139354 Mon Sep 17 00:00:00 2001 From: Le Duc Anh Date: Wed, 8 Apr 2026 11:31:45 +0700 Subject: [PATCH 1/2] rotate weapon --- .../models/weapons/人物/斧锤/双手双斧/石斧/石斧.prefab | 6 +++--- .../models/weapons/人物/斧锤/双手长斧/宣花斧/宣花斧.prefab | 6 +++--- .../models/weapons/人物/斧锤/双手长斧/巨灵斧/巨灵斧.prefab | 6 +++--- .../models/weapons/人物/斧锤/双手长斧/铜钺/铜钺.prefab | 6 +++--- .../weapons/人物/斧锤/双手长锤/八角铜锤/八角铜锤.prefab | 6 +++--- .../models/weapons/人物/斧锤/双手长锤/工锤/工锤.prefab | 6 +++--- .../models/weapons/人物/斧锤/双手长锤/战锤/战锤.prefab | 6 +++--- .../models/weapons/人物/斧锤/双手长锤/瓦棱锤/瓦棱锤.prefab | 6 +++--- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手双斧/石斧/石斧.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手双斧/石斧/石斧.prefab index 7b7867f8d6..3975bc0505 100644 --- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手双斧/石斧/石斧.prefab +++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手双斧/石斧/石斧.prefab @@ -26,13 +26,13 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 3218176555537563708} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0.235, y: 0.001, z: 0.015} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} --- !u!33 &4570469791566163120 MeshFilter: m_ObjectHideFlags: 0 diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/宣花斧/宣花斧.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/宣花斧/宣花斧.prefab index 9096283180..0ef0ba83c2 100644 --- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/宣花斧/宣花斧.prefab +++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/宣花斧/宣花斧.prefab @@ -26,13 +26,13 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 4720678646282004868} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0.564, y: -0.061, z: -0.005} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} --- !u!33 &2558500868448674905 MeshFilter: m_ObjectHideFlags: 0 diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/巨灵斧/巨灵斧.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/巨灵斧/巨灵斧.prefab index aca39e2eef..2081ee511b 100644 --- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/巨灵斧/巨灵斧.prefab +++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/巨灵斧/巨灵斧.prefab @@ -26,13 +26,13 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2916308637203925776} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0.564, y: -0.061, z: -0.005} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} --- !u!33 &2359515785900208490 MeshFilter: m_ObjectHideFlags: 0 diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/铜钺/铜钺.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/铜钺/铜钺.prefab index e9aee96fcc..bfe19b4e6f 100644 --- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/铜钺/铜钺.prefab +++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长斧/铜钺/铜钺.prefab @@ -26,13 +26,13 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 4858308094309864508} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0.84, y: -0.064, z: -0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} --- !u!33 &5945091725935784906 MeshFilter: m_ObjectHideFlags: 0 diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/八角铜锤/八角铜锤.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/八角铜锤/八角铜锤.prefab index b2bb6634a8..a725f069ba 100644 --- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/八角铜锤/八角铜锤.prefab +++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/八角铜锤/八角铜锤.prefab @@ -26,13 +26,13 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 7515438785474843149} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0.564, y: -0.013, z: -0.005} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} --- !u!33 &4684279536110930119 MeshFilter: m_ObjectHideFlags: 0 diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/工锤/工锤.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/工锤/工锤.prefab index 0fcebfa340..4c0357f1c4 100644 --- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/工锤/工锤.prefab +++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/工锤/工锤.prefab @@ -26,13 +26,13 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6015463627169791726} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0.564, y: -0.013, z: -0.005} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} --- !u!33 &5659237752439739352 MeshFilter: m_ObjectHideFlags: 0 diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/战锤/战锤.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/战锤/战锤.prefab index 62726f9721..27273dffe3 100644 --- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/战锤/战锤.prefab +++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/战锤/战锤.prefab @@ -26,13 +26,13 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1197563511380039097} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0.564, y: -0.013, z: -0.005} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} --- !u!33 &133678441249318870 MeshFilter: m_ObjectHideFlags: 0 diff --git a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/瓦棱锤/瓦棱锤.prefab b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/瓦棱锤/瓦棱锤.prefab index 79cd2107d5..96d6e89f70 100644 --- a/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/瓦棱锤/瓦棱锤.prefab +++ b/Assets/ModelRenderer/Art/Models/models/weapons/人物/斧锤/双手长锤/瓦棱锤/瓦棱锤.prefab @@ -26,13 +26,13 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6982793425996143688} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0.564, y: -0.013, z: -0.005} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} --- !u!33 &1783189990820706467 MeshFilter: m_ObjectHideFlags: 0 From 93632c663988a941b65287a891fd8ccee933e90e Mon Sep 17 00:00:00 2001 From: Chomper9981 Date: Wed, 8 Apr 2026 13:44:12 +0700 Subject: [PATCH 2/2] fix perform proplem when load tasktrace --- .../Scripts/Task/ATaskTemplMan.cs | 53 ++++++++-------- .../PerfectWorld/Scripts/Task/UI/DlgTask.cs | 32 +++++++--- .../Scripts/Task/UI/DlgTaskTrace.cs | 1 + .../Scripts/UI/GamePlay/EC_GameUIMan.cs | 6 ++ Assets/Scripts/CECHostPlayer.cs | 5 ++ Assets/Scripts/CECUIManager.cs | 60 +++++++++++++------ 6 files changed, 101 insertions(+), 56 deletions(-) diff --git a/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs b/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs index 0aa18c8d5e..f9977e61f4 100644 --- a/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs +++ b/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs @@ -707,43 +707,40 @@ namespace BrewMonster.Scripts.Task return false; } - // 可接任务列表 // Available tasks list + // 可接任务列表(全量一次扫完;分帧接口见 ProcessAvailableTasksChunk) + // Available tasks list (full scan in one call; time-sliced API: ProcessAvailableTasksChunk) public void GetAvailableTasks(TaskInterface pPlayer, List lst) { if (lst == null) return; if (lst.Capacity < 256) lst.Capacity = 256; // 预留容量 // reserve capacity - - string log = ""; - - int count = m_TasksCanSeekOut.Count; - for (int i = 0; i < count; i++) + lst.Clear(); + int cursor = 0; + bool completed; + do { - ATaskTempl pTempl = m_TasksCanSeekOut[i]; + ProcessAvailableTasksChunk(pPlayer, lst, ref cursor, int.MaxValue, out completed); + } while (!completed); + } + + /// + /// Process up to maxSteps templates from m_TasksCanSeekOut; cursor is next index (0 = start of list). + /// 每次最多处理 maxSteps 个 m_TasksCanSeekOut 项;cursor 为下一待处理下标。 + /// + public void ProcessAvailableTasksChunk(TaskInterface pPlayer, List lst, ref int cursor, int maxSteps, out bool completed) + { + int count = m_TasksCanSeekOut.Count; + int processed = 0; + while (cursor < count && processed < maxSteps) + { + ATaskTempl pTempl = m_TasksCanSeekOut[cursor]; + cursor++; + processed++; if (pTempl == null) continue; - - // 如果等级条件不满足则跳过 // Skip if level requirements are not met if (!pTempl.CheckReachLevel(pPlayer)) continue; - - // 玩家可接此任务则加入列表 // If player can accept this task, add to list - - var failCode = pPlayer.CanDeliverTask(pTempl.m_FixedData.m_ID); - if (failCode == 0) - { + if (pPlayer.CanDeliverTask(pTempl.m_FixedData.m_ID) == 0) lst.Add(pTempl); - } - else - { - log += $"Task ID {pTempl.m_FixedData.m_ID} Fail : {failCode} \n"; - } - - // if (i % 1000 == 0) - // { - // Debug.Log($"--- {i % 1000} Find Available Task --- \n {log}"); - // log = ""; - // } } - - + completed = cursor >= count; } public uint GetTaskStorageId(uint id) diff --git a/Assets/PerfectWorld/Scripts/Task/UI/DlgTask.cs b/Assets/PerfectWorld/Scripts/Task/UI/DlgTask.cs index 67909fd581..73eca8f317 100644 --- a/Assets/PerfectWorld/Scripts/Task/UI/DlgTask.cs +++ b/Assets/PerfectWorld/Scripts/Task/UI/DlgTask.cs @@ -384,6 +384,8 @@ namespace BrewMonster.Scripts.Task.UI public void OnCommand_showtrace(string szCommand,bool state) { m_bShowTrace = state; Debug.Log($"[DlgTask] OnCommand_showtrace: state={m_bShowTrace}"); + if (state) + RebuildAcceptableQuestCache(); ShowTraceDialog(); } public void TraceTask(uint idTask) @@ -607,8 +609,6 @@ namespace BrewMonster.Scripts.Task.UI public void OnEventLButtonDown_Tv_Quest(uint itemData) { - // UpdateTask((int)itemData); - // POINT ptPos = pObj->GetPos(); // A3DVIEWPORTPARAM *p = m_pA3DEngine->GetActiveViewport()->GetParam(); // int x = GET_X_LPARAM(lParam) - ptPos.x - p->X; @@ -635,7 +635,7 @@ namespace BrewMonster.Scripts.Task.UI // if(pTree->GetHitArea(x,y) == AUITREEVIEW_RECT_FRAME) // CDlgWikiShortcut::PopQuestWiki(GetGameUIMan(),idTask); // } - + m_idSelTask = idTask; } // void OnEventMouseMove_Txt_QuestItem(WPARAM wParam, LPARAM lParam, AUIObject *pObj); @@ -917,9 +917,8 @@ namespace BrewMonster.Scripts.Task.UI } else if(showType2 == ShowType2.ST_NOT_RECIEVED) { - // Re-run GetAvailableTasks every trace refresh; m_vecTasksCanGet was only filled on quest UI events and stayed stale. - // 每次追踪刷新重新计算可接任务;原先仅在任务界面事件里更新列表,游戏中会一直停留在开局数据。 - RefreshVecTasksCanGet(pTask); + // Can-get list is refreshed only on level-up, quest state change (UpdateQuestView), trace toggle on, or minimion "可接" tab — not every tick. + // 可接列表仅在升级、任务变更、打开追踪、小窗切到可接时刷新,避免每帧扫全表拖垮 FPS。 tasks.Capacity = m_vecTasksCanGet.Count; tasks.AddRange(m_vecTasksCanGet); } @@ -1298,8 +1297,8 @@ namespace BrewMonster.Scripts.Task.UI } } - // Search view already rebuilt m_vecTasksCanGet inside SearchForTask(-1). - // 搜索页在 SearchForTask 内已更新 m_vecTasksCanGet。 + // Have-quest tab: rebuild can-get cache for trace minimion. Search tab: SearchForTask(-1) already filled m_vecTasksCanGet. + // 已接任务页:重建可接缓存。搜索页:SearchForTask 已写 m_vecTasksCanGet,勿二次全表扫描。 if (m_iType == 0) RefreshVecTasksCanGet(); @@ -1413,9 +1412,24 @@ namespace BrewMonster.Scripts.Task.UI /// 用 GetAvailableTasks 重建可接任务 ID 列表,与可接任务搜索树数据源一致。 /// private void RefreshVecTasksCanGet(CECTaskInterface pTaskIfKnown = null) + { + RebuildAcceptableQuestCache(pTaskIfKnown); + } + + /// + /// Rebuilds the cached list of quests the host may accept (trace minimion "可接", etc.). + /// Safe without a DlgTask instance — call from UI manager on level-up and similar. + /// 重建玩家当前可接任务 ID 缓存;可无对话框实例,由 UI 管理器在升级等时机调用。 + /// + public static void RebuildAcceptableQuestCache(CECTaskInterface pTaskIfKnown = null) { m_vecTasksCanGet.Clear(); - CECTaskInterface pTask = pTaskIfKnown ?? GetHostPlayer()?.GetTaskInterface(); + CECTaskInterface pTask = pTaskIfKnown; + if (pTask == null) + { + var run = EC_Game.GetGameRun(); + pTask = run?.GetHostPlayer()?.GetTaskInterface(); + } if (pTask == null) return; ATaskTemplMan pMan = EC_Game.GetTaskTemplateMan(); if (pMan == null) return; diff --git a/Assets/PerfectWorld/Scripts/Task/UI/DlgTaskTrace.cs b/Assets/PerfectWorld/Scripts/Task/UI/DlgTaskTrace.cs index 02be1aa6f4..0bb4ae9e0f 100644 --- a/Assets/PerfectWorld/Scripts/Task/UI/DlgTaskTrace.cs +++ b/Assets/PerfectWorld/Scripts/Task/UI/DlgTaskTrace.cs @@ -134,6 +134,7 @@ namespace BrewMonster.Scripts.Task.UI if(value) { m_nLastShowType2 = ShowType2.ST_NOT_RECIEVED; + DlgTask.RebuildAcceptableQuestCache(); } } public void OnShowDialog() diff --git a/Assets/PerfectWorld/Scripts/UI/GamePlay/EC_GameUIMan.cs b/Assets/PerfectWorld/Scripts/UI/GamePlay/EC_GameUIMan.cs index 62074575da..237d6459f8 100644 --- a/Assets/PerfectWorld/Scripts/UI/GamePlay/EC_GameUIMan.cs +++ b/Assets/PerfectWorld/Scripts/UI/GamePlay/EC_GameUIMan.cs @@ -357,6 +357,12 @@ namespace BrewMonster.UI return false; } + /// Quest main dialog (Win_Quest), created in Init. / 任务主界面,Init 时创建。 + public DlgTask GetDlgTask() + { + return m_pDlgTask; + } + public override void Init() { base.Init(); diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index bd12ed5487..ac583faefa 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -3159,6 +3159,8 @@ namespace BrewMonster // m_pLevelUpGFX.Start(true); PlayGfx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_LEVELUP), null, 1f, 1); //PLAYERMODEL_TYPEALL + EventBus.Publish(new HostPlayerLevelUpUIEvent()); + // // Popup notify bubble text // BubbleText(BUBBLE_LEVELUP, 0); // @@ -3714,6 +3716,9 @@ namespace BrewMonster /// Fired when selected target HUD should be hidden (deselect or switch). public struct TargetHUDClearEvent { } + /// Host leveled up — UI layer may refresh quest-offer lists, popups, etc. 玩家升级,UI 可刷新可接任务等。 + public struct HostPlayerLevelUpUIEvent { } + public struct GNDINFO { public float fGndHei; // Ground height diff --git a/Assets/Scripts/CECUIManager.cs b/Assets/Scripts/CECUIManager.cs index a84be8b8e2..e6bf282408 100644 --- a/Assets/Scripts/CECUIManager.cs +++ b/Assets/Scripts/CECUIManager.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using BrewMonster.PerfectWorld.Scripts.Utility.ChatFilter; using BrewMonster.Scripts.Chat.EmotionData; using BrewMonster.Scripts.Managers; +using BrewMonster.Scripts.Task.UI; +using BrewMonster.Scripts.UI; using UnityEngine; using TMPro; @@ -55,6 +57,7 @@ public class CECUIManager : MonoSingleton EventBus.Subscribe(ShowUINPC); EventBus.Subscribe(OnTargetHUDClear); + EventBus.Subscribe(OnHostPlayerLevelUpUI); EventBus.Subscribe(TryHideUINPC); EventBus.Subscribe(OnMessageBox); @@ -85,22 +88,26 @@ public class CECUIManager : MonoSingleton m_pDlgQuickBar1.UpdateShortcuts(); } - // Periodically update task UI (DlgTask and DlgTaskTrace) / 定期更新任务UI(DlgTask和DlgTaskTrace) - if (Time.unscaledTime >= _nextTaskUpdateTime) - { - _nextTaskUpdateTime = Time.unscaledTime + TASK_UPDATE_INTERVAL; - //if hostplayer is null, return - var hostPlayer = EC_Game.GetGameRun()?.GetHostPlayer(); - if(hostPlayer == null) - { - return; - } - UpdateTaskUI(); + // Task UI must run from this Update(): TickInvoker often never calls CECUIManager.Tick in practice + // (registration order, DDOL instance, or no TickInvoker in scene), so logs/body there never ran. + // 任务 UI 必须在此 Update 驱动:TickInvoker 在部分场景下根本不会调到本类 Tick。 + if (Time.unscaledTime < _nextTaskUpdateTime) + return; + _nextTaskUpdateTime = Time.unscaledTime + TASK_UPDATE_INTERVAL; - // Hiển thị thông tin đăng nhập khi người chơi đã vào game an toàn / Show login info when host player is ready - // Hàm này bên trong đã có cờ m_bAccountLoginInfoShown để tránh bị gọi nhiều lần, nên đặt ở Update là an toàn. + UpdateTaskUI(); + + if (EC_Game.GetGameRun()?.GetHostPlayer() != null) EC_Game.GetGameRun()?.ShowAccountLoginInfo(); - } + } + + /// + /// Rebuild acceptable-quest cache after host levels up (heavy scan; not on player code path). + /// 升级后重建可接任务缓存(全表扫描放在 UI 层)。 + /// + private void OnHostPlayerLevelUpUI(CECHostPlayer.HostPlayerLevelUpUIEvent _) + { + DlgTask.RebuildAcceptableQuestCache(); } /// @@ -113,13 +120,27 @@ public class CECUIManager : MonoSingleton var inGameUIMan = GetInGameUIMan(); if (inGameUIMan == null) return; - var dlgTaskDialog = inGameUIMan.GetDialog("Win_Quest"); - var bShowTrace = inGameUIMan.IsDialogShow("Win_QuestMinion"); - if (dlgTaskDialog != null && dlgTaskDialog is BrewMonster.Scripts.Task.UI.DlgTask dlgTask) + // Prefer cached DlgTask from Init (Win_Quest). Do not rely on `is DlgTask` on AUIDialog: + // prefab may register as AUIDialog while DlgTask is the concrete component on the same GO. + // 优先使用 Init 里缓存的 DlgTask;字典里可能是 AUIDialog 引用,`is DlgTask` 会为 false。 + DlgTask dlgTask = null; + if (inGameUIMan is CECGameUIMan gameUi && gameUi.GetDlgTask() != null) + dlgTask = gameUi.GetDlgTask(); + if (dlgTask == null) { - dlgTask.RefreshTaskTrace(bShowTrace); - dlgTask.Tick(); + var dlg = inGameUIMan.GetDialog(CECUIHelper.DlgTaskName); + dlgTask = dlg != null ? dlg.GetComponent() : null; } + + if (dlgTask == null) + return; + + if (EC_Game.GetGameRun()?.GetHostPlayer() == null) + return; + + var bShowTrace = inGameUIMan.IsDialogShow("Win_QuestMinion"); + dlgTask.RefreshTaskTrace(bShowTrace); + dlgTask.Tick(); } catch (System.Exception) { @@ -132,6 +153,7 @@ public class CECUIManager : MonoSingleton { EventBus.Unsubscribe(ShowUINPC); EventBus.Unsubscribe(OnTargetHUDClear); + EventBus.Unsubscribe(OnHostPlayerLevelUpUI); EventBus.Unsubscribe(TryHideUINPC); EventBus.Unsubscribe(OnMessageBox); }