using BrewMonster.Scripts.Task; using PerfectWorld.Scripts.Task; namespace BrewMonster.Scripts.Task { public partial class ATaskTempl { #if _TASK_CLIENT // bool CanShowTask (TaskInterface* pTask) const; // bool HasShowCond() const; public void GetGlobalTaskChar(TaskInterface pTask, Task_State_info.abase_vector_wchar_t_ptr TaskCharArr) { // Build display strings for global expressions // 生成用于显示的全局表达式字符串 for (int i = 0; i < (int)m_FixedData.m_ulTaskCharCnt; i++) { // Read one UTF-16 row from m_pTaskChar and convert to C# string // 从 m_pTaskChar 读取一行 UTF-16 并转换为 C# 字符串 int colCount = BrewMonster.Scripts.Task.TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; ushort[] row = new ushort[colCount]; for (int j = 0; j < colCount; j++) { row[j] = m_FixedData.m_pTaskChar[i, j]; } string src = ModelRenderer.Scripts.Common.ByteToStringUtils.UshortArrayToUnicodeString(row); if (string.IsNullOrEmpty(src)) { continue; } // Parse '%' placeholders like %1, %2... and replace with computed values // 解析形如 %1, %2 的占位符并替换为计算结果 var sb = new System.Text.StringBuilder(); int idx = 0; char percent = '%'; // Percent sign // ����% (percent sign) while (idx < src.Length) { int pos = src.IndexOf(percent, idx); if (pos >= 0) { // Append text before '%' // 追加 '%' 之前的文本 sb.Append(src, idx, pos - idx); int j = pos + 1; int startDigits = j; while (j < src.Length && char.IsDigit(src[j])) j++; string digits = (j > startDigits) ? src.Substring(startDigits, j - startDigits) : string.Empty; int nVal; // If there's a valid index after '%', compute the global expression value // ��ȡ���õ�ȫ�ֱ���ʽ�к� (get referenced global expression index) if (!string.IsNullOrEmpty(digits) && int.TryParse(digits, out nVal) && nVal != 0) { // Compute one global expression // ����ȫ�ֱ���ʽ int nRet = (int)CalcOneGlobalExp(pTask, nVal - 1); // Convert number to string and append // ת�����ַ��������ַ��� sb.Append(nRet.ToString()); // Skip all digits after '%' // 跳过 '%' 后面的所有数字 idx = j; continue; } else { // No valid number found; keep the '%' // 未找到合法数字;保留 '%' sb.Append(percent); idx = pos + 1; } } else { // No more '%' found; append the rest // δ�ҵ�ȫ�ֱ�������ʽ����ֱ����ʾ�������� sb.Append(src, idx, src.Length - idx); break; } } string result = sb.ToString(); if (!string.IsNullOrEmpty(result)) { // Original: TaskCharArr.push_back(pszNewchar); // 原逻辑:将结果指针压入向量(此处托管环境不直接推入原生向量) // NOTE: If needed, map 'result' into UI/managed list here. } } } private float CalcOneGlobalExp(TaskInterface pTask, int nIndex) { // Evaluate one global expression row // 计算一行全局表达式 if (nIndex < 0 || nIndex >= (int)m_FixedData.m_ulExpCnt) { return 0f; } try { int colCount = BrewMonster.Scripts.Task.TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; float result = 0f; for (int i = 0; i < colCount; i++) { TASK_EXPRESSION expr = m_FixedData.m_pExpArr[nIndex, i]; if (expr.type == -1) break; // Sentinel terminator // 结束标记 // Fallback evaluation: accumulate values // 回退求值:累加表达式值 result += expr.value; } return result; } catch (System.Exception ex) { CECTaskInterface.WriteLog(0, (int)m_FixedData.m_ID, 0, $"CalcOneGlobalExp, Expression run err: {ex.Message}"); return 0f; } } // bool CanShowInExclusiveUI (TaskInterface* pTask, unsigned long ulCurTime) const; #else // void NotifyClient (TaskInterface* pTask, const ActiveTaskEntry* pEntry, unsigned char uReason, unsigned long ulCurTime, unsigned long ulParam = 0, int dps = 0, int dph = 0) const; // bool CheckGlobalRequired (TaskInterface* pTask, unsigned long ulSubTaskId, const TaskPreservedData* pPreserve, const TaskGlobalData* pGlobal, unsigned short reason) const; // bool CheckKillMonster (TaskInterface* pTask, ActiveTaskList* pList, ActiveTaskEntry* pEntry, unsigned long ulTemplId, unsigned long ulLev, bool bTeam, float fRand, int dps, int dph) const; // bool CheckKillPlayer (TaskInterface* pTask, ActiveTaskList* pList, ActiveTaskEntry* pEntry, int iOccupation, int iLevel, bool bGender, int iForce, float fRand) const; // void CheckCollectItem (TaskInterface* pTask, ActiveTaskList* pList, ActiveTaskEntry* pEntry, bool bAtNPC, int nChoice) const; // void CheckMonsterKilled (TaskInterface* pTask, ActiveTaskList* pList, ActiveTaskEntry* pEntry, bool bAtNPC, int nChoice) const; // void CheckMining (TaskInterface* pTask, ActiveTaskList* pList, ActiveTaskEntry* pEntry) const; // void CheckWaitTime (TaskInterface* pTask, ActiveTaskList* pList, ActiveTaskEntry* pEntry, unsigned long ulCurTime, bool bAtNPC, int nChoice) const; // void GiveUpOneTask (TaskInterface* pTask, ActiveTaskList* pList, ActiveTaskEntry* pEntry, bool bForce) const; // void OnSetFinished (TaskInterface* pTask, ActiveTaskList* pList, ActiveTaskEntry* pEntry, bool bNotifyMem = true) const; // bool DeliverAward (TaskInterface* pTask, ActiveTaskList* pList, ActiveTaskEntry* pEntry, int nChoice, bool bNotifyTeamMem = true, TaskGlobalData* pGlobal = NULL) const; // void RemoveAcquiredItem (TaskInterface* pTask, bool bClearTask, bool bSuccess) const; // void TakeAwayGivenItems (TaskInterface* pTask) const; // bool OnDeliverTeamMemTask (TaskInterface* pTask, TaskGlobalData* pGlobal) const; // unsigned long CheckDeliverTask (TaskInterface* pTask, unsigned long ulSubTaskId, TaskGlobalData* pGlobal, bool bNotifyErr = true, bool bMemTask = false, unsigned long ulCapId = 0) const; // bool HasGlobalData() const; #endif #if _TASK_CLIENT // void SyncTaskType(); // ʹ����������������游���� // bool GetShowGfxFlag() { return m_bShowGfxFinished;} // const wchar_t* GetDescription() const { assert(m_pwstrDescript); return (wchar_t*)m_pwstrDescript; } // const wchar_t* GetOkText() const { assert(m_pwstrOkText); return (wchar_t*)m_pwstrOkText; } // const wchar_t* GetNoText() const { assert(m_pwstrNoText); return (wchar_t*)m_pwstrNoText; } // const wchar_t* GetTribute() const { assert(m_pwstrTribute); return (wchar_t*)m_pwstrTribute; } // // const talk_proc* GetDeliverTaskTalk() const { return &m_DelvTaskTalk; } // const talk_proc* GetUnqualifiedTalk() const { return &m_UnqualifiedTalk; } // const talk_proc* GetDeliverItemTalk() const { return &m_DelvItemTalk; } // const talk_proc* GetUnfinishedTalk() const { return &m_ExeTalk; } // const talk_proc* GetAwardTalk() const { return &m_AwardTalk; } // // unsigned long GetDeliverNPC() const { return m_ulDelvNPC; } public uint GetAwardNPC() { return m_FixedData.m_ulAwardNPC; } // // void SaveToTextFile(FILE* fp); // bool SaveToTextFile(const char* szPath); // void SaveToBinFile(FILE* fp) { SaveBinary(fp); } // void SaveDescription(FILE* fp); // void SaveDescriptionBin(FILE* fp); // void SaveTribute(FILE* fp); // void SaveTributeBin(FILE* fp); // void SaveAllText(FILE* fp); // int MarshalKillMonster(char* pData); // int MarshalCollectItems(char* pData); // int MarshalDynTask(char* pData); // int MarshalSpecialAwardData(char* pData); // // ATaskTempl& operator= (const ATaskTempl& src); // bool operator == (const ATaskTempl& src) const // { // return *(ATaskTemplFixedData*)this == *(const ATaskTemplFixedData*)&src; // } #endif public bool _compare_key_value(TaskInterface pTask, COMPARE_KEY_VALUE CompKeyVal) { long lleftValue = CompKeyVal.lLeftNum; if (CompKeyVal.nLeftType == 0) { lleftValue = pTask.GetGlobalValue(CompKeyVal.lLeftNum); } long lRightValue = CompKeyVal.lRightNum; if (CompKeyVal.nRightType == 0) { lRightValue = pTask.GetGlobalValue(CompKeyVal.lRightNum); } switch(CompKeyVal.nCompOper) { case 0: { if (lleftValue > lRightValue) return true; } break; case 1: { if (lleftValue == lRightValue) return true; } break; case 2: { if (lleftValue < lRightValue) return true; } break; default: break; } return false; } // Early out: skip if this phase does not require key-value comparison public uint CheckGlobalKeyValue(TaskInterface pTask, bool bFinCheck) { if ((bFinCheck && !m_FixedData.m_bFinNeedComp) || (!bFinCheck && !m_FixedData.m_bPremNeedComp)) { return 0; } // Initialize comparison flags bool bFlag1 = false; bool bFlag2 = false; if (bFinCheck) { // Finish-conditions branch: evaluate two key-value comparisons bFlag1 = _compare_key_value(pTask, m_FixedData.m_Fin1KeyValue); bFlag2 = _compare_key_value(pTask, m_FixedData.m_Fin2KeyValue); // Evaluate logical mode: 0 = OR, 1 = AND if ((m_FixedData.m_nFinExp1AndOrExp2 == 0 && (bFlag1 || bFlag2)) || (m_FixedData.m_nFinExp1AndOrExp2 == 1 && (bFlag1 && bFlag2))) { return 0; } } else { // Premise-conditions branch: evaluate two key-value comparisons bFlag1 = _compare_key_value(pTask, m_FixedData.m_Prem1KeyValue); bFlag2 = _compare_key_value(pTask, m_FixedData.m_Prem2KeyValue); // Evaluate logical mode: 0 = OR, 1 = AND if ((m_FixedData.m_nPremExp1AndOrExp2 == 0 && (bFlag1 || bFlag2)) || (m_FixedData.m_nPremExp1AndOrExp2 == 1 && (bFlag1 && bFlag2))) { return 0; } } // Failure: global key-value prerequisite not satisfied return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_GLOBAL_KEYVAL; } public bool CheckReachLevel(BrewMonster.Scripts.Task.TaskInterface pTask) { bool bLevel = true, bReincarnationCount = true, bRealmLevel = true; if (m_FixedData.m_ulReachLevel != 0) bLevel = pTask.GetPlayerLevel() >= m_FixedData.m_ulReachLevel; if (m_FixedData.m_ulReachReincarnationCount != 0) bReincarnationCount = GetReincarnationCount(pTask) >= m_FixedData.m_ulReachReincarnationCount; if (m_FixedData.m_ulReachRealmLevel != 0) bRealmLevel = GetRealmLevel(pTask) >= m_FixedData.m_ulReachRealmLevel; return bLevel && bReincarnationCount && bRealmLevel; } private static uint GetReincarnationCount(BrewMonster.Scripts.Task.TaskInterface pTask) { return 0u; } private static uint GetRealmLevel(BrewMonster.Scripts.Task.TaskInterface pTask) { var host = BrewMonster.Network.EC_Game.GetGameRun()?.GetHostPlayer(); if (host != null) { var bp = host.GetBasicProps(); return (uint)bp.iLevel2; } return 0u; } public bool IsKeyTask() { ATaskTempl m = GetTopTask(); return m.m_FixedData.m_bKeyTask; } } }