Merge remote-tracking branch 'origin/develop' into feature/chat_01

This commit is contained in:
CuongNV
2026-03-31 14:46:34 +07:00
11 changed files with 156 additions and 93 deletions
@@ -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: []
@@ -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);
@@ -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)
@@ -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
@@ -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) {}
@@ -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;
+13 -1
View File
@@ -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);
@@ -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];
+26 -34
View File
@@ -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;
}
}
}
+10 -10
View File
@@ -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
+3
View File
@@ -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