294 lines
11 KiB
C#
294 lines
11 KiB
C#
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;
|
||
|
||
}
|
||
}
|
||
} |