Merge pull request 'fixbug/task-bug-resolve' (#163) from fixbug/task-bug-resolve into develop
Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/163
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -8,13 +8,11 @@ using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
namespace BrewMonster
|
||||
{
|
||||
public class StyledTaskTraceText : MonoBehaviour, IPointerMoveHandler,IPointerClickHandler
|
||||
public class StyledTaskTraceText : MonoBehaviour, IPointerClickHandler
|
||||
{
|
||||
|
||||
public TMP_Text tmp;
|
||||
private List<LinkCommand> linkCommands =new List<LinkCommand>();
|
||||
int hoveredLink = -1;
|
||||
|
||||
|
||||
private void Start()
|
||||
{
|
||||
@@ -22,18 +20,41 @@ namespace BrewMonster
|
||||
tmp.ForceMeshUpdate();
|
||||
}
|
||||
|
||||
public void OnPointerMove(PointerEventData eventData)
|
||||
// Helper method to find intersecting link with proper camera handling // 辅助方法,用于查找相交的链接并正确处理相机
|
||||
private int FindIntersectingLink(PointerEventData eventData)
|
||||
{
|
||||
int linkIndex = TMP_TextUtilities.FindIntersectingLink(
|
||||
tmp,
|
||||
eventData.position,
|
||||
eventData.pressEventCamera
|
||||
);
|
||||
if (tmp == null) return -1;
|
||||
|
||||
if (linkIndex != hoveredLink)
|
||||
tmp.ForceMeshUpdate();
|
||||
|
||||
// Get camera for link detection // 获取用于链接检测的相机
|
||||
Camera camera = null;
|
||||
Canvas canvas = tmp.GetComponentInParent<Canvas>();
|
||||
if (canvas != null)
|
||||
{
|
||||
hoveredLink = linkIndex;
|
||||
// IMPORTANT: TMP_TextUtilities.FindIntersectingLink expects camera=null for ScreenSpaceOverlay.
|
||||
// 重要:ScreenSpaceOverlay 必须传 camera=null,否则会算错导致 linkIndex = -1。
|
||||
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
camera = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ScreenSpaceCamera / WorldSpace
|
||||
camera = eventData.pressEventCamera != null ? eventData.pressEventCamera : canvas.worldCamera;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No canvas found; fall back to pressEventCamera (may be null) then main
|
||||
camera = eventData.pressEventCamera != null ? eventData.pressEventCamera : Camera.main;
|
||||
}
|
||||
|
||||
// Try with camera first, then fallback to null // 先尝试使用相机,然后回退到null
|
||||
int linkIndexCam = TMP_TextUtilities.FindIntersectingLink(tmp, eventData.position, camera);
|
||||
int linkIndexNull = TMP_TextUtilities.FindIntersectingLink(tmp, eventData.position, null);
|
||||
|
||||
return linkIndexCam != -1 ? linkIndexCam : linkIndexNull;
|
||||
}
|
||||
public void Set(string text)
|
||||
{
|
||||
@@ -80,53 +101,49 @@ namespace BrewMonster
|
||||
tmp.text = "";
|
||||
linkCommands.Clear();
|
||||
}
|
||||
void SetLinkColor(int linkIndex, Color32 color)
|
||||
{
|
||||
TMP_LinkInfo linkInfo = tmp.textInfo.linkInfo[linkIndex];
|
||||
|
||||
for (int i = 0; i < linkInfo.linkTextLength; i++)
|
||||
{
|
||||
int charIndex = linkInfo.linkTextfirstCharacterIndex + i;
|
||||
var charInfo = tmp.textInfo.characterInfo[charIndex];
|
||||
|
||||
if (!charInfo.isVisible) continue;
|
||||
|
||||
int meshIndex = charInfo.materialReferenceIndex;
|
||||
int vertexIndex = charInfo.vertexIndex;
|
||||
|
||||
var colors = tmp.textInfo.meshInfo[meshIndex].colors32;
|
||||
colors[vertexIndex + 0] = color;
|
||||
colors[vertexIndex + 1] = color;
|
||||
colors[vertexIndex + 2] = color;
|
||||
colors[vertexIndex + 3] = color;
|
||||
}
|
||||
|
||||
tmp.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
|
||||
}
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
TMP_LinkInfo linkInfo = tmp.textInfo.linkInfo[hoveredLink];
|
||||
if (tmp == null) return;
|
||||
|
||||
// Detect link directly in click handler // 在点击处理程序中直接检测链接
|
||||
int linkIndex = FindIntersectingLink(eventData);
|
||||
|
||||
// Validate link index // 验证链接索引
|
||||
if (linkIndex == -1 || linkIndex >= tmp.textInfo.linkCount || linkIndex >= linkCommands.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tmp.ForceMeshUpdate();
|
||||
TMP_LinkInfo linkInfo = tmp.textInfo.linkInfo[linkIndex];
|
||||
string linkText = linkInfo.GetLinkText();
|
||||
string entityID = linkInfo.GetLinkID();
|
||||
|
||||
switch (entityID)
|
||||
{
|
||||
case "coord":
|
||||
linkCommands[hoveredLink].Execute(tmp);
|
||||
//Debug.Log($"[StyledTaskTraceText] OnPointerClick: linkCommands[hoveredLink].Execute(tmp) => {linkCommands[hoveredLink].Execute(tmp)}");
|
||||
if (linkIndex < linkCommands.Count && linkCommands[linkIndex] != null)
|
||||
{
|
||||
linkCommands[linkIndex].Execute(tmp);
|
||||
}
|
||||
//Debug.Log($"[StyledTaskTraceText] OnPointerClick: linkCommands[{linkIndex}].Execute(tmp) => {linkCommands[linkIndex].Execute(tmp)}");
|
||||
break;
|
||||
case "npc":
|
||||
linkCommands[hoveredLink].Execute(tmp);
|
||||
if (linkIndex < linkCommands.Count && linkCommands[linkIndex] != null)
|
||||
{
|
||||
linkCommands[linkIndex].Execute(tmp);
|
||||
}
|
||||
break;
|
||||
case "monster":
|
||||
break;
|
||||
default:
|
||||
Debug.Log($"Clicked unknown link: ID={entityID} Text={linkText}");
|
||||
break;
|
||||
break;
|
||||
}
|
||||
hoveredLink = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1349,6 +1349,7 @@ public static class generate_item_temp
|
||||
content_length = (int)(size - offset);
|
||||
WriteInt(data, ref content_length_ptr, content_length);
|
||||
WriteInt(data, ref item_content, offset);
|
||||
|
||||
WriteInt(data, ref offset, ess.food_type); //��Ʒ�Ŀ�װ����־
|
||||
WriteInt(data, ref offset, ess.hornor); //��Ʒ��Ӧ�����ID guid
|
||||
|
||||
@@ -1357,7 +1358,69 @@ public static class generate_item_temp
|
||||
itemdataman.set_to_classid(DATA_TYPE.DT_PET_FOOD_ESSENCE, data, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int generate_flysword<RAND_CLASS>(uint id, ID_SPACE idspace, out byte[] data, out uint size, RAND_CLASS cls,item_tag_t tag)
|
||||
{
|
||||
data = new byte[0];
|
||||
size = 0;
|
||||
|
||||
DATA_TYPE datatype = DATA_TYPE.DT_INVALID;
|
||||
object obj = itemdataman._edm.get_data_ptr(id, idspace, ref datatype);
|
||||
if(obj == null || datatype != DATA_TYPE.DT_FLYSWORD_ESSENCE)
|
||||
return -1;
|
||||
FLYSWORD_ESSENCE ess = (FLYSWORD_ESSENCE)obj;
|
||||
size = (uint)(Marshal.SizeOf(typeof(item_data)) + Marshal.SizeOf(typeof(FLYSWORD_ESSENCE)));
|
||||
data = new byte[size];
|
||||
int offset = 0;
|
||||
WriteUInt(data, ref offset, id);
|
||||
WriteUInt(data, ref offset, 1);
|
||||
WriteUInt(data, ref offset, (uint)ess.pile_num_max);
|
||||
WriteInt(data, ref offset, (int)itemdataman.ELEMENTDATAMAN_EQUIP_MASK_FLYSWORD);
|
||||
WriteInt(data, ref offset, (int)ess.proc_type);
|
||||
WriteInt(data, ref offset, (int)DATA_TYPE.DT_FLYSWORD_ESSENCE);
|
||||
if(ess.has_guid == 1){
|
||||
int g1,g2;
|
||||
itemdataman.get_item_guid(id,out g1,out g2);
|
||||
WriteInt(data, ref offset, g1);
|
||||
WriteInt(data, ref offset, g2);
|
||||
}
|
||||
else{
|
||||
WriteInt(data, ref offset, 0);
|
||||
}
|
||||
WriteInt(data, ref offset, ess.price);
|
||||
WriteInt(data, ref offset, 0); //����ʱ��
|
||||
|
||||
int content_length = 0;
|
||||
int content_length_ptr = offset;
|
||||
WriteInt(data, ref offset, 0);
|
||||
int item_content = offset;
|
||||
WriteInt(data, ref offset, 0);
|
||||
content_length = (int)(size - offset);
|
||||
WriteInt(data, ref content_length_ptr, content_length);
|
||||
WriteInt(data, ref item_content, offset);
|
||||
|
||||
int t = element_data.RandNormal<RAND_CLASS, LOWER>((int)ess.time_max_min, (int)ess.time_max_max, cls, LOWER.LOWER_TREND);
|
||||
|
||||
// essence
|
||||
WriteInt(data, ref offset, (int)(t*0.5f));
|
||||
WriteInt(data, ref offset, (int)t);
|
||||
WriteShort(data, ref offset, (short)ess.require_player_level_min);
|
||||
WriteByte(data, ref offset, (byte)ess.level);
|
||||
WriteByte(data, ref offset, 0);
|
||||
WriteInt(data, ref offset, (int)ess.character_combo_id);
|
||||
WriteInt(data, ref offset, (int)ess.time_increase_per_element);
|
||||
|
||||
float speed = element_data.Rand<RAND_CLASS, LOWER>(ess.speed_increase_min, ess.speed_increase_max, cls, LOWER.LOWER_TREND);
|
||||
WriteFloat(data, ref offset, speed);
|
||||
speed = element_data.Rand<RAND_CLASS, LOWER>(ess.speed_rush_increase_min, ess.speed_rush_increase_max, cls, LOWER.LOWER_TREND);
|
||||
WriteFloat(data, ref offset, speed);
|
||||
|
||||
//���������߱�ǩ
|
||||
WriteByte(data, ref offset, tag.type);
|
||||
WriteByte(data, ref offset, (byte)tag.size);
|
||||
|
||||
itemdataman.set_to_classid(DATA_TYPE.DT_FLYSWORD_ESSENCE, data, -1);
|
||||
return 0;
|
||||
}
|
||||
public static int generate_townscroll<RAND_CLASS>(uint id, ID_SPACE idspace, out byte[] data, out uint size, RAND_CLASS cls)
|
||||
{
|
||||
DATA_TYPE datatype = DATA_TYPE.DT_INVALID;
|
||||
@@ -1402,6 +1465,7 @@ public static class generate_item_temp
|
||||
itemdataman.set_to_classid(DATA_TYPE.DT_TOWNSCROLL_ESSENCE, data, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#region Write Functions
|
||||
private static void WriteUInt(byte[] buf, ref int offset, uint value)
|
||||
{
|
||||
|
||||
@@ -491,6 +491,9 @@ namespace BrewMonster
|
||||
case DATA_TYPE.DT_PET_FOOD_ESSENCE:
|
||||
ret = generate_item_temp.generate_pet_food(id, ID_SPACE.ID_SPACE_ESSENCE, out item, out size, SPECIFIC.SPECIFIC_RAND);
|
||||
break;
|
||||
case DATA_TYPE.DT_FLYSWORD_ESSENCE:
|
||||
ret = generate_item_temp.generate_flysword(id, ID_SPACE.ID_SPACE_ESSENCE, out item, out size, SPECIFIC.SPECIFIC_RAND, tag);
|
||||
break;
|
||||
case DATA_TYPE.DT_TOWNSCROLL_ESSENCE:
|
||||
ret = generate_item_temp.generate_townscroll(id, ID_SPACE.ID_SPACE_ESSENCE, out item, out size, SPECIFIC.SPECIFIC_RAND);
|
||||
break;
|
||||
|
||||
@@ -500,7 +500,6 @@ namespace BrewMonster.Scripts.Task
|
||||
// Follow C++ logic: valid_size checks the buffer size before deserializing
|
||||
// In C++, pNotify is a pointer to the structure, so valid_size can read sub_tags.sz directly
|
||||
// In C#, we need to read sub_tags.sz from the buffer first, then validate
|
||||
|
||||
// Calculate base size: task_notify_base (3) + cur_time (4) + cap_task (4) = 11
|
||||
int baseSzNew = Marshal.SizeOf<task_notify_base>() + 8;
|
||||
if (sz <= (uint)baseSzNew)
|
||||
@@ -709,13 +708,16 @@ namespace BrewMonster.Scripts.Task
|
||||
// pTask.UpdateTaskEmotionAction(m_FixedData.m_ID);
|
||||
if ((m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTask)
|
||||
&& m_FixedData.m_uiEmotion > 0)
|
||||
{
|
||||
// TODO: Pop emotion UI
|
||||
// PopEmotionUI(m_ID,m_uiEmotion,false);
|
||||
|
||||
}
|
||||
|
||||
if (m_FixedData.m_bDisplayInTitleTaskUI)
|
||||
{
|
||||
// TODO: Update title UI
|
||||
// UpdateTitleUI(m_ID);
|
||||
|
||||
}
|
||||
pTask.OnCompleteTask((int)m_FixedData.m_ID);
|
||||
|
||||
break;
|
||||
|
||||
@@ -155,6 +155,10 @@ namespace BrewMonster.Scripts.Task.UI
|
||||
OnShowDialog();
|
||||
OnCommand_havequest();
|
||||
}
|
||||
private new void OnDisable()
|
||||
{
|
||||
OnHideDialog();
|
||||
}
|
||||
|
||||
private new void Awake()
|
||||
{
|
||||
@@ -345,10 +349,6 @@ namespace BrewMonster.Scripts.Task.UI
|
||||
CECUIHelper.FollowCoord(entityID, taskID);
|
||||
}
|
||||
|
||||
private new void Update()
|
||||
{
|
||||
Tick();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -713,7 +713,7 @@ namespace BrewMonster.Scripts.Task.UI
|
||||
return string.Empty;
|
||||
}
|
||||
//
|
||||
private bool Tick()
|
||||
public bool Tick()
|
||||
{
|
||||
RefreshTaskTrace();
|
||||
// Time-window task refresh: while in Search view, refresh the list when server time crosses a minute boundary.
|
||||
@@ -1386,6 +1386,15 @@ namespace BrewMonster.Scripts.Task.UI
|
||||
if (m_idSelTask != 0)
|
||||
UpdateTask();
|
||||
}
|
||||
void OnHideDialog()
|
||||
{
|
||||
if (m_szName != "Win_Quest") return;
|
||||
var pTree = m_pTv_Quest;
|
||||
var pItem = pTree?.GetSelectedItem();
|
||||
if( pItem )
|
||||
m_idSelTask = (int)pTree.GetItemData(pItem);
|
||||
else m_idSelTask = 0;
|
||||
}
|
||||
// virtual void OnHideDialog();
|
||||
// virtual bool OnChangeLayout(PAUIOBJECT pMine, PAUIOBJECT pTheir);
|
||||
// virtual void OnChangeLayoutEnd(bool bAllDone);
|
||||
|
||||
@@ -31,9 +31,9 @@ namespace BrewMonster.Scripts.Task.UI
|
||||
[SerializeField] protected Toggle m_pChk_Collapse;
|
||||
[SerializeField] protected GameObject m_pCollapsedArea;
|
||||
protected Dictionary<string, int> m_uniqueNameCountMap = new Dictionary<string, int>();
|
||||
[SerializeField] protected Button m_pBtnUnTrace;
|
||||
[SerializeField] protected Button m_pBtnMap;
|
||||
[SerializeField] protected Button m_pBtnChat;
|
||||
// [SerializeField] protected Button m_pBtnUnTrace;
|
||||
// [SerializeField] protected Button m_pBtnMap;
|
||||
// [SerializeField] protected Button m_pBtnChat;
|
||||
[SerializeField] protected Button m_pBtnFinishTaskByContribution;
|
||||
[SerializeField] protected Button m_pBtnContributionTaskHelp;
|
||||
protected int m_nLastTracedTasks; // ����ʾ���ݶ�Ӧ����������������ijЩ����������������б����л���
|
||||
@@ -53,11 +53,11 @@ namespace BrewMonster.Scripts.Task.UI
|
||||
//AUI_ON_COMMAND("Rdo_Quest*", OnCommand_SwitchShowType)
|
||||
//Not sure if we need this
|
||||
//AUI_ON_COMMAND("Btn_UnTrace", OnCommand_UnTraceTask)
|
||||
m_pBtnUnTrace.onClick.AddListener(OnCommand_UnTraceTask);
|
||||
//AUI_ON_COMMAND("Btn_Map", OnCommand_Map)
|
||||
m_pBtnMap.onClick.AddListener(OnCommand_Map);
|
||||
//AUI_ON_COMMAND("Btn_ForChat", OnCommand_Chat)
|
||||
m_pBtnChat.onClick.AddListener(UpdateContributionTask);
|
||||
// m_pBtnUnTrace.onClick.AddListener(OnCommand_UnTraceTask);
|
||||
// //AUI_ON_COMMAND("Btn_Map", OnCommand_Map)
|
||||
// m_pBtnMap.onClick.AddListener(OnCommand_Map);
|
||||
// //AUI_ON_COMMAND("Btn_ForChat", OnCommand_Chat)
|
||||
// m_pBtnChat.onClick.AddListener(UpdateContributionTask);
|
||||
//AUI_ON_COMMAND("Btn_Finish", OnCommand_FinishTask)
|
||||
//m_pBtnFinishTaskByContribution.onClick.AddListener(() => OnCommand_FinishTask(null));
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ public class CECUIManager : MonoSingleton<CECUIManager>
|
||||
Sprite[] m_iconlistIvtr;
|
||||
private CDlgInfoTooltip m_pDlgSkillTooltip;
|
||||
|
||||
// Task update timer / 任务更新计时器
|
||||
private float _nextTaskUpdateTime = 0f;
|
||||
private const float TASK_UPDATE_INTERVAL = .1f;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
@@ -58,6 +62,42 @@ public class CECUIManager : MonoSingleton<CECUIManager>
|
||||
// _fpsText.text = $"{Mathf.RoundToInt(1f / Time.deltaTime)}";
|
||||
if (m_pDlgQuickBar1 != null)
|
||||
{ m_pDlgQuickBar1.UpdateShortcuts(); }
|
||||
|
||||
// Periodically update task UI (DlgTask and DlgTaskTrace) / 定期更新任务UI(DlgTask和DlgTaskTrace)
|
||||
if (Time.unscaledTime >= _nextTaskUpdateTime)
|
||||
{
|
||||
_nextTaskUpdateTime = Time.unscaledTime + TASK_UPDATE_INTERVAL;
|
||||
UpdateTaskUI();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update task UI from DlgTask and DlgTaskTrace / 从DlgTask和DlgTaskTrace更新任务UI
|
||||
/// </summary>
|
||||
private void UpdateTaskUI()
|
||||
{
|
||||
try
|
||||
{
|
||||
var inGameUIMan = GetInGameUIMan();
|
||||
if (inGameUIMan == null) return;
|
||||
|
||||
var dlgTaskDialog = inGameUIMan.GetDialog("Win_Quest");
|
||||
var dlgTaskTraceDialog = inGameUIMan.GetDialog("Win_QuestMinion");
|
||||
if (dlgTaskDialog != null && dlgTaskDialog is BrewMonster.Scripts.Task.UI.DlgTask dlgTaskForTrace)
|
||||
{
|
||||
if (dlgTaskTraceDialog != null && dlgTaskTraceDialog.IsShow())
|
||||
{
|
||||
dlgTaskForTrace.RefreshTaskTrace();
|
||||
}
|
||||
dlgTaskForTrace.Tick();
|
||||
}
|
||||
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
// Silently handle errors to avoid spamming logs / 静默处理错误以避免日志刷屏
|
||||
// Task UI update errors are handled silently / 任务UI更新错误被静默处理
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
|
||||
Reference in New Issue
Block a user