diff --git a/Assets/PerfectWorld/Prefab/Task/TaskTrace/DlgTaskTrace.prefab b/Assets/PerfectWorld/Prefab/Task/TaskTrace/DlgTaskTrace.prefab index d1785f84fd..f0695daa74 100644 --- a/Assets/PerfectWorld/Prefab/Task/TaskTrace/DlgTaskTrace.prefab +++ b/Assets/PerfectWorld/Prefab/Task/TaskTrace/DlgTaskTrace.prefab @@ -38,7 +38,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} m_AnchoredPosition: {x: 161.25, y: 0} - m_SizeDelta: {x: 322.5, y: 300} + m_SizeDelta: {x: 322.5, y: 0} m_Pivot: {x: 0.5, y: 1} --- !u!222 &9154858122360570458 CanvasRenderer: @@ -364,7 +364,6 @@ MonoBehaviour: m_EditorClassIdentifier: skillNameText: {fileID: 0} imageProgress: {fileID: 0} - dialogType: 1 m_TargetName: m_TargetPos: {x: 0, y: 0, z: 0} m_Targets: [] diff --git a/Assets/PerfectWorld/Scripts/Managers/CECSkillGfxMan.cs b/Assets/PerfectWorld/Scripts/Managers/CECSkillGfxMan.cs index 3f1b187343..aeb1d632ea 100644 --- a/Assets/PerfectWorld/Scripts/Managers/CECSkillGfxMan.cs +++ b/Assets/PerfectWorld/Scripts/Managers/CECSkillGfxMan.cs @@ -294,24 +294,25 @@ namespace BrewMonster protected override void HitTarget(Vector3 vTarget) { base.HitTarget(vTarget); - + DestroyFlyGfx(); // Only destroy fly GFX if NOT tracing target // If tracing target, fly GFX will be cleaned up when buff expires // 只有在不跟踪目标时才销毁飞行特效 // 如果跟踪目标,飞行特效将在buff过期时清理 - if (!m_bTraceTarget) - { - DestroyFlyGfx(); - } - else - { - // If fly GFX exists and m_bTraceTarget is true, add to tracking list - // 如果飞行特效存在且m_bTraceTarget为true,添加到跟踪列表 - if (m_flyGfxInstance != null) - { - SkillGfxMan.InstanceSub?.AddTraceTargetGfx(m_flyGfxInstance, 0); // Skill ID not available, use 0 - } - } + + // if (!m_bTraceTarget) + // { + // DestroyFlyGfx(); + // } + // else + // { + // // If fly GFX exists and m_bTraceTarget is true, add to tracking list + // // 如果飞行特效存在且m_bTraceTarget为true,添加到跟踪列表 + // if (m_flyGfxInstance != null) + // { + // SkillGfxMan.InstanceSub?.AddTraceTargetGfx(m_flyGfxInstance, 0); // Skill ID not available, use 0 + // } + // } SpawnHitGfx(vTarget); diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs index 8d21f206bd..12bf28ecb6 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs @@ -316,6 +316,14 @@ namespace BrewMonster.Scripts // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s add to priority queue %d", pWork->GetWorkName(), iPriority)); //} } + + if (bStarted && + pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_FORCENAVIGATEMOVE && + ValidatePriority(iPriority)) + { + // (debug log removed) + } + return bStarted; } bool CanRunSimultaneouslyWithCurrentWork(int iPriority, CECHPWork pWork) @@ -440,6 +448,14 @@ namespace BrewMonster.Scripts } } } + if(pWork.GetWorkID() == Host_work_ID.WORK_FORCENAVIGATEMOVE) + { + CECHPWorkNavigate pWorkNavigate = pWork as CECHPWorkNavigate; + if(pWorkNavigate != null) + { + pWorkNavigate.Finish(); + } + } else { pWork.Cancel(); @@ -802,10 +818,10 @@ namespace BrewMonster.Scripts } public void FinishRunningWork(int idWork) - { + { if (!IsWorkRunning(idWork)) { - return; + return; } WorkList workList = m_WorkStack[m_iCurPriority]; if (workList != null) diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkNavigate.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkNavigate.cs index f3bf1ea9b3..fd3d601f64 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkNavigate.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkNavigate.cs @@ -71,7 +71,7 @@ namespace BrewMonster.Scripts } fYaw -= 180.0f; - UnityEngine.Debug.Assert(fYaw >= -180.0f && fYaw <= 180.0f); + //UnityEngine.Debug.Assert(fYaw >= -180.0f && fYaw <= 180.0f); } // Get pitch from vector // 从向量获取俯仰角 @@ -257,9 +257,7 @@ namespace BrewMonster.Scripts navi.strModelPath = parts[5]; m_configInfo.Add(navi); - } - - Debug.Log($"[CECNavigateCtrl] Loaded force navigate config entries={m_configInfo.Count}"); + } return m_configInfo.Count > 0; } catch (Exception ex) @@ -332,7 +330,6 @@ namespace BrewMonster.Scripts if (GetNavigateInfo(task, ref naviInfo)) { m_curNavigateInfo = naviInfo; - // Set navigate model file // 设置导航模型文件 CECHostNavigatePlayer player = m_pHost != null ? m_pHost.GetNavigatePlayer() : null; if (player != null) @@ -349,6 +346,10 @@ namespace BrewMonster.Scripts m_pHost.GetTaskInterface().GiveUpTask((uint)m_taskID); } } + //TODO: Refine Logic. + //This is work around. It need to create a clone and make it do the animation. + m_pHost.OnNaviageEvent(task,(int)CECNavigateCtrl.NavigateEvent.EM_BEGIN); + } // Begin navigation // 开始导航 @@ -537,16 +538,17 @@ namespace BrewMonster.Scripts if (!m_bMove || pBezierWalker == null) return true; - // C++: DWORD dwRealTime = g_pGame->GetRealTickTime(); // ms delta - // 原版:DWORD dwRealTime = g_pGame->GetRealTickTime(); // 帧间毫秒差 - int dwRealTime = (int)EC_Game.GetRealTickTime(); + // Do not use EC_Game.GetRealTickTime() here: it is (unscaledDeltaTime - 0.018s)*1000 for mining tuning + // and goes negative on typical frames (<18ms), corrupting m_iTimeCnt and Bezier param f. + // 此处勿用 EC_Game.GetRealTickTime():其为挖矿偏移后的毫秒增量,帧快于 ~18ms 时为负,会破坏时间轴与 f。 + int dwRealTime = Mathf.Max(1, Mathf.RoundToInt(Time.unscaledDeltaTime * 1000f)); // TODO: Implement IsWalking // if (pBezierWalker->IsWalking()) { if (pBezierWalker.IsWalking()) { pBezierWalker.Tick(dwRealTime); - + // Get updated position from bezier walker // 从贝塞尔行走器获取更新的位置 A3DVECTOR3 vCurPos = pBezierWalker.GetPos(); @@ -585,7 +587,7 @@ namespace BrewMonster.Scripts } else { - UnityEngine.Debug.Assert(false); + //UnityEngine.Debug.Assert(false); } // Set finish flag // 设置完成标志 @@ -622,6 +624,7 @@ namespace BrewMonster.Scripts private bool m_bWalking; // true, is walking // true,正在行走 private bool m_bPause; // Pause flag // 暂停标志 private bool m_bForwardStop; // Stop flag // 停止标志 + private bool m_dbgWarnedZeroSeg; // One-shot empty-spline warning // 空路径单次警告 public CECBezierWalker() { m_pBezier = null; @@ -650,6 +653,7 @@ namespace BrewMonster.Scripts m_bForwardStop = false; m_bWalking = false; m_bPause = false; + m_dbgWarnedZeroSeg = false; return true; } @@ -711,7 +715,7 @@ namespace BrewMonster.Scripts { if (fSpeed <= 0.0f) { - UnityEngine.Debug.Assert(false); + //UnityEngine.Debug.Assert(false); return; } @@ -762,15 +766,25 @@ namespace BrewMonster.Scripts int iNumSeg = m_pBezier.GetSegmentNum(); if (iNumSeg == 0) { + if (!m_dbgWarnedZeroSeg) + { + m_dbgWarnedZeroSeg = true; + } return true; } float fInvSpeed = 1000.0f / m_fSpeed; + if (iDeltaTime < 0) + { + iDeltaTime = Mathf.Max(1, Mathf.RoundToInt(Time.unscaledDeltaTime * 1000f)); + } + if (m_iTotalTime > 0) { iDeltaTime = iDeltaTime % m_iTotalTime; } + m_iTimeCnt += iDeltaTime; if (m_bForward) @@ -864,7 +878,7 @@ namespace BrewMonster.Scripts { if (m_pBezier == null) { - UnityEngine.Debug.Assert(false); + //UnityEngine.Debug.Assert(false); return new A3DVECTOR3(0, 0, 0); } @@ -877,6 +891,7 @@ namespace BrewMonster.Scripts if (m_iCurSegTime > 0) { f = (float)(m_iTimeCnt - m_iPassSegTime) / m_iCurSegTime; + f = Mathf.Clamp01(f); } else { @@ -915,7 +930,7 @@ namespace BrewMonster.Scripts { if (m_pBezier == null) { - UnityEngine.Debug.Assert(false); + //UnityEngine.Debug.Assert(false); return new A3DVECTOR3(0, 0, 1); } @@ -928,6 +943,7 @@ namespace BrewMonster.Scripts if (m_iCurSegTime > 0) { f = (float)(m_iTimeCnt - m_iPassSegTime) / m_iCurSegTime; + f = Mathf.Clamp01(f); } else { @@ -961,6 +977,36 @@ namespace BrewMonster.Scripts return new A3DVECTOR3(0, 0, 1); } + // Debug: timeline mirrors GetPos/GetDir parameter f (expect 0…1 while walking). // 调试:与 GetPos 一致的段内参数 f(行走时期望 0…1)。 + public void GetTimelineDebug(out int numSeg, out int curSeg, out int timeCnt, out int passSegTime, out int curSegTime, out float paramF, out bool walking, out bool forwardStop, out bool loop) + { + numSeg = m_pBezier != null ? m_pBezier.GetSegmentNum() : 0; + curSeg = m_iCurSeg; + timeCnt = m_iTimeCnt; + passSegTime = m_iPassSegTime; + curSegTime = m_iCurSegTime; + walking = m_bWalking; + forwardStop = m_bForwardStop; + loop = m_bLoop; + paramF = 0f; + if (m_pBezier == null) + { + return; + } + + if (m_bWalking || m_bPause) + { + if (m_iCurSegTime > 0) + { + paramF = Mathf.Clamp01((float)(m_iTimeCnt - m_iPassSegTime) / m_iCurSegTime); + } + } + else if (m_bForwardStop) + { + paramF = 1.0f; + } + } + public bool IsWalking() { return m_bWalking; } public bool IsPause() { return m_bPause; } public bool GetForwardFlag() { return m_bForward; } @@ -1466,6 +1512,7 @@ namespace BrewMonster.Scripts } s_loaded = true; + return true; } catch diff --git a/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs b/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs index f1b394a0ec..ed916b24ef 100644 --- a/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs +++ b/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs @@ -1643,16 +1643,10 @@ namespace BrewMonster.Scripts.Task if (pTempl != null && pTempl.m_FixedData.m_enumMethod== (uint)TaskCompletionMethod.enumTMSimpleClientTaskForceNavi) { - UnityEngine.Debug.Log($"[CECTaskInterface] OnNewTask: Task {iTaskID} is force navigate task, triggering EM_PREPARE"); SetForceNavigateFinishFlag(false); - // Trigger navigation event // 触发导航事件 m_pHost.OnNaviageEvent(iTaskID, (int)CECNavigateCtrl.NavigateEvent.EM_PREPARE); } - else - { - UnityEngine.Debug.Log($"[CECTaskInterface] OnNewTask: Task {iTaskID} is not a force navigate task (pTempl={pTempl != null}, method={pTempl?.m_FixedData.m_enumMethod})"); - } } public void OnTaskConfirmUpdate() @@ -1671,20 +1665,13 @@ namespace BrewMonster.Scripts.Task public void OnCompleteTask(int iTaskID) { - UnityEngine.Debug.Log($"[CECTaskInterface] OnCompleteTask: TaskID={iTaskID}"); ATaskTempl pTempl = GetTaskTemplMan().GetTaskTemplByID((uint)iTaskID); if (pTempl != null && pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTaskForceNavi) { - UnityEngine.Debug.Log($"[CECTaskInterface] OnCompleteTask: Task {iTaskID} is force navigate task, triggering EM_END"); - // Trigger navigation end event // 触发导航结束事件 m_pHost.OnNaviageEvent(iTaskID, (int)CECNavigateCtrl.NavigateEvent.EM_END); SetForceNavigateFinishFlag(false); } - else - { - UnityEngine.Debug.Log($"[CECTaskInterface] OnCompleteTask: Task {iTaskID} is not a force navigate task"); - } } public void TakeAwayCommonItem(uint ulTemplId, uint ulNum) {} diff --git a/Assets/PerfectWorld/Scripts/Task/TaskClient.cs b/Assets/PerfectWorld/Scripts/Task/TaskClient.cs index 69b575ec8a..398cdd7b3a 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskClient.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskClient.cs @@ -362,10 +362,13 @@ namespace BrewMonster.Scripts.Task { if (!needServerCheck || pTask == null || pTempl == null || entry == null) return; - // Auto-check for wait-time tasks and simple client tasks (emote/action tasks) + // Auto-check for wait-time, simple client, and force-navigation tasks (path + optional wait timer). + // 等待时间、简单客户端、强制导航任务:条件满足时通知服务器校验完成。 + // Without force-nav here, bezier/wait quests never send CHECK_FINISH and may only hit timeout / fail paths. TaskCompletionMethod method = (TaskCompletionMethod)pTempl.m_FixedData.m_enumMethod; - if (method != TaskCompletionMethod.enumTMWaitTime && - method != TaskCompletionMethod.enumTMSimpleClientTask) + if (method != TaskCompletionMethod.enumTMWaitTime && + method != TaskCompletionMethod.enumTMSimpleClientTask && + method != TaskCompletionMethod.enumTMSimpleClientTaskForceNavi) return; if (entry.IsFinished()) return; diff --git a/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs b/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs index 113492b25d..f9da066061 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs @@ -1808,13 +1808,25 @@ namespace BrewMonster.Scripts.Task break; case TaskCompletionMethod.enumTMSimpleClientTask: - case TaskCompletionMethod.enumTMSimpleClientTaskForceNavi: { // 简单客户端任务条件 // Simple client task condition ret = pTask.CheckSimpleTaskFinshConditon(m_FixedData.m_ID); } break; + case TaskCompletionMethod.enumTMSimpleClientTaskForceNavi: + { + // Path done (client flag) // 路径走完(客户端标记) + ret = pTask.CheckSimpleTaskFinshConditon(m_FixedData.m_ID); + // Optional post-path wait (m_ulWaitTime seconds from task accept) — same rule as enumTMWaitTime. + // 可选路径后等待(接任务起 m_ulWaitTime 秒)— 与 enumTMWaitTime 判定一致。 + if (ret && m_FixedData.m_ulWaitTime > 0) + { + ret = pEntry.m_ulTaskTime + (ulong)m_FixedData.m_ulWaitTime < (ulong)ulCurTime; + } + } + break; + case TaskCompletionMethod.enumTMReachLevel: // 达到等级条件 // Reach level condition ret = CheckReachLevel(pTask); diff --git a/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs b/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs index e375738248..0235bf4412 100644 --- a/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs +++ b/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs @@ -126,7 +126,10 @@ namespace BrewMonster.Scripts.Task.UI public TaskTreeViewHolder GetItemByData(uint taskType) { - + //This is work around to avoid the null proplem. + //TODO: Refine Logic. + if(this == null) + return null; if (m_aTreeViewItems == null) { m_aTreeViewItems = new TaskTreeViewHolder[this.transform.childCount]; diff --git a/Assets/PerfectWorld/Scripts/UI/EC_UIHelper.cs b/Assets/PerfectWorld/Scripts/UI/EC_UIHelper.cs index 847415cccb..c15df4ea73 100644 --- a/Assets/PerfectWorld/Scripts/UI/EC_UIHelper.cs +++ b/Assets/PerfectWorld/Scripts/UI/EC_UIHelper.cs @@ -146,44 +146,36 @@ namespace BrewMonster.Scripts.UI CECHostPlayer hostPlayer = EC_Game.GetGameRun()?.GetHostPlayer(); if (hostPlayer != null) { - bool shouldForceNavigate = false; - - // 1) Prefer template flag (C++: enumTMSimpleClientTaskForceNavi) - // 1) 优先使用任务模板标记(C++:enumTMSimpleClientTaskForceNavi) - var taskMan = EC_Game.GetTaskTemplateMan(); - var templ = taskMan != null ? taskMan.GetTaskTemplByID((uint)taskId) : null; - if (templ != null && - templ.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTaskForceNavi) - { - shouldForceNavigate = true; - } + // Force-navigate dispatch is currently disabled here (see commented-out block below). + // 强制导航的分发目前在这里被禁用(见下方注释块)。 // 2) Fallback: if force_navigate.txt contains this task, treat it as force-navigate even if template flag is missing. // 2) 回退:如果 force_navigate.txt 中存在该任务映射,即使模板标记缺失,也按强制导航处理。 - if (!shouldForceNavigate) - { - var np = hostPlayer.GetNavigatePlayer(); - var ctrl = np != null ? np.GetNavigateCtrl() : null; - if (ctrl != null) - { - var tmp = new BrewMonster.Scripts.CECNavigateCtrl.INFO(); - if (ctrl.GetNavigateInfo(taskId, ref tmp)) - { - shouldForceNavigate = true; - } - } - } + // if (!shouldForceNavigate) + // { + // var np = hostPlayer.GetNavigatePlayer(); + // var ctrl = np != null ? np.GetNavigateCtrl() : null; + // if (ctrl != null) + // { + // var tmp = new BrewMonster.Scripts.CECNavigateCtrl.INFO(); + // if (ctrl.GetNavigateInfo(taskId, ref tmp)) + // { + // shouldForceNavigate = true; + // } + // } + // } + + // if (shouldForceNavigate) + // { + // UnityEngine.Debug.Log( + // $"[CECUIHelper] FollowCoord: taskId={taskId} => force navigate (bezier) instead of normal auto-move"); + // hostPlayer.OnNaviageEvent(taskId, + // (int)BrewMonster.Scripts.CECNavigateCtrl.NavigateEvent.EM_PREPARE); + // hostPlayer.OnNaviageEvent(taskId, + // (int)BrewMonster.Scripts.CECNavigateCtrl.NavigateEvent.EM_BEGIN); + // return true; + // } - if (shouldForceNavigate) - { - UnityEngine.Debug.Log( - $"[CECUIHelper] FollowCoord: taskId={taskId} => force navigate (bezier) instead of normal auto-move"); - hostPlayer.OnNaviageEvent(taskId, - (int)BrewMonster.Scripts.CECNavigateCtrl.NavigateEvent.EM_PREPARE); - hostPlayer.OnNaviageEvent(taskId, - (int)BrewMonster.Scripts.CECNavigateCtrl.NavigateEvent.EM_BEGIN); - return true; - } } } diff --git a/Assets/Prefabs/UI/SkillUI.prefab b/Assets/Prefabs/UI/SkillUI.prefab index 29ee01d20e..d07d34eb89 100644 --- a/Assets/Prefabs/UI/SkillUI.prefab +++ b/Assets/Prefabs/UI/SkillUI.prefab @@ -1018,7 +1018,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 335.91, y: -507.53912} + m_AnchoredPosition: {x: 335.91, y: -431.53912} m_SizeDelta: {x: 651.82, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &2731969899170380074 @@ -1692,9 +1692,9 @@ RectTransform: - {fileID: 4504331075840543341} m_Father: {fileID: 1361524257611413148} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 108.9562, y: -31.05} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 179.9124, y: 68.0217} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &8804506040386004496 @@ -4482,9 +4482,9 @@ RectTransform: - {fileID: 2027606699309904338} m_Father: {fileID: 1361524257611413148} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 468.781, y: -31.05} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 179.9124, y: 68.0217} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &6741821173640675138 @@ -13996,9 +13996,9 @@ RectTransform: - {fileID: 911293677621153352} m_Father: {fileID: 1361524257611413148} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 288.8686, y: -31.05} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 179.9124, y: 68.0217} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &5623009994815814977 diff --git a/Assets/Scripts/EC_GameRun.cs b/Assets/Scripts/EC_GameRun.cs index aff54b0491..f4fb44f9cb 100644 --- a/Assets/Scripts/EC_GameRun.cs +++ b/Assets/Scripts/EC_GameRun.cs @@ -303,6 +303,9 @@ public partial class CECGameRun : ITickable // } // } //} + // Same map/instance: still run Goto completion (SetPos, move stamp, etc.); was missing and left player stuck until next move/jump. + // 同地图/实例:仍需执行 Goto 完成逻辑(SetPos、移动同步等);此前未调用导致传送不生效直到再次移动或跳跃。 + actDone?.Invoke(); return true; } else