From 39092a47d5cb7d41b00428dcea52112c506b8fa5 Mon Sep 17 00:00:00 2001 From: MinhHai Date: Sun, 16 Nov 2025 16:46:39 +0700 Subject: [PATCH] update logic search task --- .../Scripts/Task/ATaskTemplMan.cs | 54 +- .../Scripts/Task/CECTaskInterface.cs | 185 ++++- .../Scripts/Task/TaskInterface.cs | 37 +- .../Scripts/Task/TaskTempl.Method.cs | 757 ++++++++++++++++++ Assets/PerfectWorld/Scripts/Task/TaskTempl.cs | 52 +- .../Scripts/Task/UI/TaskTreeView.cs | 27 +- .../Scripts/Task/UI/TaskTreeViewItem.cs | 37 +- .../Scripts/Task/UI/TaskWindow.cs | 320 ++++++-- 8 files changed, 1358 insertions(+), 111 deletions(-) diff --git a/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs b/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs index 85211c1766..9c336af594 100644 --- a/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs +++ b/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs @@ -208,8 +208,8 @@ namespace BrewMonster.Scripts.Task m_ExlusiveAwardTaskMap[pTask.m_FixedData.m_ID] = pTask; #if _TASK_CLIENT - if (pTask.m_FixedData.m_ulDelvNPC != 0 && pTask.m_FixedData.m_bCanSeekOut) - m_TasksCanSeekOut.Add(pTask); + if (pTask.m_FixedData.m_ulDelvNPC != 0 && pTask.m_FixedData.m_bCanSeekOut) + m_TasksCanSeekOut.Add(pTask); #endif AddTaskToMap(pTask); @@ -217,7 +217,7 @@ namespace BrewMonster.Scripts.Task private void AddTaskToMap(ATaskTempl pTempl) { - if (pTempl.m_FixedData.m_enumMethod == (ulong)TaskMethod.enumTMProtectNPC && pTempl.m_FixedData.m_ulNPCToProtect > 0) + if (pTempl.m_FixedData.m_enumMethod == (ulong)TaskCompletionMethod.enumTMProtectNPC && pTempl.m_FixedData.m_ulNPCToProtect > 0) m_ProtectNPCMap[pTempl.m_FixedData.m_ulNPCToProtect] = pTempl; m_AllTemplMap[pTempl.m_FixedData.m_ID] = pTempl; @@ -310,6 +310,54 @@ namespace BrewMonster.Scripts.Task // } return false; } + + // 可接任务列表 // Available tasks list + public void GetAvailableTasks(TaskInterface pPlayer, List lst) + { + if (lst == null) return; + if (lst.Capacity < 256) lst.Capacity = 256; // 预留容量 // reserve capacity + + string log = ""; + + int count = m_TasksCanSeekOut.Count; + for (int i = 0; i < count; i++) + { + ATaskTempl pTempl = m_TasksCanSeekOut[i]; + if (pTempl == null) continue; + + // 如果等级条件不满足则跳过 // Skip if level requirements are not met + if (!pTempl.CheckReachLevel(pPlayer)) continue; + + // 玩家可接此任务则加入列表 // If player can accept this task, add to list + + var failCode = pPlayer.CanDeliverTask(pTempl.m_FixedData.m_ID); + if (failCode == 0) + { + lst.Add(pTempl); + } + else + { + log += $"Task ID {pTempl.m_FixedData.m_ID} Fail : {failCode} \n"; + } + + if (i % 1000 == 0) + { + Debug.Log($"--- {i % 1000} Find Available Task --- \n {log}"); + log = ""; + } + } + + + } + + // 占位:可接返回0,不可接返回非0 // Placeholder: return 0 if deliverable, non-zero otherwise + // private int CanDeliverTask(TaskInterface pPlayer, uint templId) + // { + // // 后续可替换为正式逻辑 // Replace with real logic later + // var impl = pPlayer; + // return (impl != null && impl.IsDeliverLegal()) ? 0 : 1; + // } + #endif } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs b/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs index 6d0d795ecf..9db97d4859 100644 --- a/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs +++ b/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs @@ -445,6 +445,8 @@ namespace BrewMonster.Scripts.Task public bool IsDeliverLegal() { // return !m_pHost->IsTrading() && m_pHost->GetBoothState() == 0 && !m_pHost->IsDead(); + return true; + // TODO: implement return m_pHost.IsTrading() && m_pHost.GetBoothState() == 0 && !m_pHost.IsDead(); } @@ -512,7 +514,8 @@ namespace BrewMonster.Scripts.Task // resolve template for top-level entries; children left unresolved in C# if (entry.m_ParentIndex == (char)0xff) { - entry.m_ulTemplAddr = 0u; + // entry.m_ulTemplAddr = 0u; + entry.m_ulTemplAddr = pMan.GetTopTaskByID(entry.m_ID) != null ? 1u : 0u; ATaskTempl topTempl = pMan.GetTopTaskByID(entry.m_ID); if (topTempl != null) @@ -575,6 +578,12 @@ namespace BrewMonster.Scripts.Task { return EC_Game.GetGameRun().GetCommonData(lKey); } + // C++: long CECTaskInterface::GetGlobalValue(long lKey) + public long GetGlobalValue(long key) + { + // NOTE: Engine exposes only int common data; cast to long + return EC_Game.GetGameRun().GetCommonData((int)key); + } public byte GetShapeMask() { @@ -599,13 +608,13 @@ namespace BrewMonster.Scripts.Task ATaskTempl pTempl = GetTaskTemplMan().GetTaskTemplByID(task_id); if (pTempl == null) return false; - if (pTempl.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMSimpleClientTask && pTempl.m_FixedData.m_uiEmotion != 0) + if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTask && pTempl.m_FixedData.m_uiEmotion != 0) { if (m_emotionTask != null && m_emotionTask.TryGetValue(task_id, out bool finished)) return finished; return false; } - else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMSimpleClientTaskForceNavi) + else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTaskForceNavi) { return GetForceNavigateFinishFlag(); } @@ -636,6 +645,145 @@ namespace BrewMonster.Scripts.Task return false; } + // ===== Additional TaskInterface methods ported from C++ ===== + public uint GetMaxHistoryLevel() + { + // TODO: Use reincarnation tome when available (GetReincarnationTome().max_level) + return (uint)m_pHost.GetBasicProps().iLevel; + } + + public uint GetReincarnationCount() + { + // TODO: Hook to host reincarnation count when available + return 0u; + } + + public bool IsRealmExpFull() + { + // TODO: Implement via host API when available + return false; + } + + public uint GetReputation() + { + // TODO: Expose reputation on host; return 0 for now + return 0u; + } + + public int GetFactionRole() + { + // TODO: Expose faction role id on host + return 0; + } + + public bool IsInFaction(uint factionId) + { + // TODO: Expose faction id on host; cannot verify now + return false; + } + + public bool IsMale() + { + return m_pHost.m_iGender == GENDER.GENDER_MALE; + } + + public uint GetPlayerOccupation() + { + return (uint)m_pHost.m_iProfession; + } + + public uint GetCurPeriod() + { + // Maps to "second level" in basic props (realm level) + return (uint)m_pHost.GetBasicProps().iLevel2; + } + + public bool IsGM() + { + // TODO: Expose GM flag on host + return false; + } + + public bool IsShieldUser() + { + // TODO: Expose ShieldUser flag on host + return false; + } + + public bool IsMarried() + { + // TODO: Expose spouse id on host + return false; + } + + public bool IsWeddingOwner() + { + // TODO: Expose wedding scene info and compare with host id + return false; + } + + public uint GetInvEmptySlot() + { + return (uint)EC_Inventory.GetEmptySlotNum(EC_Inventory.IVTRTYPE_PACK); + } + + public int GetFactionContrib() + { + return m_pHost.GetContribInfo().cumulate_contrib; + } + + public int GetForce() + { + // TODO: Expose force id on host + return 0; + } + + public int GetForceReputation() + { + // TODO: Expose force reputation on host + return 0; + } + + public int GetForceContribution() + { + // TODO: Expose force contribution on host + return 0; + } + + public int GetExp() + { + return m_pHost.GetBasicProps().iExp; + } + + public int GetSP() + { + return m_pHost.GetBasicProps().iSP; + } + + public int GetForceActivityLevel() + { + // TODO: Expose force activity level on host + return -1; + } + + public bool IsKing() + { + // TODO: Expose king status on host + return false; + } + + public bool IsInTeam() + { + // TODO: Implement team system and check membership + return false; + } + + public uint GetAccountTotalCash() + { + // TODO: Expose account total cash on host/session + return 0u; + } + #if _TASK_CLIENT // Prepare award preview based on task and state public void GetTaskAwardPreview(uint ulTaskId, ref Task_Award_Preview p, bool bActiveTask=true) @@ -807,6 +955,23 @@ namespace BrewMonster.Scripts.Task return 0u; } + + public uint CanDeliverTask(uint ulTaskId) + { + ATaskTempl pTempl = GetTaskTemplMan().GetTopTaskByID(ulTaskId); + if (pTempl == null) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_NO_TASK; + + if (!IsDeliverLegal()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_INDETERMINATE; + + // return pTempl->CheckPrerequisite(this, static_cast(GetActiveTaskList()), GetCurTime(), true, true, false); + return pTempl.CheckPrerequisite(this, GetActiveTaskList(), GetCurTime(), true, true, false); + + // if (!pTempl.CheckReachLevel(this)) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_BELOW_LEVEL; + // uint keyCheck = pTempl.CheckGlobalKeyValue(this, false); + // if (keyCheck != 0u) return keyCheck; + + return 0u; + } #endif @@ -885,7 +1050,7 @@ namespace BrewMonster.Scripts.Task if (pTempl.m_FixedData.m_ulGoldWanted != 0) pInfo.m_ulGoldWanted = pTempl.m_FixedData.m_ulGoldWanted; // 任务类型分支 // Task method branches - if (pTempl.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMCollectNumArticle) + if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMCollectNumArticle) { for (int j = 0; j < pTempl.m_FixedData.m_ulItemsWanted; j++) { @@ -895,7 +1060,7 @@ namespace BrewMonster.Scripts.Task pInfo.m_ItemsWanted[j].m_ulItemsGained = ATaskTempl._get_item_count(this, iw.m_ulItemTemplId, iw.m_bCommonItem); } } - else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMKillNumMonster) + else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMKillNumMonster) { int ulItemCount = 0; int ulMonsterCount = 0; @@ -926,7 +1091,7 @@ namespace BrewMonster.Scripts.Task } } } - else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMKillPlayer) + else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMKillPlayer) { int ulItemCount = 0; int ulPlayerCount = 0; @@ -957,20 +1122,20 @@ namespace BrewMonster.Scripts.Task } } } - else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMProtectNPC) + else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMProtectNPC) { pInfo.m_ulNPCToProtect = pTempl.m_FixedData.m_ulNPCToProtect; pInfo.m_ulProtectTime = pTempl.m_FixedData.m_ulProtectTimeLen; } - else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMWaitTime) + else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMWaitTime) { pInfo.m_ulWaitTime = pTempl.m_FixedData.m_ulWaitTime; } - else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMGlobalValOK) + else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMGlobalValOK) { pTempl.GetGlobalTaskChar(this, pInfo.m_TaskCharArr); } - else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMReachLevel) + else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMReachLevel) { pInfo.m_ulReachLevel = pTempl.m_FixedData.m_ulReachLevel; pInfo.m_ulReachReincarnation = pTempl.m_FixedData.m_ulReachReincarnationCount; diff --git a/Assets/PerfectWorld/Scripts/Task/TaskInterface.cs b/Assets/PerfectWorld/Scripts/Task/TaskInterface.cs index 7eb9efb4f9..2a31733edf 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskInterface.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskInterface.cs @@ -41,11 +41,44 @@ namespace BrewMonster.Scripts.Task bool HasTask(uint ulTaskId); - #if _TASK_CLIENT +#if _TASK_CLIENT void GetTaskAwardPreview(uint ulTaskId,ref Task_Award_Preview p, bool bActiveTask = true); uint GetTaskCount(); uint GetTaskId(uint ulIndex); - #endif + + uint CanDeliverTask(uint ulTaskId); +#endif + // bool HasTask(uint taskId); + // bool CheckTaskForbid(uint taskId); + long GetGlobalValue(long key); + // uint GetPlayerLevel(); + uint GetMaxHistoryLevel(); + uint GetReincarnationCount(); + bool IsRealmExpFull(); + uint GetReputation(); + // uint GetGoldNum(); + int GetFactionRole(); + bool IsInFaction(uint factionId); + bool IsMale(); + uint GetPlayerOccupation(); + uint GetCurPeriod(); + bool IsGM(); + bool IsShieldUser(); + bool IsMarried(); + // bool IsAtCrossServer(); + bool IsWeddingOwner(); + uint GetInvEmptySlot(); + int GetFactionContrib(); + // byte GetShapeMask(); + int GetForce(); + int GetForceReputation(); + int GetForceContribution(); + int GetExp(); + int GetSP(); + int GetForceActivityLevel(); + bool IsKing(); + bool IsInTeam(); + uint GetAccountTotalCash(); } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/TaskTempl.Method.cs b/Assets/PerfectWorld/Scripts/Task/TaskTempl.Method.cs index ed260ece41..ede8415632 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskTempl.Method.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskTempl.Method.cs @@ -5,6 +5,270 @@ namespace BrewMonster.Scripts.Task { public partial class ATaskTempl { + public uint GetID() + { + return m_FixedData.m_ID; + } + + // Process Part + + public uint CheckPrerequisite( + TaskInterface pTask, + ActiveTaskList pList, + uint ulCurTime, + bool bCheckPrevTask = true, + bool bCheckTeam = true, + bool bCheckBudge = true, + bool bCheckLevel = true) + { + uint ulRet = 0u; + + // �����Ǹ��ڵ� // English: Not the root node + if (m_pParent != null) + { + ulRet = (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_NOT_ROOT; + goto ret_here; + } + + if (bCheckBudge) + { + ulRet = CheckBudget(pList); + if (ulRet != 0u) goto ret_here; + } + // else if (pList->GetEntry(m_ID)) // English: Already has the same task + else if (pTask.HasTask(m_FixedData.m_ID)) + { + ulRet = (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_SAME_TASK; + goto ret_here; + } + + // �Ƿ����� // English: Is task forbidden + if (pTask.CheckTaskForbid(m_FixedData.m_ID)) + { + ulRet = (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_TASK_FORBID; + goto ret_here; + } + + // ��ΪPQ�����ж������Ƿ��Ѿ���PQ���� // English: If current is PQ task, ensure no existing PQ task + if (m_FixedData.m_bPQTask) + { + for (byte i = 0; i < pList.m_uTaskCount; i++) + { + var CurEntry = pList.m_TaskEntries[i]; + if (CurEntry == null) continue; + ATaskTempl pTempl = CurEntry.GetTempl(); + + if (pTempl != null && pTempl.m_FixedData.m_bPQTask) + { + ulRet = (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_ALREADY_HAS_PQ; + goto ret_here; + } + } + } + + ulRet = CheckGivenItems(pTask); + if (ulRet != 0u) goto ret_here; + + // �Ƿ����㷢��ʱ�� // English: Check if within delivery timetable + ulRet = CheckTimetable(ulCurTime); + if (ulRet != 0u) goto ret_here; + + // ����ʱ���� // English: Check deliver time + ulRet = CheckDeliverTime(pTask, ulCurTime); + if (ulRet != 0u) goto ret_here; + + ulRet = CheckFnshLst(pTask, ulCurTime); + if (ulRet != 0u) goto ret_here; + + // �Ƿ�ﵽ�˺�������ɴ��� // English: Check daily deliver count limit + ulRet = CheckDeliverCount(pTask); + if (ulRet != 0u) goto ret_here; + + // �Ƿ�ﵽ��ֵ��� // English: Check RMB/account balance + ulRet = CheckAccountRMB(pTask); + if (ulRet != 0u) goto ret_here; + + // �Ƿ������ɫ������¼ʱ������ // English: Check character time requirements + ulRet = CheckCharTime(pTask); + if (ulRet != 0u) goto ret_here; + + // Check Level // English: Level constraints + if (bCheckLevel) + { + ulRet = CheckLevel(pTask); + if (ulRet != 0u) goto ret_here; + } + + // ת������ // English: Reincarnation constraints + ulRet = CheckReincarnation(pTask); + if (ulRet != 0u) goto ret_here; + + // ����ȼ� // English: Realm level constraints + ulRet = CheckRealmLevel(pTask); + if (ulRet != 0u) goto ret_here; + + // ���羭���Ƿ����� // English: Realm exp full check + ulRet = CheckRealmExpFull(pTask); + if (ulRet != 0u) goto ret_here; + + // ���� // English: Reputation check + ulRet = CheckRepu(pTask); + if (ulRet != 0u) goto ret_here; + + // Ѻ�� // English: Deposit check + ulRet = CheckDeposit(pTask); + if (ulRet != 0u) goto ret_here; + + // ������Ʒ // English: Items check + ulRet = CheckItems(pTask); + if (ulRet != 0u) goto ret_here; + + // ���� // English: Faction check + ulRet = CheckFaction(pTask); + if (ulRet != 0u) goto ret_here; + + // �Ա� // English: Gender check + ulRet = CheckGender(pTask); + if (ulRet != 0u) goto ret_here; + + // ְҵ // English: Occupation check + ulRet = CheckOccupation(pTask); + if (ulRet != 0u) goto ret_here; + + // �����ض�ʱ�� // English: Specific period check + ulRet = CheckPeriod(pTask); + if (ulRet != 0u) goto ret_here; + + // �Ƿ�GM // English: GM check + ulRet = CheckGM(pTask); + if (ulRet != 0u) goto ret_here; + + // �Ƿ���������û� // English: Shielded user check + ulRet = CheckShieldUser(pTask); + if (ulRet != 0u) goto ret_here; + + // �������� // English: Previous task check + if (bCheckPrevTask) + { + ulRet = CheckPreTask(pTask); + if (ulRet != 0u) goto ret_here; + } + + // �������� // English: Mutex task check + ulRet = CheckMutexTask(pTask, ulCurTime); + if (ulRet != 0u) goto ret_here; + + // ���򴥷� // English: In-zone trigger check + ulRet = CheckInZone(pTask); + if (ulRet != 0u) goto ret_here; + + // ������� // English: Team task check + if (bCheckTeam) + { + ulRet = CheckTeamTask(pTask); + if (ulRet != 0u) goto ret_here; + } + + // ���� // English: Spouse check + ulRet = CheckSpouse(pTask); + if (ulRet != 0u) goto ret_here; + + ulRet = CheckWeddingOwner(pTask); + if (ulRet != 0u) goto ret_here; + + // ���� // English: Marriage check + ulRet = CheckMarriage(pTask); + if (ulRet != 0u) goto ret_here; + + // ����������� // English: Living skill check + ulRet = CheckLivingSkill(pTask); + if (ulRet != 0u) goto ret_here; + + // �������� // English: Special award activity check + ulRet = CheckSpecialAward(pTask); + if (ulRet != 0u) goto ret_here; + + // ȫ��key/value // English: Global key/value + ulRet = CheckGlobalKeyValue(pTask, false); + if (ulRet != 0u) goto ret_here; + + if (m_FixedData.m_bCompareItemAndInventory) + { + ulRet = CheckIvtrEmptySlot(pTask); + if (ulRet != 0u) goto ret_here; + } + // ���ɹ��׶� // English: Faction contribution check + ulRet = CheckFactionContrib(pTask); + if (ulRet != 0u) goto ret_here; + + // ��¼��ɽ��������ɸ��� // English: Recorded tasks number check + ulRet = CheckRecordTasksNum(pTask); + if (ulRet != 0u) goto ret_here; + + // ����״̬ // English: Transform mask check + ulRet = CheckTransform(pTask); + if (ulRet != 0u) goto ret_here; + + // ���� // English: Force check + ulRet = CheckForce(pTask); + if (ulRet != 0u) goto ret_here; + + // �������� // English: Force reputation check + ulRet = CheckForceReputation(pTask); + if (ulRet != 0u) goto ret_here; + + // ����ս�� // English: Force contribution check + ulRet = CheckForceContribution(pTask); + if (ulRet != 0u) goto ret_here; + + // ����ֵ // English: EXP check + ulRet = CheckExp(pTask); + if (ulRet != 0u) goto ret_here; + + // Ԫ��ֵ // English: SP check + ulRet = CheckSP(pTask); + if (ulRet != 0u) goto ret_here; + + // ������Ծ�ȼ� // English: Force activity level check + ulRet = CheckForceActivityLevel(pTask); + if (ulRet != 0u) goto ret_here; + + // ���� // English: King check + ulRet = CheckKing(pTask); + if (ulRet != 0u) goto ret_here; + + // ������� // English: Not in team check + ulRet = CheckNotInTeam(pTask); + if (ulRet != 0u) goto ret_here; + // �ƺ� // English: Title check + ulRet = CheckTitle(pTask); + if (ulRet != 0u) goto ret_here; + + // ��ʷ�ƽ��׶� // English: History stage check + ulRet = CheckHistoryStage(pTask); + if (ulRet != 0u) goto ret_here; + + // �ռ����� // English: Card collection count check + ulRet = CheckCardCollection(pTask); + if (ulRet != 0u) goto ret_here; + + // ����ijƷ��ӵ������ // English: Specific card rank count check + ulRet = CheckCardRankCount(pTask); + if (ulRet != 0u) goto ret_here; + + // �����󣬲��ܽ�ȡǿ���ƶ����� // English: No navigate when in transform shape + ulRet = CheckInTransformShape(pTask); + if (ulRet != 0u) goto ret_here; + + ret_here: + + // TODO: pTask.GetPlayerId() not available in managed interface; use 0 + string log = $"CheckPrerequisite: ret = {ulRet}"; + CECTaskInterface.WriteLog(0, (int)m_FixedData.m_ID, 1, log); + + return ulRet; + } + #if _TASK_CLIENT // bool CanShowTask (TaskInterface* pTask) const; // bool HasShowCond() const; @@ -290,5 +554,498 @@ namespace BrewMonster.Scripts.Task return m.m_FixedData.m_bKeyTask; } + + // ===== Missing methods converted from C++ (TaskTempl.inl) ===== + // 保留原中文注释,并在旁加入英文翻译 + + // inline unsigned long _get_item_count(TaskInterface* pTask, unsigned long ulItemId, bool bCommon) + // 获取道具数量(通用/任务) // English: Get item count (common/task) + // public static uint _get_item_count(TaskInterface pTask, uint ulItemId, bool bCommon) + // { + // return bCommon ? pTask.GetCommonItemCount(ulItemId) : pTask.GetTaskItemCount(ulItemId); + // } + + // inline unsigned long ATaskTempl::CheckBudget(ActiveTaskList* pList) const + // 检查任务栏容量与空间 // English: Check task list budget and space + public uint CheckBudget(ActiveTaskList pList) + { + // TODO: Convert full logic with TASK_HIDDEN_COUNT/TASK_TITLE_TASK_COUNT/TASK_ACTIVE_LIST_MAX_LEN and list counters when constants and fields are available + // 占位返回通过 // English: Placeholder pass + return 0u; + } + + // inline unsigned long ATaskTempl::CheckGivenItems(TaskInterface* pTask) const + // 检查交付所需道具容量合法性 // English: Check deliverable item capacity + public uint CheckGivenItems(TaskInterface pTask) + { + // TODO: Use m_FixedData.m_ulGivenItems, m_ulGivenCmnCount, m_ulGivenTskCount and pTask.CanDeliver* API when fields confirmed + return 0u; + } + + // inline unsigned long ATaskTempl::CheckTimetable(unsigned long ulCurTime) const + // 检查任务可接时间表 // English: Check task timetable window + public uint CheckTimetable(uint ulCurTime) + { + // TODO: Implement judge_time_date against m_FixedData.m_tmStart/m_tmEnd/m_tmType + return 0u; + } + + // inline unsigned long ATaskTempl::CheckDeliverTime(TaskInterface* pTask, unsigned long ulCurTime) const + // 检查任务发放频率限制(日/周/月/年) // English: Check deliver frequency limits (day/week/month/year) + public uint CheckDeliverTime(TaskInterface pTask, uint ulCurTime) + { + // TODO: Implement with FinishedTimeList/FinishedCntList and timezone bias when types are available + return 0u; + } + + // inline unsigned long ATaskTempl::CheckFnshLst(TaskInterface* pTask, unsigned long ulCurTime) const + // 检查完成与失败记录是否允许重复领取 // English: Check finished/failed list for redo permissions + public uint CheckFnshLst(TaskInterface pTask, uint ulCurTime) + { + // TODO: Implement using FinishedTaskList and m_FixedData.m_bCanRedo/m_bCanRedoAfterFailure + return 0u; + } + + // inline unsigned long ATaskTempl::CheckDeliverCount(TaskInterface* pTask) const + // 检查周期内角色/账号次数限制 // English: Check period deliver counts for role/account + public uint CheckDeliverCount(TaskInterface pTask) + { + // TODO: Implement with FinishedCountList/FinishedTaskList based on account/role limits + return 0u; + } + + // inline unsigned long ATaskTempl::CheckAccountRMB(TaskInterface* pTask) const + // 检查账号现金(RMB)范围 // English: Check account total cash (RMB) range + public uint CheckAccountRMB(TaskInterface pTask) + { + if (m_FixedData.m_ulPremRMBMin != 0u && m_FixedData.m_ulPremRMBMax != 0u) + { + uint total = pTask.GetAccountTotalCash(); + if (total < m_FixedData.m_ulPremRMBMin || total > m_FixedData.m_ulPremRMBMax) + { + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_RMB_NOT_ENOUGH; + } + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckCharTime(TaskInterface* pTask) const + // 检查角色创建/登录时间窗口 // English: Check character time window + public uint CheckCharTime(TaskInterface pTask) + { + // TODO: Implement using m_FixedData.m_bCharTime, m_iCharStartTime/m_iCharEndTime, m_tmCharEndTime and pTask time APIs + return 0u; + } + + // inline unsigned long ATaskTempl::CheckLevel(TaskInterface* pTask) const + // 等级上下限 // English: Level min/max + public uint CheckLevel(TaskInterface pTask) + { + uint level = m_FixedData.m_bPremCheckMaxHistoryLevel > 0 ? pTask.GetMaxHistoryLevel() : pTask.GetPlayerLevel(); + if (m_FixedData.m_ulPremise_Lev_Min != 0u && level < m_FixedData.m_ulPremise_Lev_Min) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_BELOW_LEVEL; + if (m_FixedData.m_ulPremise_Lev_Max != 0u && level > m_FixedData.m_ulPremise_Lev_Max) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_ABOVE_LEVEL; + return 0u; + } + + // inline unsigned long ATaskTempl::CheckReincarnation(TaskInterface* pTask) const + // 转生次数上下限 // English: Reincarnation count min/max + public uint CheckReincarnation(TaskInterface pTask) + { + if (m_FixedData.m_bPremCheckReincarnation) + { + uint count = pTask.GetReincarnationCount(); + if (count < m_FixedData.m_ulPremReincarnationMin) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_BELOW_REINCARNATION; + if (count > m_FixedData.m_ulPremReincarnationMax) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_ABOVE_REINCARNATION; + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckRealmLevel(TaskInterface* pTask) const + // 修真境界等级 // English: Realm level + public uint CheckRealmLevel(TaskInterface pTask) + { + if (m_FixedData.m_bPremCheckRealmLevel) + { + uint level = GetRealmLevel(pTask); + if (level < m_FixedData.m_ulPremRealmLevelMin) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_BELOW_REALMLEVEL; + if (level > m_FixedData.m_ulPremRealmLevelMax) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_ABOVE_REALMLEVEL; + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckRealmExpFull(TaskInterface* pTask) const + // 修真经验是否已满 // English: Realm EXP full check + public uint CheckRealmExpFull(TaskInterface pTask) + { + if (m_FixedData.m_bPremCheckRealmExpFull) + { + if (!pTask.IsRealmExpFull()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_REALM_EXP_FULL; + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckRepu(TaskInterface* pTask) const + // 声望上下限 // English: Reputation min/max + public uint CheckRepu(TaskInterface pTask) + { + if (m_FixedData.m_lPremise_Reputation != 0 && pTask.GetReputation() < (uint)m_FixedData.m_lPremise_Reputation) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_BELOW_REPU; + if (m_FixedData.m_lPremise_RepuMax != 0 && pTask.GetReputation() > (uint)m_FixedData.m_lPremise_RepuMax) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_BELOW_REPU; + return 0u; + } + + // inline unsigned long ATaskTempl::CheckDeposit(TaskInterface* pTask) const + // 寄存金(金币) // English: Deposit (gold) + public uint CheckDeposit(TaskInterface pTask) + { + if (m_FixedData.m_ulPremise_Deposit != 0u && pTask.GetGoldNum() < m_FixedData.m_ulPremise_Deposit) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_NO_DEPOSIT; + return 0u; + } + + // inline unsigned long ATaskTempl::CheckItems(TaskInterface* pTask) const + // 前置道具检查(任一/全部) // English: Prerequisite item check (any/ALL) + public uint CheckItems(TaskInterface pTask) + { + // TODO: Implement using m_FixedData.m_ulPremItems, m_bPremItemsAnyOne, m_PremItems[] + return 0u; + } + + // inline unsigned long ATaskTempl::CheckFaction(TaskInterface* pTask) const + // 家族/帮派及职位 // English: Faction/clan and role + public uint CheckFaction(TaskInterface pTask) + { + int role = pTask.GetFactionRole(); + bool roleOk = role <= m_FixedData.m_iPremise_FactionRole; + if (m_FixedData.m_ulPremise_Faction != 0u && !(pTask.IsInFaction(m_FixedData.m_ulPremise_Faction) && roleOk)) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_CLAN; + return 0u; + } + + // inline unsigned long ATaskTempl::CheckGender(TaskInterface* pTask) const + // 性别 // English: Gender + public uint CheckGender(TaskInterface pTask) + { + bool isMale = pTask.IsMale(); + if (m_FixedData.m_ulGender == TaskTemplConstants.TASK_GENDER_MALE && !isMale) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_WRONG_GENDER; + if (m_FixedData.m_ulGender == TaskTemplConstants.TASK_GENDER_FEMALE && isMale) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_WRONG_GENDER; + return 0u; + } + + // inline unsigned long ATaskTempl::CheckOccupation(TaskInterface* pTask) const + // 职业 // English: Occupation + public uint CheckOccupation(TaskInterface pTask) + { + if (m_FixedData.m_ulOccupations == 0u) return 0u; + uint current = pTask.GetPlayerOccupation(); + for (uint i = 0; i < m_FixedData.m_ulOccupations; i++) + { + if (m_FixedData.m_Occupations[i] == current) + return 0u; + } + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_NOT_IN_OCCU; + } + + // inline unsigned long ATaskTempl::CheckPeriod(TaskInterface* pTask) const + // 历练阶段(区间) // English: Period check (interval) + public uint CheckPeriod(TaskInterface pTask) + { + uint cur = pTask.GetCurPeriod(); + if (cur < m_FixedData.m_ulPremise_Period) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_WRONG_PERIOD; + if (m_FixedData.m_ulPremise_Period < 20u) return 0u; + if (m_FixedData.m_ulPremise_Period < 30u) return cur < 30u ? 0u : (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_WRONG_PERIOD; + if (m_FixedData.m_ulPremise_Period < 40u) return cur < 40u ? 0u : (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_WRONG_PERIOD; + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_WRONG_PERIOD; + } + + // inline unsigned long ATaskTempl::CheckGM(TaskInterface* pTask) const + // GM 限制 // English: GM check + public uint CheckGM(TaskInterface pTask) + { + return m_FixedData.m_bGM ? (pTask.IsGM() ? 0u : (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_GM) : 0u; + } + + // inline unsigned long ATaskTempl::CheckShieldUser(TaskInterface* pTask) const + // 屏蔽用户 // English: Shielded user + public uint CheckShieldUser(TaskInterface pTask) + { + return m_FixedData.m_bShieldUser ? (pTask.IsShieldUser() ? 0u : (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_SHIELD_USER) : 0u; + } + + // inline unsigned long ATaskTempl::CheckPreTask(TaskInterface* pTask) const + // 前置任务 // English: Previous tasks + public uint CheckPreTask(TaskInterface pTask) + { + // TODO: Implement using FinishedTaskList and m_FixedData.m_ulPremise_Tasks[*] + return 0u; + } + + // (No inline in provided snippet) 互斥任务 // English: Mutex task + public uint CheckMutexTask(TaskInterface pTask, uint ulCurTime) + { + // TODO: Implement when mutex task data is available + return 0u; + } + + // inline unsigned long ATaskTempl::CheckInZone(TaskInterface* pTask) const + // 区域检查 // English: In-zone check + public uint CheckInZone(TaskInterface pTask) + { + // TODO: Implement worldId + region bounding box check using m_FixedData.m_ulDelvWorld and m_pDelvRegion + return 0u; + } + + // inline unsigned long ATaskTempl::CheckTeamTask(TaskInterface* pTask) const + // 组队接任务要求 // English: Team-task requirements + public uint CheckTeamTask(TaskInterface pTask) + { + // TODO: Implement full team captain and member checks per HasAllTeamMemsWanted + return 0u; + } + + // inline unsigned long ATaskTempl::CheckSpouse(TaskInterface* pTask) const + // 配偶要求 // English: Spouse requirement + public uint CheckSpouse(TaskInterface pTask) + { + if (m_FixedData.m_bPremise_Spouse && !pTask.IsMarried()) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_INDETERMINATE; + return 0u; + } + + // inline unsigned long ATaskTempl::CheckWeddingOwner(TaskInterface* pTask) const + // 婚礼举办者检查 // English: Wedding owner check + public uint CheckWeddingOwner(TaskInterface pTask) + { + if (m_FixedData.m_bPremiseWeddingOwner) + { + if (pTask.IsAtCrossServer()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_CROSSSERVER_NO_MARRIAGE; + if (!pTask.IsWeddingOwner()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_WEDDING_OWNER; + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckMarriage(TaskInterface* pTask) const + // 结婚任务条件 // English: Marriage task requirements + public uint CheckMarriage(TaskInterface pTask) + { + // TODO: Implement two-person team with opposite gender per original logic if APIs exist + return 0u; + } + + // inline unsigned long ATaskTempl::CheckLivingSkill(TaskInterface* pTask) const + // 生活技能等级 // English: Living skill level + public uint CheckLivingSkill(TaskInterface pTask) + { + // TODO: Loop m_FixedData.m_lSkillLev[MAX_LIVING_SKILLS] with skill ids and pTask.HasLivingSkill/GetLivingSkillLevel + return 0u; + } + + // inline unsigned long ATaskTempl::CheckIvtrEmptySlot(TaskInterface* pTask) const + // 背包空位检查 // English: Inventory empty slot check + public uint CheckIvtrEmptySlot(TaskInterface pTask) + { + if (!m_FixedData.m_bCompareItemAndInventory) return 0u; + if (pTask.GetInvEmptySlot() < m_FixedData.m_ulInventorySlotNum) + { + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_NOT_IVTRSLOTNUM; + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckFactionContrib(TaskInterface* pTask) const + // 家族贡献 // English: Faction contribution + public uint CheckFactionContrib(TaskInterface pTask) + { + int contrib = pTask.GetFactionContrib(); + if (m_FixedData.m_iPremiseFactionContrib != 0 && contrib < m_FixedData.m_iPremiseFactionContrib) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_BELOW_FACTION_CONTRIB; + return 0u; + } + + // inline unsigned long ATaskTempl::CheckRecordTasksNum(TaskInterface* pTask) const + // 完成记录任务数量 // English: Finished-record tasks count + public uint CheckRecordTasksNum(TaskInterface pTask) + { + // TODO: Implement using FinishedTaskList scanning for recorded tasks count + return 0u; + } + + // inline unsigned long ATaskTempl::CheckTransform(TaskInterface* pTask) const + // 变身形态 // English: Transform mask + public uint CheckTransform(TaskInterface pTask) + { + byte playerShapeType = pTask.GetShapeMask(); + // 0xFF 不限制 // English: 0xFF = no restriction + if (m_FixedData.m_ucPremiseTransformedForm == 0xFF) return 0u; + // 职业变身 // English: Occupation transform + if (m_FixedData.m_ucPremiseTransformedForm == 0x80) + { + if ((playerShapeType >> 6) != 2) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_TRANSFORM_MASK; + return 0u; + } + // 指定形态 // English: Specific form + if (m_FixedData.m_ucPremiseTransformedForm != playerShapeType) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_TRANSFORM_MASK; + return 0u; + } + + // inline unsigned long ATaskTempl::CheckForce(TaskInterface* pTask) const + // 势力检查 // English: Force check + public uint CheckForce(TaskInterface pTask) + { + if (m_FixedData.m_bPremCheckForce) + { + if (pTask.IsAtCrossServer()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_CROSSSERVER_NO_FORCE; + if (m_FixedData.m_iPremForce == -1) + { + if (pTask.GetForce() == 0) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_FORCE; + } + else if (pTask.GetForce() != m_FixedData.m_iPremForce) + { + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_FORCE; + } + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckForceReputation(TaskInterface* pTask) const + // 势力声望 // English: Force reputation + public uint CheckForceReputation(TaskInterface pTask) + { + if (m_FixedData.m_iPremForceReputation != 0) + { + if (pTask.IsAtCrossServer()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_CROSSSERVER_NO_FORCE; + if (pTask.GetForceReputation() < m_FixedData.m_iPremForceReputation) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_FORCE_REPUTATION; + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckForceContribution(TaskInterface* pTask) const + // 势力贡献 // English: Force contribution + public uint CheckForceContribution(TaskInterface pTask) + { + if (m_FixedData.m_iPremForceContribution != 0) + { + if (pTask.IsAtCrossServer()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_CROSSSERVER_NO_FORCE; + if (pTask.GetForceContribution() < m_FixedData.m_iPremForceContribution) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_FORCE_REPUTATION; + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckExp(TaskInterface* pTask) const + // 势力经验 // English: Force EXP + public uint CheckExp(TaskInterface pTask) + { + if (m_FixedData.m_iPremForceExp != 0) + { + if (pTask.IsAtCrossServer()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_CROSSSERVER_NO_FORCE; + if (pTask.GetExp() < m_FixedData.m_iPremForceExp) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_EXP; + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckSP(TaskInterface* pTask) const + // 势力SP // English: Force SP + public uint CheckSP(TaskInterface pTask) + { + if (m_FixedData.m_iPremForceSP != 0) + { + if (pTask.IsAtCrossServer()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_CROSSSERVER_NO_FORCE; + if (pTask.GetSP() < m_FixedData.m_iPremForceSP) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_SP; + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckForceActivityLevel(TaskInterface* pTask) const + // 势力活跃等级 // English: Force activity level + public uint CheckForceActivityLevel(TaskInterface pTask) + { + if (m_FixedData.m_iPremForceActivityLevel != -1) + { + if (pTask.IsAtCrossServer()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_CROSSSERVER_NO_FORCE; + if (m_FixedData.m_iPremForceActivityLevel != pTask.GetForceActivityLevel()) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_FORCE_AL; + } + return 0u; + } + + // inline unsigned long ATaskTempl::CheckKing(TaskInterface* pTask) const + // 王检查 // English: King check + public uint CheckKing(TaskInterface pTask) + { + if (m_FixedData.m_bPremIsKing && !pTask.IsKing()) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_KING; + return 0u; + } + + // inline unsigned long ATaskTempl::CheckNotInTeam(TaskInterface* pTask) const + // 不在队伍 // English: Not in team + public uint CheckNotInTeam(TaskInterface pTask) + { + if (m_FixedData.m_bPremNotInTeam && pTask.IsInTeam()) + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_IN_TEAM; + return 0u; + } + + // inline unsigned long ATaskTempl::CheckTitle(TaskInterface* pTask) const + // 称号检查 // English: Title check + public uint CheckTitle(TaskInterface pTask) + { + // TODO: Implement using m_FixedData.m_iPremTitleNumTotal/m_iPremTitleNumRequired and award title arrays + return 0u; + } + + // inline unsigned long ATaskTempl::CheckHistoryStage(TaskInterface* pTask) const + // 历史阶段 // English: History stage + public uint CheckHistoryStage(TaskInterface pTask) + { + // TODO: Implement using pTask.GetCurHistoryStageIndex() and m_FixedData.m_iPremHistoryStageIndex[2] + return 0u; + } + + // inline unsigned long ATaskTempl::CheckCardCollection(TaskInterface* pTask) const + // 将星卡收集数量 // English: General card collection count + public uint CheckCardCollection(TaskInterface pTask) + { + // TODO: Implement using pTask.GetObtainedGeneralCardCount() and m_FixedData.m_ulPremGeneralCardCount + return 0u; + } + + // inline unsigned long ATaskTempl::CheckCardRankCount(TaskInterface* pTask) const + // 指定品级将星卡数量 // English: Specific rank general card count + public uint CheckCardRankCount(TaskInterface pTask) + { + // TODO: Implement using pTask.GetObtainedGeneralCardCountByRank(rank) and m_FixedData fields + return 0u; + } + + // inline unsigned long ATaskTempl::CheckInTransformShape(TaskInterface* pTask) const + // 变身中禁止导航 // English: No navigate while in shaped + public uint CheckInTransformShape(TaskInterface pTask) + { + if (m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTaskForceNavi && pTask.GetShapeMask() != 0) + { + return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_NO_NAVIGATE_INSHPAED; + } + return 0u; + } + + // 特殊活动奖励检查 // English: Special award activity check + public uint CheckSpecialAward(TaskInterface pTask) + { + // 非“特殊活动奖励”类型则直接通过 // English: Pass if not a special-award dynamic task + if (m_FixedData.m_DynTaskType != (byte)DynTaskType.enumDTTSpecialAward) return 0u; + // 未配置特殊奖励标识则失败 // English: Fail if special award id not configured + if (m_FixedData.m_ulSpecialAward == 0u) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_SPECIAL_AWARD; + + // TODO: 获取玩家特殊奖励信息并校验 // English: Fetch player's special-award info and validate against required id + // 受限于当前 TaskInterface 未暴露获取接口,暂时视为通过 // English: Interface lacks API; treat as pass for now + return 0u; + } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs b/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs index 482bea78fc..4f509ec9f1 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs @@ -1132,27 +1132,27 @@ namespace BrewMonster.Scripts.Task /// /// Completion Method /// - public enum TaskMethod - { - enumTMNone = 0, // None - enumTMKillNumMonster, // Kill a number of monsters - enumTMCollectNumArticle, // Collect a number of items - enumTMTalkToNPC, // Talk to a specific NPC - enumTMReachSite, // Reach a specific location - enumTMWaitTime, // Wait for a specified time - enumTMAnswerQuestion, // Answer a question - enumTMTinyGame, // Mini-game - enumTMProtectNPC, // Protect a specific NPC - enumTMNPCReachSite, // NPC reaches a specific location - enumTMGlobalValOK, // Global variable condition satisfied - enumTMLeaveSite, // Leave a specific location - enumTMReachTreasureZone, // Reach the treasure area - enumTMKillPlayer, // Kill another player - enumTMTransform, // Transform state - enumTMReachLevel, // Check level: normal level, rebirth count, realm level - enumTMSimpleClientTask, // Simple client task (only client-side validation, currently just checks UI triggers) - enumTMSimpleClientTaskForceNavi // Force navigation - } + // public enum TaskCompletionMethod + // { + // enumTMNone = 0, // None + // enumTMKillNumMonster, // Kill a number of monsters + // enumTMCollectNumArticle, // Collect a number of items + // enumTMTalkToNPC, // Talk to a specific NPC + // enumTMReachSite, // Reach a specific location + // enumTMWaitTime, // Wait for a specified time + // enumTMAnswerQuestion, // Answer a question + // enumTMTinyGame, // Mini-game + // enumTMProtectNPC, // Protect a specific NPC + // enumTMNPCReachSite, // NPC reaches a specific location + // enumTMGlobalValOK, // Global variable condition satisfied + // enumTMLeaveSite, // Leave a specific location + // enumTMReachTreasureZone, // Reach the treasure area + // enumTMKillPlayer, // Kill another player + // enumTMTransform, // Transform state + // enumTMReachLevel, // Check level: normal level, rebirth count, realm level + // enumTMSimpleClientTask, // Simple client task (only client-side validation, currently just checks UI triggers) + // enumTMSimpleClientTaskForceNavi // Force navigation + // } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct COMPARE_KEY_VALUE @@ -3989,13 +3989,13 @@ namespace BrewMonster.Scripts.Task // 根据完成方式设置掩码 // Set mask according to completion method uint method = m_FixedData.m_enumMethod; - if (method == (uint)TaskMethod.enumTMKillNumMonster) + if (method == (uint)TaskCompletionMethod.enumTMKillNumMonster) m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_KILL_MONSTER; - else if (method == (uint)TaskMethod.enumTMCollectNumArticle) + else if (method == (uint)TaskCompletionMethod.enumTMCollectNumArticle) m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_COLLECT_ITEM; - else if (method == (uint)TaskMethod.enumTMTalkToNPC) + else if (method == (uint)TaskCompletionMethod.enumTMTalkToNPC) m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_TALK_TO_NPC; - else if (method == (uint)TaskMethod.enumTMKillPlayer) + else if (method == (uint)TaskCompletionMethod.enumTMKillPlayer) m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_KILL_PLAYER; // PQ子任务使用对应掩码 // PQ subtask uses corresponding mask @@ -4031,7 +4031,7 @@ namespace BrewMonster.Scripts.Task m_FixedData.m_ulNextSibling = (m_pNextSibling != null) ? m_pNextSibling.m_FixedData.m_ID : 0u; m_FixedData.m_ulPrevSibling = (m_pPrevSibling != null) ? m_pPrevSibling.m_FixedData.m_ID : 0u; m_FixedData.m_ulFirstChild = (m_pFirstChild != null) ? m_pFirstChild.m_FixedData.m_ID : 0u; - if (m_pFirstChild != null) m_FixedData.m_enumMethod = (uint)TaskMethod.enumTMNone; + if (m_pFirstChild != null) m_FixedData.m_enumMethod = (uint)TaskCompletionMethod.enumTMNone; } // 添加子任务到层级结构 // Add sub task to hierarchy diff --git a/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs b/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs index b6a8f00f7b..8ba28cf49f 100644 --- a/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs +++ b/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeView.cs @@ -1,6 +1,8 @@ using System; +using System.Collections; using UnityEngine; using UnityEngine.Events; +using UnityEngine.UI; namespace BrewMonster.PerfectWorld.Scripts.Task.UI { @@ -19,7 +21,7 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI SetSelectedItem(evt.Data); }); } - + public void SetItemData(TaskTreeViewItem item, uint taskType) { item.SetItemData(taskType); @@ -60,6 +62,8 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI // Parent: root (this) if null; otherwise under given parent item var parentTransform = (pParent != null ? pParent.transform : this.transform); go.transform.SetParent(parentTransform, false); + RefreshLayout(parentTransform.GetComponent()); + RefreshLayout(this.GetComponent()); // Set sibling position: after specific item if provided; otherwise append to end if (pAfter != null && pAfter.transform.parent == parentTransform) @@ -79,10 +83,22 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI // Refresh local cache of items m_aTreeViewItems = GetComponentsInChildren(); - + return pItem; } + public void DeleteAllItems() + { + foreach (Transform child in transform) + { + Destroy(child.gameObject); + } + + m_aTreeViewItems = null; + _currentSelectedItem = null; + } + + public TaskTreeViewItem GetItemByData(uint taskType) { if (m_aTreeViewItems == null) @@ -110,6 +126,13 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI { _currentSelectedItem = GetItemByData(idItem); } + + public void RefreshLayout(RectTransform parent) + { + // Force Unity to rebuild layout immediately + parent.ForceUpdateRectTransforms(); + LayoutRebuilder.ForceRebuildLayoutImmediate(parent); + } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeViewItem.cs b/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeViewItem.cs index 52bb325a1f..f466fa6872 100644 --- a/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeViewItem.cs +++ b/Assets/PerfectWorld/Scripts/Task/UI/TaskTreeViewItem.cs @@ -1,3 +1,4 @@ +using System; using TMPro; using UnityEngine; using UnityEngine.Events; @@ -6,7 +7,7 @@ using UnityEngine.UI; namespace BrewMonster.PerfectWorld.Scripts.Task.UI { - public class TaskTreeViewItem : MonoBehaviour, IPointerClickHandler + public class TaskTreeViewItem : MonoBehaviour { [SerializeField] private TMP_Text m_text; [SerializeField] private Button m_Button; @@ -16,7 +17,28 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI public UnityEvent OnClick = new UnityEvent(); - + + #region UNITY_METHODS + + private void Awake() + { + m_Button.onClick.AddListener(OnBtnClick); + + + } + + // private void Start() + // { + // RectTransform parent = transform.parent.GetComponent(); + // if (parent != null && parent.GetComponent()) + // { + // // Force Unity to rebuild layout immediately + // parent.ForceUpdateRectTransforms(); + // LayoutRebuilder.ForceRebuildLayoutImmediate(parent); + // } + // } + + #endregion public void SetItemData(uint uItemData) { m_uItemData = uItemData; @@ -45,12 +67,19 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI } } - public void OnPointerClick(PointerEventData eventData) + // public void OnPointerClick(PointerEventData eventData) + // { + // OnClick.Invoke(m_uItemData); + // EventBus.Publish(new TaskItemClickEvent() { Data = m_uItemData }); + // // TaskWindow.Instance.OnEventLButtonDown_Tv_Quest(m_uItemData); + // } + + void OnBtnClick() { OnClick.Invoke(m_uItemData); EventBus.Publish(new TaskItemClickEvent() { Data = m_uItemData }); - // TaskWindow.Instance.OnEventLButtonDown_Tv_Quest(m_uItemData); } + } public struct TaskItemClickEvent diff --git a/Assets/PerfectWorld/Scripts/Task/UI/TaskWindow.cs b/Assets/PerfectWorld/Scripts/Task/UI/TaskWindow.cs index a9a31edac7..d797f6393e 100644 --- a/Assets/PerfectWorld/Scripts/Task/UI/TaskWindow.cs +++ b/Assets/PerfectWorld/Scripts/Task/UI/TaskWindow.cs @@ -7,6 +7,8 @@ using BrewMonster.Network; using BrewMonster.Scripts.Task; using CSNetwork.GPDataType; using ModelRenderer.Scripts.GameData; +using NUnit.Framework; +using PerfectWorld.Scripts.Task; using UnityEngine; using UnityEngine.UI; using TMPro; @@ -94,9 +96,12 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI [SerializeField] protected Button m_pBtn_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; // PAUILABEL -> TMP_Text + [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 @@ -141,6 +146,10 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI OnEventLButtonDown_Tv_Quest(evt.Data); }); + m_pBtn_HaveQuest.onClick.AddListener(OnCommand_havequest); + m_pBtn_SearchQuest.onClick.AddListener(OnCommand_searchquest); + + OnInitDialog(); } @@ -153,8 +162,36 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI #region PUBLIC METHODS - public void OnCommand_searchquest(string szCommand) {} - public void OnCommand_havequest(string szCommand) {} + public void OnCommand_searchquest() + { + // if (m_szName != "Win_Quest") return; + m_iType = 1; + // TODO + // PAUIOBJECT pObj = GetDlgItem("Img_New"); + // if (pObj && IsShow()) pObj->Show(false); + // if(GetDlgItem("Lab_Trace")) GetDlgItem("Lab_Trace")->Show(false); + if(m_pBtn_bShowTrace) m_pBtn_bShowTrace.gameObject.SetActive(false); + m_pBtn_Abandon.gameObject.SetActive(false); + Btn_Focus.gameObject.SetActive(false); + Lab_QuestNO.gameObject.SetActive(false); + m_pTxt_QuestNO.gameObject.SetActive(false); + m_pBtn_SearchQuest.interactable = false; + m_pBtn_HaveQuest.interactable = true; + SearchForTask(); + } + public void OnCommand_havequest() + { + m_iType = 0; + // TODO: if(GetDlgItem("Lab_Trace")) GetDlgItem("Lab_Trace")->Show(true); + if(m_pBtn_bShowTrace) m_pBtn_bShowTrace.gameObject.SetActive(true); + m_pBtn_Abandon.gameObject.SetActive(true); + Btn_Focus.gameObject.SetActive(true); + Lab_QuestNO.gameObject.SetActive(true); + m_pTxt_QuestNO.gameObject.SetActive(true); + m_pBtn_SearchQuest.interactable = true; + m_pBtn_HaveQuest.interactable = false; + UpdateTask(); + } public void OnCommand_showtrace(string szCommand) {} public void OnCommand_focus(string szCommand) {} public void OnCommand_abandon(string szCommand) {} @@ -180,7 +217,7 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI // if( pItem ) OnCommand_focus("focus"); // } // P_AUITREEVIEW_ITEM pItem = pTree->GetSelectedItem(); - var pItem = m_pTv_Quest.GetItemByData(itemData); + // var pItem = m_pTv_Quest.GetItemByData(itemData); int idTask = (int)itemData; // int idTask(0); // if( pItem && pTree->GetParentItem(pItem) != pTree->GetRootItem()) @@ -282,8 +319,7 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI } else if (m_iType == 1) { - // TODO - // SearchForTask(pTree->GetItemData(pItem)); + SearchForTask((int)pTree.GetItemData(pItem)); } } else @@ -363,14 +399,11 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI strNewTextItem = ""; // Base desc - UpdateTaskBaseDesc(strNewTextItem, tsi); - - // Deliver NPC - UpdateDeliverNPC(strNewTextItem, (int)pTemp.GetDeliverNPC()); + UpdateTaskBaseDesc(ref strNewTextItem, tsi); // Award NPC int nANPC = (int)pTemp.GetAwardNPC(); - UpdateAwardNPC(strNewTextItem, nANPC); + UpdateAwardNPC(ref strNewTextItem, nANPC); // Complete condition UpdateCompleteCondition(ref strNewTextItem, ref strNewHintItem, tsi); @@ -379,7 +412,7 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI UpdateItemWanted(ref strNewTextItem, tsi, idTask); // Treasure Map - UpdateTreasureMap(strNewTextItem); + UpdateTreasureMap(ref strNewTextItem); // Task Confirm UpdateTaskConfirm(idTask, pTemp.m_FixedData.m_enumFinishType == (uint)TaskFinishType.enumTFTConfirm); @@ -396,7 +429,7 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI if (Btn_TreasureMap != null) { Btn_TreasureMap.gameObject. - SetActive(pTemp.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMReachTreasureZone); + SetActive(pTemp.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMReachTreasureZone); } } } @@ -420,12 +453,132 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI } // GetGameUIMan()->ReplaceColor(&strNewTextItem, A3DCOLORRGB(255, 255, 255), pTextItem->GetColor()); - // SetTextItemText(strNewTextItem, pMan.GetTaskTemplByID((uint)idTask) != null && !bLastTaskChanged, strNewHintItem); + SetTextItemText(strNewTextItem, pMan.GetTaskTemplByID((uint)idTask) != null && !bLastTaskChanged, strNewHintItem); return true; } // - // bool SearchForTask(int idTask = -1); + // Guard: only handle search list when current UI type is 1 (search) + public bool SearchForTask(int idTask = -1) + { + if (m_iType != 1) + { + return true; + } + + // Setup managers and UI references + ATaskTemplMan pMan = EC_Game.GetTaskTemplateMan(); + CECTaskInterface pTask = GetHostPlayer().GetTaskInterface(); + var pTextDesc = m_pTxt_Content; + var pTextItem = m_pTxt_QuestItem; + + // Track composed text buffers and change flag + string strNewTextItem = ""; + string strNewHintItem = ""; + bool bLastTaskChanged = false; + + // Simplified: assume we are in quest UI context if tree exists + bool bQuestUI = m_pTv_Quest != null; + + // When a concrete task id is provided + if (idTask >= 0) + { + ATaskTempl pTemp = pMan != null ? pMan.GetTaskTemplByID((uint)idTask) : null; + if (pTemp != null) + { + // Update description when the selected task changes + if (idTask != m_idLastTask) + { + if (pTextDesc != null) pTextDesc.SetText(pTemp.GetDescription()); + m_idLastTask = idTask; + bLastTaskChanged = true; + } + + // Optional: update tree item text if needed (skip if API not available) + if (bQuestUI) + { + var pItem = m_pTv_Quest.GetSelectedItem(); + if (pItem != null) + { + uint id = m_pTv_Quest.GetItemData(pItem); + // NOTE: ATaskTemplMan.IsTaskToPush may be conditionally compiled; avoid hard dependency + // If needed, uncomment when method is available: + // if (pMan.IsTaskToPush((int)id)) m_pTv_Quest.SetItemText(pItem, GetTaskNameWithColor(pTemp)); + } + } + + // Get task state info + Task_State_info tsi = default; + if (pTask != null) pTask.GetTaskStateInfo((uint)idTask, ref tsi, false); + + // Reset composed text buffer + strNewTextItem = ""; + + // Append: base description + UpdateTaskBaseDesc(ref strNewTextItem, tsi); + + // Append: deliver NPC + UpdateDeliverNPC(ref strNewTextItem, (int)pTemp.GetDeliverNPC()); + + // Append: award NPC + int nANPC = (int)pTemp.GetAwardNPC(); + UpdateAwardNPC(ref strNewTextItem, nANPC); + + // Append: completion conditions + UpdateCompleteCondition(ref strNewTextItem, ref strNewHintItem, tsi); + + // Append: wanted items + UpdateItemWanted(ref strNewTextItem, tsi, idTask); + + // Preview and show awards + Task_Award_Preview award = default; + if (pTask != null) pTask.GetTaskAwardPreview((uint)idTask, ref award); + UpdateBaseAward(award); + UpdateItemAward(award); + } + else + { + // No template found for id: clear content + m_idLastTask = -2; + if (m_pTxt_Content != null) m_pTxt_Content.SetText(""); + if (m_pTxt_QuestItem != null) m_pTxt_QuestItem.SetText(""); + } + } + else + { + // zhangyitian 20140521 先将可接任务列表清空,再判断是否有可接任务 + // zhangyitian 20140521 First clear the available tasks list, then check if there are available tasks + // 修正了原先没有可接任务时,可接任务列表显示已接任务的问题 + // Fix: prevent accepted tasks from showing when there are no available tasks + ClearContent(false); + + // TaskTemplLst ttl; + List ttl = new List(); // TaskTemplLst -> List + pMan.GetAvailableTasks(pTask, ttl); + if( ttl.Count <= 0 ) return true; + + for(int i = 0; i < ttl.Count; i++ ) + { + int id = (int)ttl[i].GetID(); + AddTaskNode(id); + } + + SortTaskNodeByType(); + + // string strTemp; + // ActiveTaskList pLst = (ActiveTaskList)pTask.GetActiveTaskList(); + // int iMaxTaskCount = pLst->GetMaxSimultaneousCount(); + // strTemp.Format(_AL("%d/%d"), pTask->GetTaskCount(), iMaxTaskCount); + // m_pTxt_QuestNO->SetText(strTemp); + } + + // Apply colors and set composed text into UI + bool hasTempl = idTask >= 0 && pMan != null && pMan.GetTaskTemplByID((uint)idTask) != null; + SetTextItemText(strNewTextItem, hasTempl && !bLastTaskChanged, strNewHintItem); + + // Done + return true; + } // // //�������������б��������ɽ�������ѽ����� zhangyitian // bool UpdateQuestView(); @@ -554,8 +707,8 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI if (pTextItem == null) return; // Preserve scroll position if inside a ScrollRect - UnityEngine.UI.ScrollRect scrollRect = pTextItem.GetComponentInParent(); - float oldNormPos = scrollRect != null ? scrollRect.verticalNormalizedPosition : 0f; + // UnityEngine.UI.ScrollRect scrollRect = pTextItem.GetComponentInParent(); + // float oldNormPos = scrollRect != null ? scrollRect.verticalNormalizedPosition : 0f; if (!string.Equals(strNewTextItem, pTextItem.text)) { @@ -563,11 +716,11 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI // TODO: apply hint to a tooltip UI if available (strNewHintItem) } - if (keepScrollPos && scrollRect != null) - { - // Restore previous scroll position - scrollRect.verticalNormalizedPosition = oldNormPos; - } + // if (keepScrollPos && scrollRect != null) + // { + // // Restore previous scroll position + // scrollRect.verticalNormalizedPosition = oldNormPos; + // } } // void SetTaskText(PAUIOBJECT pObj, ACString* pStr); @@ -585,36 +738,43 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI var sb = new System.Text.StringBuilder(); int colCount = 0; const int col = 3; + int cellSpace = 30; if (award.m_ulGold > 0) { - sb.Append(string.Format(GetStringFromTable(3201), award.m_ulGold)); - if ((++colCount) % col == 0) sb.Append("\r"); + var text = $"{GetStringFromTable(3201)} {award.m_ulGold}"; + sb.Append(text); + sb.Append(' ', cellSpace - text.Length); + if ((++colCount) % col == 0) sb.Append("\n"); } if (award.m_ulExp > 0) { - sb.Append(string.Format(GetStringFromTable(3202), award.m_ulExp)); - if ((++colCount) % col == 0) sb.Append("\r"); + var text = $"{GetStringFromTable(3201)} {award.m_ulExp}"; + sb.Append(text); + sb.Append(' ', cellSpace - text.Length); + if ((++colCount) % col == 0) sb.Append("\n"); } if (award.m_ulSP > 0) { - sb.Append(string.Format(GetStringFromTable(3203), award.m_ulSP)); - if ((++colCount) % col == 0) sb.Append("\r"); + var text = $"{GetStringFromTable(3201)} {award.m_ulSP}"; + sb.Append(text); + sb.Append(' ', cellSpace - text.Length); + if ((++colCount) % col == 0) sb.Append("\n"); } if (award.m_ulRealmExp > 0) { - sb.Append(string.Format(GetStringFromTable(3207), award.m_ulRealmExp)); - if ((++colCount) % col == 0) sb.Append("\r"); + sb.Append($"{GetStringFromTable(3207)} {award.m_ulRealmExp}"); + if ((++colCount) % col == 0) sb.Append("\n"); } if (award.m_iForceContrib > 0) { - sb.Append(string.Format(GetStringFromTable(3205), award.m_iForceContrib)); - if ((++colCount) % col == 0) sb.Append("\r"); + sb.Append($"{GetStringFromTable(3205)} {award.m_iForceContrib}"); + if ((++colCount) % col == 0) sb.Append("\n"); } if (award.m_iForceRepu > 0) { - sb.Append(string.Format(GetStringFromTable(3206), award.m_iForceRepu)); - if ((++colCount) % col == 0) sb.Append("\r"); + sb.Append($"{GetStringFromTable(3206)} {award.m_iForceRepu}"); + if ((++colCount) % col == 0) sb.Append("\n"); } if (sb.Length > 0 && m_pTxt_BaseAward != null) @@ -633,7 +793,7 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI { if (m_pTxt_BaseAward != null && m_pTxt_BaseAward.gameObject.activeSelf) { - string strAward = (GetStringFromTable(3204) ?? string.Empty) + "\r" + (m_pTxt_BaseAward.text ?? string.Empty); + string strAward = (GetStringFromTable(3204) ?? string.Empty) + "\n" + (m_pTxt_BaseAward.text ?? string.Empty); m_pTxt_BaseAward.text = strAward; } else if (m_pTxt_BaseAward != null) @@ -679,7 +839,7 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI else txtRT.anchoredPosition = pos; } } - private void UpdateTaskBaseDesc(string strText, Task_State_info tsi) + private void UpdateTaskBaseDesc(ref string strText, Task_State_info tsi) { // Build the base description text from task state var sb = new System.Text.StringBuilder(); @@ -731,30 +891,59 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI } // Apply to content text - if (m_pTxt_Content != null) - { - m_pTxt_Content.text += sb.ToString(); - } + // if (m_pTxt_Content != null) + // { + // m_pTxt_Content.text += sb.ToString(); + // } + + strText += sb.ToString(); } private static string FormatTime(int nSec, string desc, int timeLimit) { var ts = System.TimeSpan.FromSeconds(System.Math.Max(0, nSec)); string label = string.IsNullOrEmpty(desc) ? string.Empty : desc; - return $"{label}{ts:hh\\:mm\\:ss}\r"; + return $"{label}{ts:hh\\:mm\\:ss}\n"; } private static string GetStringFromTable(int id) { - // return AUIManager.GetStringFromTable(id); - return ""; - + // TODO: return AUIManager.GetStringFromTable(id); + + // HARD CODED STRINGS + switch (id) + { + case 3101: + return "Hàng ngày"; + case 3102: + return "Tu chân"; + case 3103: + return "Chủ tuyến"; + case 3105: + return "Event"; + case 3201: + return "Gold:"; + case 3202: + return "EXP:"; + case 3203: + return "SP:"; + case 3207: + return "Realm EXP:"; + case 3205: + return "Contribution:"; + case 3206: + return "Reputation:"; + case 7621: + return "NPC giao nhiệm vụ: "; + default: + return "UnKnown String"; + } } private static string GetStringFromTable(uint id) { // return AUIManager.GetStringFromTable(id); - return ""; + return GetStringFromTable((int)id); } private static string GetFixedMsg(uint id) @@ -763,7 +952,7 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI } - private void UpdateDeliverNPC(string strText, int nDNPC) + private void UpdateDeliverNPC(ref string strText, int nDNPC) { // [中文] 交付NPC // [English] Deliver NPC @@ -793,16 +982,17 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI var sb = new System.Text.StringBuilder(); sb.Append(GetStringFromTable(7620)); sb.Append(npcName); - sb.Append("\r"); - if (m_pTxt_QuestItem != null) - { - Debug.Log($"UpdateDeliverNPC: {sb.ToString()}"); - m_pTxt_QuestItem.text += sb.ToString(); - } + sb.Append("\n"); + // if (m_pTxt_QuestItem != null) + // { + // Debug.Log($"UpdateDeliverNPC: {sb.ToString()}"); + // m_pTxt_QuestItem.text += sb.ToString(); + // } + strText += sb.ToString(); } - private A3DVECTOR3 UpdateAwardNPC(string strText, int nANPC) + private A3DVECTOR3 UpdateAwardNPC(ref string strText, int nANPC) { A3DVECTOR3 ret = new A3DVECTOR3(0f); // Award NPC @@ -830,12 +1020,14 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI var sb = new System.Text.StringBuilder(); sb.Append(GetStringFromTable(7621)); sb.Append(npcName); - sb.Append("\r"); - if (m_pTxt_Content != null) - { - Debug.Log($"Award NPC: {sb.ToString()}"); - m_pTxt_QuestItem.text += sb.ToString(); - } + sb.Append("\n"); + // if (m_pTxt_Content != null) + // { + // Debug.Log($"Award NPC: {sb.ToString()}"); + // m_pTxt_QuestItem.text += sb.ToString(); + // } + + strText += sb.ToString(); return ret; } @@ -955,7 +1147,7 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI { uint killed = tsi.m_PlayerWanted[index].m_ulPlayersKilled; uint toKill = tsi.m_PlayerWanted[index].m_ulPlayersToKill; - return $" {killed}/{toKill}\r"; + return $" {killed}/{toKill}\n"; } // Get host reincarnation count (fallback implementation) @@ -1006,14 +1198,14 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI // If task is KillPlayer, also add player requirements line // 若为击杀玩家任务,同时追加玩家需求行 - if (pTempl.m_FixedData.m_enumMethod == (uint)TaskMethod.enumTMKillPlayer && i < TaskInterfaceConstants.MAX_PLAYER_WANTED) + if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMKillPlayer && i < TaskInterfaceConstants.MAX_PLAYER_WANTED) { strText += GetKillPlayerRequirements(tsi, i); } } } - private void UpdateTreasureMap(string strText) + private void UpdateTreasureMap(ref string strText) { // if (IsTreasureMapSelected()) // { @@ -1058,7 +1250,7 @@ namespace BrewMonster.PerfectWorld.Scripts.Task.UI } // TODO: Clear Tree quest view - // m_pTv_Quest.DeleteAllItems(); + m_pTv_Quest.DeleteAllItems(); } // // add node to task tree void AddTaskNode(int id)