Files
test/Assets/PerfectWorld/Scripts/Task/TaskTempl.Method.cs
T
2025-11-22 18:58:40 +07:00

2233 lines
74 KiB
C#
Raw 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 System;
using System.Runtime.InteropServices;
using BrewMonster.Network;
using BrewMonster.Scripts.Task;
using PerfectWorld.Scripts.Task;
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;
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;
public void OnServerNotify(
TaskInterface pTask,
ActiveTaskEntry pEntry,
ref task_notify_base pNotify,
uint sz)
{
uint ulTime = 0, ulCaptainTask = 0;
ActiveTaskList pLst = null;
ATaskTempl pSub = new ATaskTempl();
task_sub_tags sub_tags = new task_sub_tags();
// memset(&sub_tags, 0, sizeof(sub_tags));
uint i=0;
svr_monster_killed pKilled = null;
svr_player_killed pKilledPlayer = null;
StorageTaskList pStorage = pTask.GetStorageTaskList();
svr_treasure_map pTreasure = null;
var m_enumMethod = m_FixedData.m_enumMethod;
switch (pNotify.reason)
{
case TaskTemplConstants.TASK_SVR_NOTIFY_PLAYER_KILLED:
{
if (sz != Marshal.SizeOf<svr_player_killed>()) break;
if (m_enumMethod != (uint)TaskCompletionMethod.enumTMKillPlayer) break;
pKilledPlayer = new svr_player_killed(pNotify);
int iIndex = pKilledPlayer.index;
if (iIndex < TaskInterfaceConstants.MAX_MONSTER_WANTED)
{
pEntry.m_wMonsterNum[iIndex] = pKilledPlayer.player_num;
}
}
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_TREASURE_MAP:
if (m_enumMethod == (uint)TaskCompletionMethod.enumTMReachTreasureZone)
{
pTreasure = new svr_treasure_map(pNotify);
pEntry.m_iUsefulData1 = pTreasure.treasure_index;
}
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_MONSTER_KILLED:
if (sz != Marshal.SizeOf<svr_monster_killed>()) break;
if (m_enumMethod != (uint)TaskCompletionMethod.enumTMKillNumMonster) break;
pKilled = new svr_monster_killed(pNotify);
for (i = 0; i < m_FixedData.m_ulMonsterWanted; i++)
{
MONSTER_WANTED mw = m_FixedData.m_MonsterWanted[i];
if (mw.m_ulMonsterTemplId == pKilled.monster_id)
{
pEntry.m_wMonsterNum[i] = pKilled.monster_num;
if (pKilled.dps > 0 && pKilled.dph > 0)
{
pTask.ShowPunchBagMessage(true,pKilled.dps >= mw.m_iDPS && pKilled.dph >= mw.m_iDPH,pKilled.monster_id,pKilled.dps,pKilled.dph);
}
break;
}
}
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_NEW:
var svr_new_task = new svr_new_task(pNotify);
if (svr_new_task.valid_size((int)sz) ) break;
pLst = pTask.GetActiveTaskList();
svr_new_task.get_data(
ref ulTime,
ref ulCaptainTask,
ref sub_tags
);
GetTaskTemplMan().RemoveActiveStorageTask(pStorage, m_FixedData.m_ID);
if (sub_tags.sub_task > 0)
{
pSub = GetConstSubById(sub_tags.sub_task);
if (pSub == null) break;
}
else
pSub = null;
if (CheckBudget(pLst) > 0) break;
DeliverTask(
pTask,
pLst,
null,
ulCaptainTask,
pTask.GetTaskMask(),
ulTime,
pSub,
ref sub_tags,
new TaskGlobalData(),
0);
if (m_FixedData.m_lAvailFrequency != (int)TaskAwardFreq.enumTAFNormal &&
!m_FixedData.m_bAccountTaskLimit && !m_FixedData.m_bRoleTaskLimit)
{
// static_cast<TaskFinishTimeList*>(pTask->GetFinishedTimeList())->AddOrUpdate(
// m_ID,
// ulTime);
var TaskFinishTimeList = new TaskFinishTimeList();
TaskFinishTimeList.ReadFromBuffer(pTask.GetFinishedTimeList());
TaskFinishTimeList.AddOrUpdate(m_FixedData.m_ID, ulTime);
}
// TODO: Log new task acceptance
// if (CanShowPrompt() && !m_bDisplayInTitleTaskUI) TaskInterface::ShowTaskMessage(m_ID, TASK_MSG_NEW);
// ׷ٷʱ
if (!m_FixedData.m_bHidden && !m_FixedData.m_bDisplayInTitleTaskUI)
// TaskInterface::TraceTask(m_ID);
// TODO: Log task trace
// pTask.TraceTask(m_FixedData.m_ID);
if (m_FixedData.m_bDisplayInTitleTaskUI)
// TODO: Update title UI
// TaskInterface::UpdateTitleUI(m_ID);
if ((m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTask) && m_FixedData.m_uiEmotion > 0)
// TODO: Pop emotion UI
// TaskInterface::PopEmotionUI(m_ID,m_uiEmotion,true);
pTask.OnNewTask((int)m_FixedData.m_ID);
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_COMPLETE:
var svr_task_complete = new svr_task_complete(pNotify);
if (svr_task_complete.valid_size((int)sz)) break;
svr_task_complete.get_data(
ref ulTime,
ref sub_tags
);
pEntry.m_uState = (char)svr_task_complete.sub_tags.state;
if (!pEntry.IsSuccess())
{
#if TASK_TEMPL_EDITOR
RecursiveCheckPunchMonster(this);
#endif
}
// TODO: Log task completion
// if (CanShowPrompt() && !m_bDisplayInTitleTaskUI) TaskInterface::ShowTaskMessage(
// m_ID,
// (pEntry->IsSuccess() && !pEntry->IsGiveUp()) ? TASK_MSG_SUCCESS : TASK_MSG_FAIL);
RecursiveAward(
pTask,
pTask.GetActiveTaskList(),
pEntry,
ulTime,
-1,
ref sub_tags);
pTask.UpdateConfirmTasksMap();
// TODO: Show task completion trace
// pTask.UpdateTaskEmotionAction(m_FixedData.m_ID);
if ((m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTask)
&& m_FixedData.m_uiEmotion > 0)
// TODO: Pop emotion UI
// PopEmotionUI(m_ID,m_uiEmotion,false);
if (m_FixedData.m_bDisplayInTitleTaskUI)
// TODO: Update title UI
// UpdateTitleUI(m_ID);
pTask.OnCompleteTask((int)m_FixedData.m_ID);
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_GIVE_UP:
pLst = pTask.GetActiveTaskList();
pLst.ClearTask(pTask, pEntry, false);
// TODO: Log task give up
// if (m_bDisplayInTitleTaskUI) TaskInterface::UpdateTitleUI(m_ID);
// if ((m_enumMethod == enumTMSimpleClientTask) && m_uiEmotion)
// TaskInterface::PopEmotionUI(m_ID,m_uiEmotion,false);
pTask.OnGiveupTask((int)m_FixedData.m_ID);
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_FINISHED:
pEntry.SetFinished();
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_DIS_GLOBAL_VAL:
// DisplayTaskCharInfo(pTask, pEntry);
break;
default:
// assert(false);
break;
}
// Update task UI after processing server notification
pTask.UpdateTaskUI(pNotify.task, pNotify.reason);
}
public static void _notify_svr(TaskInterface pTask, byte uReason, ushort uTaskID)
{
task_notify_base notify = new task_notify_base();
notify.reason = uReason;
notify.task = uTaskID;
pTask.NotifyServer( ref notify, (uint)Marshal.SizeOf<task_notify_base>());
}
#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; }
public ushort[] GetTribute() { return m_pwstrTribute; }
//
public talk_proc GetDeliverTaskTalk() { return m_DelvTaskTalk; }
public talk_proc GetUnqualifiedTalk() { return m_UnqualifiedTalk; }
public talk_proc GetDeliverItemTalk() { return m_DelvItemTalk; }
public talk_proc GetUnfinishedTalk() { return m_ExeTalk; }
public talk_proc GetAwardTalk() { return m_AwardTalk; }
//
public uint GetDeliverNPC() { return m_FixedData.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;
}
// ===== 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;
}
public void ClearValidCount() { m_uValidCount = 0; }
public ATaskTemplMan GetTaskTemplMan()
{
return EC_Game.GetTaskTemplateMan();
}
public ATaskTempl GetConstSubById(uint ulId)
{
ATaskTempl pChild = m_pFirstChild;
while (pChild != null)
{
if (pChild.m_FixedData.m_ID == ulId) return pChild;
pChild = pChild.m_pNextSibling;
}
return null;
}
public ActiveTaskEntry DeliverTask(
TaskInterface pTask,
ActiveTaskList pList,
ActiveTaskEntry pEntry,
uint ulCaptainTask,
uint ulMask,
uint ulCurTime,
ATaskTempl pSubTempl,
ref task_sub_tags pSubTag,
TaskGlobalData pGlobal,
byte uParentIndex)
{
// TODO: implement full logic when ActiveTaskList/ActiveTaskEntry and TaskInterface APIs are available
return null;
/*ActiveTaskEntry* aEntries = pList->m_TaskEntries;
if (!pEntry) pEntry = aEntries + pList->m_uTaskCount;
else if (pEntry->m_ID != 0) // entryռãҪŲһλ;
pList->RealignTask(pEntry, 1);
unsigned char uIndex = static_cast<unsigned char>(pEntry - aEntries);
pEntry->m_ID = static_cast<unsigned short>(m_ID);
pEntry->m_ulTemplAddr = reinterpret_cast<unsigned long>(this);
pEntry->m_ParentIndex = uParentIndex;
pEntry->m_PrevSblIndex = 0xff;
pEntry->m_NextSblIndex = 0xff;
pEntry->m_ChildIndex = 0xff;
pEntry->m_uState = 0;
pEntry->m_ulTaskTime = ulCurTime;
#ifndef _TASK_CLIENT
// ΪPQҪʱ¼m_ulTaskTime
if (m_bPQTask)
{
pEntry->m_ulTaskTime = PublicQuestInterface::GetCurTaskStamp(m_ID);
}
#endif
if (ulCaptainTask)
{
pEntry->m_ulCapTemplAddr = reinterpret_cast<unsigned long>(GetTaskTemplMan()->GetTopTaskByID(ulCaptainTask));
if (pEntry->m_ulCapTemplAddr) pEntry->m_uCapTaskId = static_cast<unsigned short>(ulCaptainTask);
else
{
pEntry->m_uCapTaskId = 0;
char log[1024];
sprintf(log, "DeliverTask, Cant Find CapTask = %d", ulCaptainTask);
TaskInterface::WriteLog(pTask->GetPlayerId(), m_ID, 0, log);
}
}
else
{
pEntry->m_uCapTaskId = 0;
pEntry->m_ulCapTemplAddr = 0;
}
pEntry->SetSuccess(); // Later will check whether truly succeed
memset(pEntry->m_BufData, 0, sizeof(pEntry->m_BufData));
#ifndef _TASK_CLIENT
// ΪPQPQҪʱ¼m_ulTaskTime
if (m_bPQTask)
{
ulCurTime = PublicQuestInterface::GetCurTaskStamp(m_ID);
}
else if (m_enumMethod == enumTMReachTreasureZone)
{
// رλúͲرͼ½λõindex
unsigned short uZonesSum = m_ucZonesNumX * m_ucZonesNumZ;
unsigned short uTreasureLocIndex = pTask->RandNormal(1,uZonesSum);
char sTreasureLocMinX = (uTreasureLocIndex % m_ucZonesNumX - 1);
char sTreasureLocMinZ = (uTreasureLocIndex / m_ucZonesNumX);
// IJرͼλãʹرλòܴڲرͼıԵ
int sMapMinX = pTask->RandNormal(sTreasureLocMinX,sTreasureLocMinX + TASK_TREASURE_MAP_SIDE_MULTIPLE - 3) - TASK_TREASURE_MAP_SIDE_MULTIPLE + 2;
int sMapMinZ = pTask->RandNormal(sTreasureLocMinZ,sTreasureLocMinZ + TASK_TREASURE_MAP_SIDE_MULTIPLE - 3) - TASK_TREASURE_MAP_SIDE_MULTIPLE + 2;
// ѽб
pEntry->m_iUsefulData1 = uTreasureLocIndex;
pEntry->m_iUsefulData1 |= (sMapMinX << 16) & 0x00FF0000;
pEntry->m_iUsefulData1 |= (sMapMinZ << 24) & 0xFF000000;
}
ulMask |= m_ulMask;
#else
if (m_enumMethod == enumTMReachTreasureZone)
{
task_notify_base notify;
notify.reason = TASK_CLT_NOTIFY_REQUEST_TREASURE_INDEX;
notify.task = static_cast<unsigned short>(m_ID);
pTask->NotifyServer(&notify, sizeof(notify));
}
#endif
pList->m_uTaskCount++;
if (!m_pParent)
{
if (m_bHidden) pList->m_uTopHideTaskCount++;
else if (m_bDisplayInTitleTaskUI) pList->m_uTitleTaskCount++;
else pList->m_uTopShowTaskCount++;
pList->m_uUsedCount += m_uDepth;
#ifndef _TASK_CLIENT
if (pGlobal)
{
pGlobal->AddRevNum();
pGlobal->m_ulRcvUpdateTime = ulCurTime;
TaskUpdateGlobalData(m_ID, pGlobal->buf);
}
#endif
}
if (uParentIndex != 0xff)
{
ActiveTaskEntry& ParentEntry = aEntries[uParentIndex];
if (ParentEntry.m_ChildIndex == 0xff) ParentEntry.m_ChildIndex = uIndex;
else
{
unsigned char uChildEntry = ParentEntry.m_ChildIndex;
while (aEntries[uChildEntry].m_NextSblIndex != 0xff)
uChildEntry = aEntries[uChildEntry].m_NextSblIndex;
aEntries[uChildEntry].m_NextSblIndex = uIndex;
pEntry->m_PrevSblIndex = uChildEntry;
}
}
#ifndef _TASK_CLIENT
if (!m_pParent)
DeliverGivenItems(pTask);
#endif
pEntry++;
if (pSubTempl)
{
return pSubTempl->DeliverTask(
pTask,
pList,
pEntry,
0,
ulMask,
ulCurTime,
NULL,
pSubTag,
NULL,
uIndex);
}
else if (m_bRandOne)
{
#ifdef _TASK_CLIENT
if (pSubTag->cur_index < pSubTag->sz)
{
pSubTempl = GetSubByIndex(pSubTag->tags[pSubTag->cur_index]);
pSubTag->cur_index++;
if (pSubTempl)
{
return pSubTempl->DeliverTask(
pTask,
pList,
pEntry,
0,
ulMask,
ulCurTime,
NULL,
pSubTag,
NULL,
uIndex);
}
}
#else
int nSel;
pSubTempl = RandOneChild(pTask, nSel);
if (pSubTempl)
{
if (pSubTag->sz < MAX_SUB_TAGS)
pSubTag->tags[pSubTag->sz++] = static_cast<unsigned char>(nSel);
return pSubTempl->DeliverTask(
pTask,
pList,
pEntry,
0,
ulMask,
ulCurTime,
NULL,
pSubTag,
NULL,
uIndex);
}
#endif
}
else
{
const ATaskTempl* pChild = m_pFirstChild;
while (pChild)
{
pEntry = pChild->DeliverTask(
pTask,
pList,
pEntry,
0,
ulMask,
ulCurTime,
NULL,
pSubTag,
NULL,
uIndex);
if (m_bExeChildInOrder) return pEntry;
pChild = pChild->m_pNextSibling;
}
}
return pEntry;*/
}
void RecursiveAward(
TaskInterface pTask,
ActiveTaskList pList,
ActiveTaskEntry pEntry,
uint ulCurtime,
int nChoice,
ref task_sub_tags pSubTag)
{
// TODO : implement full logic when ActiveTaskList/ActiveTaskEntry and TaskInterface APIs are available
/*{
char log[1024];
sprintf(log, "RecursiveAward: state = 0x%x", pEntry->m_uState);
TaskInterface::WriteLog(pTask->GetPlayerId(), m_ID, 1, log);
}
ActiveTaskEntry* aEntries = pList->m_TaskEntries;
// ʧܲȡƷ
bool bFailedTaskDoNotTakeItem = !pEntry->IsSuccess() && m_bNotClearItemWhenFailed && m_bClearAcquired;
//
pList->ClearChildrenOf(pTask, pEntry, !bFailedTaskDoNotTakeItem);
if (!pEntry->m_ulTemplAddr) return; // must check it
if (!m_pParent && m_bNeedRecord)
{
static_cast<FinishedTaskList*>(pTask->GetFinishedTaskList())->AddOneTask(
m_ID,
pEntry->IsSuccess());
}
// ˺޴ɴ
if (!m_pParent && m_bAccountTaskLimit)
{
// ʱжǷɴ
CheckDeliverTime(pTask, ulCurtime);
// ûйѡʧܵʱ򲻼¼ɴ߹ѡʧܵʱ򲻼¼ɴɹʱ
if (!m_bNotIncCntWhenFailed || (m_bNotIncCntWhenFailed && pEntry->IsSuccess()))
static_cast<TaskFinishCountList*>(pTask->GetFinishedCntList())->AddOrUpdate(m_ID,ulCurtime);
}
// ɫ޴ɴ
else if (!m_pParent && m_bRoleTaskLimit)
{
// ʱжǷɴ
CheckDeliverTime(pTask, ulCurtime);
// ûйѡʧܵʱ򲻼¼ɴ߹ѡʧܵʱ򲻼¼ɴɹʱ
if (!m_bNotIncCntWhenFailed || (m_bNotIncCntWhenFailed && pEntry->IsSuccess())) {
// FinishedTaskListɴ
static_cast<FinishedTaskList*>(pTask->GetFinishedTaskList())->AddForFinishCount(m_ID,pEntry->IsSuccess());
// TaskFinishTimeListʱ
static_cast<TaskFinishTimeList*>(pTask->GetFinishedTimeList())->AddOrUpdate(m_ID, ulCurtime);
}
}
#ifndef _TASK_CLIENT
// Ʒ
AWARD_DATA ad;
CalcAwardData(
pTask,
&ad,
pEntry,
pEntry->m_ulTaskTime,
ulCurtime);
unsigned long ulRet = DeliverByAwardData(pTask, pList, pEntry, &ad, ulCurtime, nChoice);
if (ulRet)
{
char log[1024];
sprintf(log, "RecursiveAward, ret = %d", ulRet);
TaskInterface::WriteLog(pTask->GetPlayerId(), m_ID, 0, log);
}
// ȥõĻԤȸƷڷƷִ
if (m_bClearAcquired)
{
if (!bFailedTaskDoNotTakeItem)
RemoveAcquiredItem(pTask, false, pEntry->IsSuccess());
}
else if (!pEntry->IsSuccess())
TakeAwayGivenItems(pTask);
#endif
pEntry->m_ulTemplAddr = 0;
pEntry->m_ID = 0;
if (pList->m_uTaskCount)
pList->m_uTaskCount--;
else
TaskInterface::WriteLog(pTask->GetPlayerId(), m_ID, 0, "Award, TaskCount == 0");
if (pEntry->m_ParentIndex != 0xff)
{
ActiveTaskEntry& ParentEntry = aEntries[pEntry->m_ParentIndex];
if (pEntry->m_PrevSblIndex != 0xff)
aEntries[pEntry->m_PrevSblIndex].m_NextSblIndex = pEntry->m_NextSblIndex;
else
ParentEntry.m_ChildIndex = pEntry->m_NextSblIndex;
if (pEntry->m_NextSblIndex != 0xff)
aEntries[pEntry->m_NextSblIndex].m_PrevSblIndex = pEntry->m_PrevSblIndex;
if (!pEntry->IsSuccess() && m_bParentAlsoFail)
{
pList->RealignTask(pEntry, 0);
ParentEntry.ClearSuccess();
ParentEntry.SetFinished();
m_pParent->RecursiveAward(pTask, pList, &ParentEntry, ulCurtime, -1, pSubTag);
}
else if (pEntry->IsSuccess() && m_bParentAlsoSucc)
{
pList->RealignTask(pEntry, 0);
ParentEntry.SetFinished();
pList->ClearChildrenOf(pTask, &ParentEntry);
if (m_pParent->m_enumFinishType == enumTFTDirect)
m_pParent->RecursiveAward(pTask, pList, &ParentEntry, ulCurtime, -1, pSubTag);
#ifdef _TASK_CLIENT
else if (!m_pParent->m_bHidden && !m_pParent->m_bDisplayInTitleTaskUI)
TaskInterface::TraceTask(m_pParent->m_ID);
#endif
}
else if (m_pParent->m_bExeChildInOrder && m_pNextSibling)
{
if (ParentEntry.m_ChildIndex != 0xff || pList->GetEntry(m_pNextSibling->m_ID)) // Ϊ0xff
pList->RealignTask(pEntry, 0);
else
{
m_pNextSibling->DeliverTask(
pTask,
pList,
pEntry,
0,
*pTask->GetTaskMask(),
ulCurtime,
NULL,
pSubTag,
NULL,
pEntry->m_ParentIndex);
#ifdef _TASK_CLIENT
// ѡһһ˳ִ
// ǰ׷ٸʱѾ
// ڵڶԺ˳ִе
if (!m_pParent->m_bHidden && !m_pParent->m_bDisplayInTitleTaskUI)
TaskInterface::TraceTask(m_pNextSibling->m_ID);
#endif
}
}
else if (ParentEntry.m_ChildIndex == 0xff) // ʱΪ
{
pList->RealignTask(pEntry, 0);
ParentEntry.SetFinished();
if (m_pParent->m_enumFinishType == enumTFTDirect)
m_pParent->RecursiveAward(pTask, pList, &ParentEntry, ulCurtime, -1, pSubTag);
#ifdef _TASK_CLIENT
else if (!m_pParent->m_bHidden && !m_pParent->m_bDisplayInTitleTaskUI)
TaskInterface::TraceTask(m_pParent->m_ID);
#endif
}
else
pList->RealignTask(pEntry, 0);
}
else // Root Node
{
pList->RealignTask(pEntry, 0);
if (pList->m_uUsedCount >= m_uDepth)
pList->m_uUsedCount -= m_uDepth;
else
{
char log[1024];
sprintf(log, "Award, Used = %d", pList->m_uUsedCount);
TaskInterface::WriteLog(pTask->GetPlayerId(), m_ID, 0, log);
pList->m_uUsedCount = 0;
}
if (m_bHidden)
{
if (pList->m_uTopHideTaskCount)
pList->m_uTopHideTaskCount--;
}
else if(m_bDisplayInTitleTaskUI)
{
if (pList->m_uTitleTaskCount)
pList->m_uTitleTaskCount--;
}
else
{
if (pList->m_uTopShowTaskCount)
pList->m_uTopShowTaskCount--;
}
}*/
}
public void TakeAwayGivenItems(TaskInterface pTask)
{
uint ulCount;
for (int i = 0; i < m_FixedData.m_ulGivenItems; i++)
{
ITEM_WANTED wi = m_FixedData.m_GivenItems[i];
if (wi.m_bCommonItem)
{
ulCount = (uint)pTask.GetCommonItemCount(wi.m_ulItemTemplId);
if (ulCount > wi.m_ulItemNum) ulCount = wi.m_ulItemNum;
if (ulCount > 0) pTask.TakeAwayCommonItem(wi.m_ulItemTemplId, ulCount);
}
else
{
ulCount = (uint)pTask.GetTaskItemCount(wi.m_ulItemTemplId);
if (ulCount > 0) pTask.TakeAwayTaskItem(wi.m_ulItemTemplId, ulCount);
}
}
}
public void RemoveAcquiredItem(TaskInterface pTask, bool bClearTask, bool bSuccess)
{
var m_enumMethod = m_FixedData.m_enumMethod;
var m_ulItemsWanted = m_FixedData.m_ulItemsWanted;
var m_ItemsWanted = m_FixedData.m_ItemsWanted;
var m_ulGoldWanted = m_FixedData.m_ulGoldWanted;
var m_iFactionContribWanted = m_FixedData.m_iFactionContribWanted;
var m_iFactionExpContribWanted = m_FixedData.m_iFactionExpContribWanted;
var m_ulMonsterWanted = m_FixedData.m_ulMonsterWanted;
var m_MonsterWanted = m_FixedData.m_MonsterWanted;
var m_ulPlayerWanted = m_FixedData.m_ulPlayerWanted;
var m_PlayerWanted = m_FixedData.m_PlayerWanted;
if (m_enumMethod == (uint)TaskCompletionMethod.enumTMCollectNumArticle)
{
for (int i = 0; i < m_ulItemsWanted; i++)
{
ITEM_WANTED wi = m_ItemsWanted[i];
uint ulCount;
if (wi.m_bCommonItem)
{
if (bClearTask) continue;
ulCount = (uint)pTask.GetCommonItemCount(wi.m_ulItemTemplId);
if (ulCount == 0) continue;
if (wi.m_ulItemNum > 0 && ulCount > wi.m_ulItemNum) ulCount = wi.m_ulItemNum;
pTask.TakeAwayCommonItem(wi.m_ulItemTemplId, ulCount);
}
else
{
ulCount = (uint)pTask.GetTaskItemCount(wi.m_ulItemTemplId);
if (ulCount > 0) pTask.TakeAwayTaskItem(wi.m_ulItemTemplId, ulCount);
}
}
// ɹǮ
if (m_ulGoldWanted > 0 && !bClearTask && bSuccess)
{
uint ulGold = pTask.GetGoldNum();
if (ulGold > m_ulGoldWanted) ulGold = m_ulGoldWanted;
pTask.TakeAwayGold(ulGold);
}
//ɹѰɹ׶
if (m_iFactionContribWanted > 0 && !bClearTask && bSuccess)
{
int iContrib = pTask.GetFactionConsumeContrib();
if (iContrib > m_iFactionContribWanted) iContrib = m_iFactionContribWanted;
pTask.TakeAwayFactionConsumeContrib(iContrib);
}
//ɹѰɾ
if (m_iFactionExpContribWanted > 0 && !bClearTask && bSuccess)
{
int iContrib = pTask.GetFactionExpContrib();
if (iContrib > m_iFactionExpContribWanted) iContrib = m_iFactionExpContribWanted;
pTask.TakeAwayFactionExpContrib(iContrib);
}
}
else if (m_enumMethod == (uint)TaskCompletionMethod.enumTMKillNumMonster)
{
for (int i = 0; i < m_ulMonsterWanted; i++)
{
// const MONSTER_WANTED& mw = m_MonsterWanted[i];
MONSTER_WANTED mw = m_MonsterWanted[i];
if (mw.m_ulDropItemId == 0) continue;
uint ulCount;
if (mw.m_bDropCmnItem)
{
ulCount = (uint)pTask.GetCommonItemCount(mw.m_ulDropItemId);
if (mw.m_ulDropItemCount > 0 && ulCount > mw.m_ulDropItemCount) ulCount = mw.m_ulDropItemCount;
if (ulCount > 0) pTask.TakeAwayCommonItem(mw.m_ulDropItemId, ulCount);
}
else
{
ulCount = (uint)pTask.GetTaskItemCount(mw.m_ulDropItemId);
if (ulCount > 0) pTask.TakeAwayTaskItem(mw.m_ulDropItemId, ulCount);
}
}
}
else if (m_enumMethod == (uint)TaskCompletionMethod.enumTMKillPlayer)
{
for (uint i = 0; i < m_ulPlayerWanted; ++i)
{
// const PLAYER_WANTED& pw = m_PlayerWanted[i];
var pw = m_PlayerWanted[i];
if (pw.m_ulDropItemId == 0) continue;
uint ulCount;
if (pw.m_bDropCmnItem)
{
ulCount = (uint)pTask.GetCommonItemCount(pw.m_ulDropItemId);
if (pw.m_ulDropItemCount > 0 && ulCount > pw.m_ulDropItemCount) ulCount = pw.m_ulDropItemCount;
if (ulCount > 0) pTask.TakeAwayCommonItem(pw.m_ulDropItemId, ulCount);
}
else
{
ulCount = (uint)pTask.GetTaskItemCount(pw.m_ulDropItemId);
if (ulCount>0) pTask.TakeAwayTaskItem(pw.m_ulDropItemId, ulCount);
}
}
}
}
public bool IsValidState() { return m_uValidCount < TaskTemplConstants.TASK_MAX_VALID_COUNT; }
public static bool _compare_pq_key_value( COMPARE_KEY_VALUE CompKeyVal)
{
long lleftValue = CompKeyVal.lLeftNum;
if (CompKeyVal.nLeftType == 0)
{
lleftValue = PublicQuestInterface.QuestGetGlobalValue(CompKeyVal.lLeftNum);
// pTask->GetGlobalValue(CompKeyVal.lLeftNum);
}
long lRightValue = CompKeyVal.lRightNum;
if (CompKeyVal.nRightType == 0)
{
lRightValue = PublicQuestInterface.QuestGetGlobalValue(CompKeyVal.lRightNum);
// 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;
}
public uint CheckGlobalPQKeyValue(bool bFinCheck)
{
var m_bFinNeedComp = m_FixedData.m_bFinNeedComp;
var m_bPremNeedComp = m_FixedData.m_bPremNeedComp;
var m_Fin1KeyValue = m_FixedData.m_Fin1KeyValue;
var m_Fin2KeyValue = m_FixedData.m_Fin2KeyValue;
var m_nFinExp1AndOrExp2 = m_FixedData.m_nFinExp1AndOrExp2;
var m_nPremExp1AndOrExp2 = m_FixedData.m_nPremExp1AndOrExp2;
var m_Prem1KeyValue = m_FixedData.m_Prem1KeyValue;
var m_Prem2KeyValue = m_FixedData.m_Prem2KeyValue;
if (bFinCheck && !m_bFinNeedComp
||!bFinCheck && !m_bPremNeedComp)
return 0;
bool bFlag1 = false;
bool bFlag2 = false;
if (bFinCheck)
{
bFlag1 = _compare_pq_key_value(m_Fin1KeyValue);
bFlag2 = _compare_pq_key_value(m_Fin2KeyValue);
if (m_nFinExp1AndOrExp2 == 0 && (bFlag1 || bFlag2) //
|| m_nFinExp1AndOrExp2 == 1 && (bFlag1 && bFlag2)) //
return 0;
}
else
{
bFlag1 = _compare_pq_key_value(m_Prem1KeyValue);
bFlag2 = _compare_pq_key_value(m_Prem2KeyValue);
if (m_nPremExp1AndOrExp2 == 0 && (bFlag1 || bFlag2) //
|| m_nPremExp1AndOrExp2 == 1 && (bFlag1 && bFlag2)) //
return 0;
}
return TaskInterfaceConstants.TASK_PREREQU_FAIL_GLOBAL_KEYVAL;
}
public void OnSetFinished(
TaskInterface pTask,
ActiveTaskList pList,
ActiveTaskEntry pEntry,
bool bNotifyMem = true)
{
var m_enumFinishType = m_FixedData.m_enumMethod;
pEntry.SetFinished();
// ֪ͨͻ
NotifyClient(
pTask,
pEntry,
TaskTemplConstants.TASK_SVR_NOTIFY_FINISHED,
0);
if(pEntry.GetTempl().m_FixedData.m_bPQTask)
PublicQuestInterface.QuestRemovePlayer((int)pEntry.GetTempl().m_FixedData.m_ID, pTask.GetPlayerId());
if (m_enumFinishType == (uint)TaskFinishType.enumTFTDirect ||
!pEntry.IsSuccess())
DeliverAward(pTask, pList, pEntry, -1, bNotifyMem);
}
public void GiveUpOneTask(
TaskInterface pTask,
ActiveTaskList pList,
ActiveTaskEntry pEntry,
bool bForce)
{
var m_bCanGiveUp = m_FixedData.m_bCanGiveUp;
if (m_pParent != null || !m_bCanGiveUp) return;
pEntry.ClearSuccess();
pEntry.SetGiveUp();
OnSetFinished(pTask, pList, pEntry);
// TaskInterface::WriteLog(pTask.GetPlayerId(), m_ID, 1, "GiveUpTask");
// TaskInterface::WriteKeyLog(pTask.GetPlayerId(), m_ID, 1, "GiveUpTask");
}
private void NotifyClient(
TaskInterface pTask,
ActiveTaskEntry pEntry,
byte uReason,
uint ulCurTime,
uint ulParam=0,
int dps=0,
int dph=0)
{
var m_ID = m_FixedData.m_ID;
var m_MonsterWanted = m_FixedData.m_MonsterWanted;
string log = new string(new char[1024]);
byte[] buf = new byte[512];
// task_notify_base* pNotify = reinterpret_cast<task_notify_base*>(buf);
var pNotify = new task_notify_base();
int sz = 0;
pNotify.reason = uReason;
pNotify.task = (ushort)(m_ID);
bool bWriteLog = true;
switch (uReason)
{
case TaskTemplConstants.TASK_SVR_NOTIFY_PLAYER_KILLED:
var svr_player_killed = new svr_player_killed(pNotify);
svr_player_killed.player_num = pEntry.m_wMonsterNum[ulParam];
svr_player_killed.index = (ushort)ulParam;
sz = Marshal.SizeOf(svr_player_killed);
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_MONSTER_KILLED:
{
var svrMonsterKilled = new svr_monster_killed(pNotify)
{
monster_id = m_MonsterWanted[ulParam].m_ulMonsterTemplId,
monster_num = pEntry.m_wMonsterNum[ulParam],
dps = (dps != 0 && dph != 0) ? dps : 0,
dph = (dps != 0 && dph != 0) ? dph : 0
};
sz = Marshal.SizeOf(svrMonsterKilled);
bWriteLog = false;
}
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_NEW:
{
// static_cast<svr_new_task*>(pNotify)->set_data(
// ulCurTime,
// reinterpret_cast<unsigned long>(pEntry),
// *(reinterpret_cast<const task_sub_tags*>(ulParam))
// );
var svrNewTask = new svr_new_task(pNotify);
svrNewTask.set_data(
ulCurTime,
pEntry.m_ID,
Marshal.PtrToStructure<task_sub_tags>((IntPtr)ulParam)
);
sz = svrNewTask.get_size();
break;
}
case TaskTemplConstants.TASK_SVR_NOTIFY_COMPLETE:
// static_cast<svr_task_complete*>(pNotify)->set_data(
// ulCurTime,
// *(reinterpret_cast<const task_sub_tags*>(ulParam))
// );
// sz = static_cast<svr_task_complete*>(pNotify)->get_size();
var svrTaskComplete = new svr_task_complete(pNotify);
svrTaskComplete.set_data(
ulCurTime,
Marshal.PtrToStructure<task_sub_tags>((IntPtr)ulParam)
);
sz = svrTaskComplete.get_size();
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_GIVE_UP:
case TaskTemplConstants.TASK_SVR_NOTIFY_FINISHED:
case TaskTemplConstants.TASK_SVR_NOTIFY_DIS_GLOBAL_VAL:
sz = Marshal.SizeOf<task_notify_base>();
break;
case TaskTemplConstants.TASK_SVR_NOTIFY_ERROR_CODE:
var svrTaskErrCode = new svr_task_err_code(pNotify);
svrTaskErrCode.err_code = ulParam;
sz = Marshal.SizeOf( svrTaskErrCode );
break;
default:
// sprintf(log, "NotifyClient, Unknown Reason = %d", uReason);
// TaskInterface::WriteLog(pTask->GetPlayerId(), m_ID, 0, log);
return;
}
if (bWriteLog)
{
// sprintf(log, "svr: Reason = %d, Param = 0x%x", uReason, ulParam);
// TaskInterface::WriteLog(pTask->GetPlayerId(), m_ID, 1, log);
}
// assert(sz <= sizeof(buf));
pTask.NotifyClient(buf, sz);
}
public bool DeliverAward(
TaskInterface pTask,
ActiveTaskList pList,
ActiveTaskEntry pEntry,
int nChoice,
bool bNotifyTeamMem = true, // = true
Nullable<TaskGlobalData> pGlobal = null ) // = null
{
char[] log = new char[1024];
// sprintf(log, "DeliverAward: Choice = %d", nChoice);
// TaskInterface::WriteLog(pTask->GetPlayerId(), m_ID, 1, log);
// TaskInterface::WriteKeyLog(pTask->GetPlayerId(), m_ID, 1, log);
// ʱ
uint ulCurTime = pTask.GetCurTime();
RecursiveCheckTimeLimit(pTask, pList, pEntry, ulCurTime);
// TODO : implement full logic when ActiveTaskList/ActiveTaskEntry and TaskInterface APIs are available
// if (!RecursiveCheckParent(pTask, pList, pEntry))
// pEntry->ClearSuccess();
//
// // ʧ
// if (!pEntry->IsAwardNotifyTeam() && bNotifyTeamMem && pEntry->GetCapOrSelf()->m_bTeamwork && !pEntry->IsSuccess())
// {
// AwardNotifyTeamMem(pTask, pEntry);
// pEntry->SetAwardNotifyTeam(); // Nofity only once
// }
//
// if (!pTask->IsDeliverLegal()) // ׵״̬
// return false;
//
// if (pEntry->IsGiveUp() && m_bClearAsGiveUp)
// {
// pList->ClearTask(pTask, pEntry, true);
// pList->UpdateTaskMask(*pTask->GetTaskMask());
// NotifyClient(pTask, NULL, TASK_SVR_NOTIFY_GIVE_UP, 0);
//
// // Ѱ
// if (m_bCompareItemAndInventory)
// {
// pTask->LockInventory(false);
// }
//
// return true;
// }
//
// pEntry->SetFinished();
//
// #if _TASK_CLIENT
//
// unsigned long ulRet;
// if ((ulRet = RecursiveCheckAward(
// pTask,
// pList,
// pEntry,
// ulCurTime,
// nChoice
// )) != 0)
// {
// if (m_enumFinishType == enumTFTNPC || !pEntry->IsErrReported())
// {
// NotifyClient(
// pTask,
// NULL,
// TASK_SVR_NOTIFY_ERROR_CODE,
// 0,
// ulRet
// );
//
// pEntry->SetErrReported();
// }
//
// char log[1024];
// sprintf(log, "DeliverAward: ret = %d", ulRet);
// TaskInterface::WriteLog(pTask->GetPlayerId(), m_ID, 1, log);
// return false;
// }
//
// #endif
//
// // ӳɹ
// if (!pEntry->IsAwardNotifyTeam() && bNotifyTeamMem && pEntry->IsSuccess())
// {
// if(pEntry->GetCapOrSelf()->m_bTeamwork)
// {
// AwardNotifyTeamMem(pTask, pEntry);
// pEntry->SetAwardNotifyTeam(); // Nofity only once
// }
// else
// {
// const ATaskTempl* pParent = pEntry->GetTempl()->GetTopTask();
// ActiveTaskEntry* pParentEntry = static_cast<ActiveTaskList*>(pTask->GetActiveTaskList())->GetEntry(pParent->GetID());
//
// if(pParentEntry->GetCapOrSelf()->m_bTeamwork && pEntry->m_ChildIndex == 0xff)
// {
// bool bIsLastChild = true;
// const ATaskTempl* pTempParent = pEntry->GetTempl();
// while(pTempParent)// && pTempParent->m_pNextSibling == NULL)
// {
// if(pTempParent->m_pNextSibling != NULL)
// {
// bIsLastChild = false;
// break;
// }
//
// pTempParent = pTempParent->m_pParent;
// }
//
// if(bIsLastChild)
// {
// AwardNotifyTeamMem(pTask, pParentEntry);
// pParentEntry->SetAwardNotifyTeam(); // Nofity only once
// }
// }
// }
// }
//
// task_sub_tags sub_tags;
// memset(&sub_tags, 0, sizeof(sub_tags));
// sub_tags.state = pEntry->m_uState;
//
// //
// RecursiveAward(pTask, pList, pEntry, ulCurTime, nChoice, &sub_tags);
//
// // ֪ͨͻ
// NotifyClient(
// pTask,
// NULL,
// TASK_SVR_NOTIFY_COMPLETE,
// ulCurTime,
// reinterpret_cast<unsigned long>(&sub_tags));
//
// // Mask
// pList->UpdateTaskMask(*pTask->GetTaskMask());
//
// // Ѱ
// if (m_bCompareItemAndInventory)
// {
// pTask->LockInventory(false);
// }
return true;
}
private void RecursiveCheckTimeLimit(
TaskInterface pTask,
ActiveTaskList pList,
ActiveTaskEntry pEntry,
uint ulCurTime)
{
// TODO: implement full logic when ActiveTaskList/ActiveTaskEntry and TaskInterface APIs are available
// if (m_ulTimeLimit > 0 && pEntry.m_ulTaskTime + m_ulTimeLimit < ulCurTime) // ʱ
// pEntry.ClearSuccess();
//
// // if (m_ulAbsFailTime && m_ulAbsFailTime < ulCurTime) // ʧЧ
// // ʧЧ
// if (m_bAbsFail)
// {
// tm cur = *localtime((long*)&ulCurTime);
//
// if(m_tmAbsFailTime.before(&cur))
// {
// pEntry->ClearSuccess();
// }
// }
//
// if (m_pParent && pEntry->m_ParentIndex != 0xff)
// {
// ActiveTaskEntry& ParentEntry = pList->m_TaskEntries[pEntry->m_ParentIndex];
// m_pParent->RecursiveCheckTimeLimit(pTask, pList, &ParentEntry, ulCurTime);
// }
}
}
}