using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using BrewMonster.Managers;
using BrewMonster.Scripts.Managers;
using BrewMonster.Network;
using BrewMonster.Scripts.Task;
using BrewMonster.Scripts.UI;
using BrewMonster.UI;
using CSNetwork.GPDataType;
using ModelRenderer.Scripts.Common;
using ModelRenderer.Scripts.GameData;
using NUnit.Framework;
using PerfectWorld.Scripts.Task;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using TMPro;
namespace BrewMonster.Scripts.Task.UI
{
///
/// This is DlgTask.cpp
///
public class DlgTask : AUIDialog
{
#if UNITY_EDITOR
[ContextMenu("Generate Tasks")]
public void TestUpdateTask()
{
UpdateTask(-1);
}
#endif
// Keep original macro as constant for array sizing
public const int CDLGTASK_AWARDITEM_MAX = 8;
public const int TickRate = 1000;
// ===== Nested structs (converted from C++), keep naming, public with explicit layout =====
// [中文] 任务目标位置
// [English] Task object position
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TASK_OBJECT_POS
{
public int x;
public int y;
public int z;
public int mapid;
}
// [中文] 任务完成时间
// [English] Task finished time
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TASK_FINISHED_TIME
{
public int iTaskID;
public uint dwTime; // DWORD -> uint
}
// [中文] ������������
// [English] Type grouping node
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TypeNode
{
public uint type; // DWORD -> uint
public GameObject item; // P_AUITREEVIEW_ITEM -> GameObject
}
// [中文] ��������ȼ�����
// [English] Level priority node
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct LevelNode
{
public int level;
public GameObject item; // P_AUITREEVIEW_ITEM -> GameObject
}
// ===== Converted member variables (keep original naming) =====
// protected:
protected int m_idLastTask;
protected int m_idSelTask;
protected bool m_bTraceNew;
protected bool m_bShowTrace;
protected int m_iType;
[SerializeField] protected TMP_Text _nameTaskText;
[SerializeField] protected TMP_Text m_pTxt_QuestNO; // PAUILABEL -> TMP_Text
[SerializeField] protected TaskTreeView m_pTv_Quest; // PAUITREEVIEW -> GameObject container
[SerializeField] protected TMP_Text m_pTxt_Content; // PAUITEXTAREA -> TMP_Text
[SerializeField] protected TMP_Text m_pTxt_QuestItem; // PAUITEXTAREA -> TMP_Text
[SerializeField] protected Button m_pBtn_Abandon; // PAUISTILLIMAGEBUTTON -> Button
[SerializeField] protected Button m_pBtn_MainQuest; // PAUISTILLIMAGEBUTTON -> Button
[SerializeField] protected Button m_pBtn_NormalQuest; // PAUISTILLIMAGEBUTTON -> Button
[SerializeField] protected Button m_pBtn_SearchQuest; // PAUISTILLIMAGEBUTTON -> Button
[SerializeField] protected Button m_pBtn_HaveQuest; // PAUISTILLIMAGEBUTTON -> Button
[SerializeField] protected Toggle m_pTog_bShowTrace; // PAUISTILLIMAGEBUTTON -> Button
[SerializeField] protected Button m_pBtn_FinishTask; // PAUISTILLIMAGEBUTTON -> Button
[SerializeField] protected TMP_Text m_pTxt_BaseAward; // PAUILABEL -> TMP_Text
[Space(10)]
[SerializeField] protected Button Btn_TreasureMap;
[SerializeField] protected Button Btn_Focus;
[SerializeField] protected GameObject Lab_QuestNO; // the title label of m_pTxt_QuestNO
// PAUIIMAGEPICTURE m_pImg_Item[CDLGTASK_AWARDITEM_MAX];
// Use fixed-size array semantics via initialization length
// [中文] 奖励物品图片数组
// [English] Award item images array
[MarshalAs(UnmanagedType.ByValArray, SizeConst = CDLGTASK_AWARDITEM_MAX)]
[SerializeField] protected Image[] m_pImg_Item = new Image[CDLGTASK_AWARDITEM_MAX];
protected uint m_ImgCount => (uint)m_pImg_Item.Length; // unsigned int -> uint
[SerializeField] protected Button m_pBtn_GotoNPC; // PAUISTILLIMAGEBUTTON -> Button
[SerializeField] protected GameObject m_pQuickBuyTrigger; // CECQuickBuyPopActivityTrigger* -> GameObject
// private:
private static List m_vecTasksUnFinish = new List();
private static List m_vecTasksCanFinish = new List();
private static List m_vecTasksCanGet = new List();
// [中文] 目标坐标集合
// [English] Target coordinates collection
private static List m_TargetCoord = new List();
private static string m_strTraceName = string.Empty; // ACString -> string
// [中文] 任务相关矿点映射
// [English] Mine map related to tasks
private static Dictionary m_TaskMines = new Dictionary(); // MINE_ESSENCE* -> object
// [中文] 任务跟踪计时器
// [English] Task trace counter
private CECCounter m_TaskTraceCounter = new (); // CECCounter -> object placeholder
// ===== Time-gated task UI refresh (search list) =====
// Timetable/time-window tasks become available/unavailable as server time moves.
// The original C++ client periodically re-evaluates prerequisites; in this port we refresh the search list
// at a low frequency while the Search view is open so players can see time-gated tasks appear/disappear.
private uint _lastSearchRefreshMinuteKey = uint.MaxValue;
private uint _pendingReselectTaskId = 0;
// Active-task timer refresh (wait-time / time-limit / protect-time)
private float _nextActiveTimerUiRefreshAt = 0f;
#region Unity METHODS
private new void OnEnable()
{
OnShowDialog();
OnCommand_havequest();
}
private new void OnDisable()
{
OnHideDialog();
}
private new void Awake()
{
EventBus.Subscribe(evt =>
{
OnEventLButtonDown_Tv_Quest(evt.Data);
});
m_pBtn_HaveQuest.onClick.AddListener(OnCommand_havequest);
m_pBtn_SearchQuest.onClick.AddListener(OnCommand_searchquest);
m_pBtn_Abandon.onClick.AddListener(OnCommand_abandon);
Btn_Focus.onClick.AddListener(() => OnCommand_focus());
if (m_pTog_bShowTrace)
{
m_pTog_bShowTrace.onValueChanged.AddListener((state) => OnCommand_showtrace(null,state));
}
// Convert exactly like C++ OnEventLButtonDown_Txt_QuestItem // 完全按照C++ OnEventLButtonDown_Txt_QuestItem转换
// C++ uses WM_LBUTTONDOWN event, we use EventTrigger PointerClick // C++使用WM_LBUTTONDOWN事件,我们使用EventTrigger PointerClick
if (m_pTxt_QuestItem != null)
{
// Enable raycast for TMP link detection (like C++ GetItemLinkItemOn needs link info) // 为TMP链接检测启用射线投射(如C++ GetItemLinkItemOn需要链接信息)
m_pTxt_QuestItem.raycastTarget = true;
// Add EventTrigger for PointerClick (like WM_LBUTTONDOWN in C++) // 为PointerClick添加EventTrigger(如C++中的WM_LBUTTONDOWN)
EventTrigger trigger = m_pTxt_QuestItem.GetComponent();
if (trigger == null)
{
trigger = m_pTxt_QuestItem.gameObject.AddComponent();
}
// Clear existing triggers // 清除现有触发器
trigger.triggers.Clear();
// Add PointerClick event (like WM_LBUTTONDOWN) // 添加PointerClick事件(如WM_LBUTTONDOWN)
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = EventTriggerType.PointerClick;
entry.callback.AddListener((data) => {
PointerEventData pointerData = (PointerEventData)data;
OnEventLButtonDown_Txt_QuestItem(pointerData);
});
trigger.triggers.Add(entry);
}
OnInitDialog();
}
// Convert exactly like C++ OnEventLButtonDown_Txt_QuestItem // 完全按照C++ OnEventLButtonDown_Txt_QuestItem转换
// C++: void CDlgTask::OnEventLButtonDown_Txt_QuestItem(WPARAM wParam, LPARAM lParam, AUIObject *pObj)
private void OnEventLButtonDown_Txt_QuestItem(PointerEventData eventData)
{
if (m_pTxt_QuestItem == null) return;
const string LINK_CLICK_VER = "DlgTaskLinkClickCamFix_v2";
UnityEngine.Debug.Log($"[DlgTask] OnEventLButtonDown_Txt_QuestItem: {LINK_CLICK_VER} pressEventCamera={(eventData.pressEventCamera != null ? eventData.pressEventCamera.name : "null")}");
// C++: int x = GET_X_LPARAM(lParam); int y = GET_Y_LPARAM(lParam); // C++: int x = GET_X_LPARAM(lParam); int y = GET_Y_LPARAM(lParam);
Vector2 localPoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle(
m_pTxt_QuestItem.rectTransform,
eventData.position,
eventData.pressEventCamera,
out localPoint);
UnityEngine.Debug.Log($"[DlgTask] OnEventLButtonDown_Txt_QuestItem: Click at localPoint={localPoint}, screenPos={eventData.position}");
// C++: GetItemLinkItemOn(x, y, pObj, &Item); // C++: GetItemLinkItemOn(x, y, pObj, &Item);
// Find which link was clicked (like C++ GetItemLinkItemOn checks vecItemLink[i].rc.PtInRect) // 查找点击了哪个链接(如C++ GetItemLinkItemOn检查vecItemLink[i].rc.PtInRect)
m_pTxt_QuestItem.ForceMeshUpdate();
// Debug: verify TMP parsed tags and we have linkInfo
int linkCount = m_pTxt_QuestItem.textInfo?.linkCount ?? -1;
UnityEngine.Debug.Log($"[DlgTask] OnEventLButtonDown_Txt_QuestItem: TMP linkCount={linkCount}, raycastTarget={m_pTxt_QuestItem.raycastTarget}, richText={m_pTxt_QuestItem.richText}");
if (linkCount <= 0)
{
string text = m_pTxt_QuestItem.text ?? string.Empty;
string preview = text.Substring(0, Mathf.Min(300, text.Length));
UnityEngine.Debug.LogWarning($"[DlgTask] OnEventLButtonDown_Txt_QuestItem: No links parsed. Text preview: {preview}");
return;
}
// Get camera for link detection // 获取用于链接检测的相机
Camera camera = null;
Canvas canvas = m_pTxt_QuestItem.GetComponentInParent