Files
test/Assets/PerfectWorld/Scripts/Task/TaskTempl.Method.cs

294 lines
11 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 '%<digits>'
// 跳过 '%' 后面的所有数字
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;
}
}
}