Merge pull request 'fixbug/task-bug-resolve' (#168) from fixbug/task-bug-resolve into develop

Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/168
This commit is contained in:
namth
2026-02-25 07:52:25 +00:00
9 changed files with 109 additions and 49 deletions
@@ -530,19 +530,10 @@ namespace BrewMonster.Network
return iIndex;
}
public static int GetObjectCoord(string strTargetID, ref List<OBJECT_COORD> TargetCoord)
public static int GetObjectCoord(string strTargetID, out List<OBJECT_COORD> TargetCoord)
{
int count = 0;
foreach(var coord in TargetCoord)
{
if(coord.strMap == strTargetID)
{
count++;
TargetCoord.Add(coord);
}
}
return count;
TargetCoord = m_CoordTab[strTargetID];
return TargetCoord.Count;
}
public static bool IsPetAutoSkill(int skill_id)
@@ -1278,10 +1278,42 @@ namespace BrewMonster.Scripts
m_vMoveDest,
null);
if (ret != CECIntelligentRoute.SearchResult.enumSearchSuccess)
if (ret == CECIntelligentRoute.SearchResult.enumSearchNoPath)
{
// Calculate map coordinates from world coordinates
// 从世界坐标计算地图坐标
// Map coord formula: (world / 10) + offset (X: +400, Z: +550)
// 地图坐标公式:(世界坐标 / 10) + 偏移量 (X: +400, Z: +550)
int mapX = Mathf.RoundToInt(m_vMoveDest.x / 10.0f) + 400;
int mapY = Mathf.RoundToInt(m_vMoveDest.y / 10.0f);
int mapZ = Mathf.RoundToInt(m_vMoveDest.z / 10.0f) + 550;
// Show popup notification to player that path cannot be found
// 显示弹窗通知玩家无法找到路径
if (CECUIManager.Instance != null)
{
string message = $"Cannot find path to target position.\nPlease move manually to target location.\n\nMap Coordinates: ({mapX}, {mapZ}, ↑{mapY})";
string messageCN = $"无法找到到目标位置的路径。\n请手动移动到目标位置。\n\n地图坐标: ({mapX}, {mapZ}, ↑{mapY})";
CECUIManager.Instance.ShowMessageBox(
"Path Not Found", // 路径未找到
message, // English message with map coordinates
BrewMonster.MessageBoxType.YesButton
);
}
else
{
Debug.LogWarning($"[CECIntelligentRoute] Cannot find path to target position. Map Coordinates: ({mapX}, {mapZ}, ↑{mapY}). Please move manually.");
}
Finish();
return;
}
else if (ret != CECIntelligentRoute.SearchResult.enumSearchSuccess)
{
break;
}
bSwitchTo2D = false;
break;
@@ -364,9 +364,12 @@ namespace BrewMonster.Scripts
{
if (DEBUG_AUTOPF)
{
BMLogger.LogWarning($"[CECIntelligentRoute] Search: no path. start=({start.x:F2},{start.y:F2},{start.z:F2}) end=({end.x:F2},{end.y:F2},{end.z:F2}) agentIndex={idx}");
BMLogger.Log($"[CECIntelligentRoute] Search: no path found, ignoring. End position=({end.x:F2},{end.y:F2},{end.z:F2})");
}
ResetSearch();
// Don't call ResetSearch() again - it was already called at the start of Search()
// This prevents the idle state deadlock that blocks all movement
// 不再调用 ResetSearch() - 已在 Search() 开始时调用
// 这防止了阻止所有移动的空闲状态死锁
return SearchResult.enumSearchNoPath;
}
@@ -1122,7 +1122,7 @@ namespace BrewMonster.Scripts.Task
// p += sizeof(TASK_NPC_PACK_HEADER);
TASK_NPC_PACK_HEADER header = GPDataTypeHelper.FromBytes<TASK_NPC_PACK_HEADER>(data);
var p = Marshal.SizeOf<TASK_NPC_PACK_HEADER>();
long p = Marshal.SizeOf<TASK_NPC_PACK_HEADER>();
if (header.version != TASK_NPC_INFO_VERSION)
{
@@ -1150,8 +1150,7 @@ namespace BrewMonster.Scripts.Task
// const NPC_INFO& info = pInfos[i];
// m_NPCInfoMap[info.id] = info;
NPC_INFO info = GPDataTypeHelper.FromBytes<NPC_INFO>(data, p);
p += Marshal.SizeOf<NPC_INFO>();
NPC_INFO info = GPDataTypeHelper.FromBytes<NPC_INFO>(data, ref p);
m_NPCInfoMap[info.id] = info;
}
@@ -129,10 +129,13 @@ namespace BrewMonster.Scripts.Task
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct NPC_INFO
{
public uint id;
public uint id; // uint in C++ // uint in C++
public short x;
public short y;
public short z;
//Add padding to because the c++ struct size is auto add 2 bytes padding if not have pragmapack.
public byte padding1; // 1 byte padding to match C++ struct size (12 bytes total) // 1字节填充以匹配C++结构体大小(总共12字节)
public byte padding2; // 1 byte padding to match C++ struct size (12 bytes total) // 1字节填充以匹配C++结构体大小(总共12字节)
}
// public class ServerNotificationConstants
@@ -133,7 +133,7 @@ namespace BrewMonster.UI
m_TargetPos = new A3DVECTOR3(0, 0, 0);
bool bInTable = false;
m_TargetPos = EC_Game.GetGameRun().GetHostPlayer().GetObjectCoordinates(
idTarget, ref m_Targets, ref bInTable);
idTarget, out m_Targets, ref bInTable);
//todo: add map feature here.
if(!bInTable /*&& MAJOR_MAP== CECWorld.Instance.GetInstanceID())*/)
{
@@ -249,7 +249,7 @@ namespace BrewMonster.Scripts.Task.UI
if(cur != worldid)
{
EC_Game.GetObjectCoord(mapName, ref tempCoord);
EC_Game.GetObjectCoord(mapName, out tempCoord);
var iter = tempCoord.Find(coord => coord.strMap == strCurMap);
instCoord.Add(iter);
}
+43 -12
View File
@@ -24,7 +24,8 @@ namespace BrewMonster.Scripts.UI
GPDataTypeHelper.ISNPCID(id) ||
GPDataTypeHelper.ISMATTERID(id) ||
(id > 100000000); // player ids are typically huge; template ids are usually small
A3DVECTOR3 ret = new A3DVECTOR3(0);
var world = EC_Game.GetGameRun()?.GetWorld();
if (world != null && isLikelyRuntimeObjectId)
{
@@ -33,22 +34,45 @@ namespace BrewMonster.Scripts.UI
{
var objPos = obj.transform.position;
in_table = true;
return new A3DVECTOR3(objPos.x, objPos.y, objPos.z);
BMLogger.Log($"[CECUIHelper] GetTaskObjectCoordinates isLikelyRuntimeObjectId: objPos={objPos.x},{objPos.y},{objPos.z}, inTable={in_table}");
ret.Set(objPos.x, objPos.y, objPos.z);
return ret;
}
}
List<OBJECT_COORD> TargetTemp = new List<OBJECT_COORD>();
ret = EC_Game.GetGameRun()?.GetHostPlayer().GetObjectCoordinates(id, out TargetTemp, ref in_table) ?? new A3DVECTOR3(0);
// 1) Try live NPC/Monster in scene by template id (best match to "click name -> go to that entity")
// 1) 先尝试在场景中按模板ID查找活体NPC/怪物(最符合“点名字就去找它”)
var npcMan = EC_ManMessageMono.Instance != null ? EC_ManMessageMono.Instance.CECNPCMan : null;
if (npcMan != null)
//This only work in Major map not A61. Skip for now.
// if(!in_table)
// {
// var npcMan = EC_ManMessageMono.Instance != null ? EC_ManMessageMono.Instance.CECNPCMan : null;
// if (npcMan != null)
// {
// var npc = npcMan.FindNPCByTemplateID(id);
// if (npc != null)
// {
// UnityEngine.Vector3 npcPos = npc.transform.position;
// in_table = true;
// BMLogger.Log($"[CECUIHelper] GetTaskObjectCoordinates npcMan: npcPos={npcPos.x},{npcPos.y},{npcPos.z}, inTable={in_table}");
// ret.Set(npcPos.x, npcPos.y, npcPos.z);
// }
// }
// }
// else
// {
// BMLogger.Log($"[CECUIHelper] GetTaskObjectCoordinates in_table: ret={ret.x},{ret.y},{ret.z}, inTable={in_table}");
// }
if(ret.x != 0 && ret.y != 0 && ret.z != 0)
{
var npc = npcMan.FindNPCByTemplateID(id);
if (npc != null)
{
UnityEngine.Vector3 npcPos = npc.transform.position;
in_table = true;
return new A3DVECTOR3(npcPos.x, npcPos.y, npcPos.z);
}
BMLogger.Log($"[CECUIHelper] GetHostPlayer GetObjectCoordinates True ret={ret.x},{ret.y},{ret.z}, inTable={in_table}");
return ret;
}
else
{
BMLogger.Log($"[CECUIHelper] GetHostPlayer TryGetFirstObjectCoord False ret={ret.x},{ret.y},{ret.z}, inTable={in_table}");
}
// Fallback to task_npc table (C++: ATaskTemplMan::GetTaskNPCInfo)
@@ -59,19 +83,25 @@ namespace BrewMonster.Scripts.UI
// NOTE: Keep original PW coordinate mapping: ret.Set(x, z, y)
// 注意:保持原版坐标映射:ret.Set(x, z, y)
in_table = true;
BMLogger.Log($"[CECUIHelper] GetTaskObjectCoordinates TryGetTaskNPCInfo: info.x={info.x}, info.z={info.z}, info.y={info.y}, inTable={in_table}");
return new A3DVECTOR3(info.x, info.z, info.y);
}
else{
BMLogger.Log($"[CECUIHelper] GetTaskObjectCoordinates TryGetTaskNPCInfo: not found for id={id}");
}
// Fallback to coord_data.txt (C++: Configs/Coord_data.txt via CECGame::GetObjectCoord)
// 回退到 coord_data.txtC++Configs/Coord_data.txt,通过 CECGame::GetObjectCoord
if (BrewMonster.Network.EC_Game.TryGetFirstObjectCoord(id.ToString(), out var coordPos, out var mapName))
{
in_table = true;
BMLogger.Log($"[CECUIHelper] GetTaskObjectCoordinates TryGetFirstObjectCoord: coordPos.x={coordPos.x}, coordPos.y={coordPos.y}, coordPos.z={coordPos.z}, inTable={in_table}");
return new A3DVECTOR3(coordPos.x, coordPos.y, coordPos.z);
}
UnityEngine.Debug.LogWarning($"[CECUIHelper] GetTaskObjectCoordinates: Not found for id={id} (isLikelyRuntimeObjectId={isLikelyRuntimeObjectId}).");
return new A3DVECTOR3(0);
BMLogger.Log($"[CECUIHelper] GetTaskObjectCoordinates default return ret={ret.x},{ret.y},{ret.z}, inTable={in_table}");
return ret;
// TODO: Implement this method properly
// A3DVECTOR3 ret(0.f);
@@ -144,6 +174,7 @@ namespace BrewMonster.Scripts.UI
// Resolve coordinates
bool inTable = false;
A3DVECTOR3 vPos = GetTaskObjectCoordinates(id, ref inTable);
BMLogger.Log($"[CECUIHelper] FollowCoord: vPos={vPos.x},{vPos.y},{vPos.z}, inTable={inTable}");
if (!inTable)
{
// Fallback: use task regions if available (move to the center of the first region)
+17 -16
View File
@@ -3653,21 +3653,19 @@ namespace BrewMonster
public CECCounter GetIncantCnt() { return m_IncantCnt; }
// Get key object(NPC..) coordinates
public A3DVECTOR3 GetObjectCoordinates(int idTarget, ref ObjectCoords TargetCoord, ref bool bInTable)
public A3DVECTOR3 GetObjectCoordinates(int idTarget, out List<OBJECT_COORD> TargetCoord, ref bool bInTable)
{
if (TargetCoord == null)
{
TargetCoord = new ObjectCoords();
}
TargetCoord.Clear();
TargetCoord = new List<OBJECT_COORD>();
A3DVECTOR3 vDestPos = new A3DVECTOR3(0, 0, 0);
bInTable = false;
// Get object coordinates from CECGame::m_CoordTab
string szText = idTarget.ToString();
List<OBJECT_COORD> tempCoord = new List<OBJECT_COORD>();
int iCount = EC_Game.GetObjectCoord(szText, ref tempCoord);
List<OBJECT_COORD> originalCoords = new List<OBJECT_COORD>();
int iCount = EC_Game.GetObjectCoord(szText, out originalCoords);
if (iCount == 0)
{
return vDestPos;
@@ -3680,11 +3678,12 @@ namespace BrewMonster
CECInstance pInstance = CECGameRun.Instance.GetInstance(idInstance);
string strCurMap = pInstance.GetPath();
// ȼͬһͼǷҪҵƷ
bool bHasObjectInCurrentInstance = tempCoord.Any(coord => coord.strMap == strCurMap);
bool bHasObjectInCurrentInstance = originalCoords.Any(coord => coord.strMap == strCurMap);
// Iterate over original list and build filtered TargetCoord list
for (int i = 0; i < iCount; i++)
{
OBJECT_COORD objCoord = tempCoord[i];
OBJECT_COORD objCoord = originalCoords[i];
if (strCurMap == objCoord.strMap)
{
TargetCoord.Add(objCoord);
@@ -3696,22 +3695,24 @@ namespace BrewMonster
fMinDist = tempDist;
bInTable = true;
vDestPos = objCoord.vPos;
}
}
}
// ǰͼûĿĻĿڵͼڵǰͼ
else if (!bHasObjectInCurrentInstance)
{
// find the entrance of instance
List<OBJECT_COORD> instCoord = new List<OBJECT_COORD>();
int iCount2 = EC_Game.GetObjectCoord(objCoord.strMap, ref instCoord);
for (int j = 0; j < iCount2; ++j)
int iCount2 = EC_Game.GetObjectCoord(objCoord.strMap, out instCoord);
for (int j = 0; j < iCount2; ++j)
{
if (instCoord[j].strMap == strCurMap)
{
TargetCoord.Add(instCoord[j]);
// Check if this is the nearest target
float tempDist = (instCoord[i].vPos - GetPos()).Magnitude();
float tempDist = (instCoord[j].vPos - GetPos()).Magnitude();
if (tempDist < fMinDist)
{
fMinDist = tempDist;