Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

Perfect World (World2) Data Editor

Joined
Jul 26, 2011
Messages
2,030
Reaction score
396
@ 雷希德 Can you share the data structure of aipolicy.data

if you know how to use this, great, if not, perhaps someone will
#ifndef _TASKSERVER_H_
#define _TASKSERVER_H_

#include "TaskInterface.h"

#ifndef _TASK_CLIENT

class elementdataman;

// 加载任务文件
bool LoadTasksFromPack(elementdataman* pDataMan, const char* szPackPath, const char* szDynPackPath);

// 释放任务文件
void ReleaseTaskTemplMan();

// 通知队长建立
void OnTeamSetup(TaskInterface* pTask);

// 通知队长解散
void OnTeamDisband(TaskInterface* pTask);

// 通知队长加入成员
void OnTeamAddMember(TaskInterface* pTask, const task_team_member_info* pInfo);

// 通知队长成员退出
void OnTeamDismissMember(TaskInterface* pTask, unsigned long ulPlayerId);

// 通知队员退出
void OnTeamMemberLeave(TaskInterface* pTask);

// 接收其他玩家通知
void OnPlayerNotify(TaskInterface* pTask, unsigned long ulPlayerId, const void* pBuf, size_t sz);

// 接收客户端通知
void OnClientNotify(TaskInterface* pTask, const void* pBuf, size_t sz);

// 检查任务能否发放
bool OnTaskCheckDeliver(TaskInterface* pTask, unsigned long ulTaskId);

// NPC发放任务物品
void OnNPCDeliverTaskItem(TaskInterface* pTask, unsigned long ulNPCId, unsigned long ulTaskId);

// 检查在NPC处完成的任务
void OnTaskCheckAward(TaskInterface* pTask, unsigned long ulTasklId, int nChoice);

// 玩家被杀
void OnTaskPlayerKilled(TaskInterface* pTask);

// 定时检查整个任务系统限时且有接收者上限任务的状态
void OnTaskCheckAllTimeLimits(unsigned long ulCurTime);

// 单人杀怪
void OnTaskKillMonster(TaskInterface* pTask, unsigned long ulTemplId, unsigned long ulLev, float fRand);

// 组队杀怪
void OnTaskTeamKillMonster(TaskInterface* pTask, unsigned long ulTemplId, unsigned long ulLev, float fRand);

// 挖任务矿
void OnTaskMining(TaskInterface* pTask, unsigned long ulTaskId);

// 请求任务全局数据
void TaskQueryGlobalData(
unsigned long ulTaskId,
unsigned long ulPlayerId,
const void* pPreservedData,
size_t size);

// 更新任务全局数据
void TaskUpdateGlobalData(
unsigned long ulTaskId,
const unsigned char pData[TASK_GLOBAL_DATA_SIZE]);

// 获得全局数据
void OnTaskReceivedGlobalData(
TaskInterface* pTask,
unsigned long ulTaskId,
unsigned char pData[TASK_GLOBAL_DATA_SIZE],
const void* pPreservedData,
size_t size);

// 遗忘生活技能
void OnForgetLivingSkill(TaskInterface* pTask);

// 玩家升级
void OnTaskPlayerLevelUp(TaskInterface* pTask);

// PQ任务初始化
bool InitPublicQuestSystem();

// PQ任务的heartbeat
void OnTaskPublicQuestHeartbeat();

// PQ任务杀怪贡献度分配
void OnTaskKillPQMonster(TaskInterface* pTask, unsigned long ulTemplId, bool bOwner,float fTeamContrib,int iTeamMemberCnt,float fPersonalContib);

// PQ任务初始化link信息
void OnTaskCheckPQEnterWorldInit(TaskInterface* pTask, unsigned long ulTaskId);

enum{
EX_TK_SENDAUMAIL_LEVEL1 = 1,
EX_TK_SENDAUMAIL_LEVEL2 = 2,
EX_TK_SENDAUMAIL_LEVEL3 = 3,
EX_TK_SENDAUMAIL_EXAWARD = 4,
EX_TK_LOGIN_REWARD = 5,
EX_TK_MOSTKILL_BONUS = 6,
EX_TK_MOSTDEATH_BONUS = 7,
EX_TK_MOSTPROFIT_BONUS = 8,
EX_TK_15DAYS_SECONDS = 15 * 24 * 3600,
};
//
void OnTaskExternEvent(TaskInterface* pTask, int Event);

// 某些奖励由任务发放,比如账号补填
void OnTaskSpecialAwardMask(TaskInterface* pTask,unsigned long ulTaskID);

// 称号任务
void OnTaskTitle(TaskInterface* pTask, unsigned long ulTaskID);

#endif

#endif

#include "TaskServer.h"
#include "TaskTempl.h"

#ifdef LINUX
#include "../template/elementdataman.h"
#else
#include "elementdataman.h"
#endif

#include "TaskTemplMan.h"

#ifndef _TASK_CLIENT

// 加载任务文件
bool LoadTasksFromPack(elementdataman* pDataMan, const char* szPackPath, const char* szDynPackPath)
{
GetTaskTemplMan()->Init(pDataMan);
bool b = GetTaskTemplMan()->LoadTasksFromPack(szPackPath, true);
if (!b) return false;
return GetTaskTemplMan()->LoadDynTasksFromPack(szDynPackPath);
}

// 释放任务文件
void ReleaseTaskTemplMan()
{
GetTaskTemplMan()->Release();
}

/*
* 其它队员任务失败导致全队失败
*/
inline void OnTaskForceFail(TaskInterface* pTask, unsigned long ulTaskId, bool bNotifyMem)
{
TaskInterface::WriteLog(pTask->GetPlayerId(), ulTaskId, 1, "TeamForceFail");

ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
ActiveTaskEntry* pEntries = pLst->m_TaskEntries;
unsigned char i;

for (i = 0; i < pLst->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = pEntries;

if (CurEntry.m_ID == ulTaskId || CurEntry.m_uCapTaskId == ulTaskId)
{
CurEntry.ClearSuccess();
CurEntry.GetTempl()->OnSetFinished(pTask, pLst, &CurEntry, bNotifyMem);
return;
}
}
}

inline void OnTaskForceSucc(TaskInterface* pTask, unsigned long ulTaskId)
{
TaskInterface::WriteLog(pTask->GetPlayerId(), ulTaskId, 1, "TeamForceSucc");

ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
ActiveTaskEntry* pEntries = pLst->m_TaskEntries;
unsigned char i;

for (i = 0; i < pLst->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = pEntries;

if (CurEntry.m_ID == ulTaskId || CurEntry.m_uCapTaskId == ulTaskId)
{
CurEntry.GetTempl()->OnSetFinished(pTask, pLst, &CurEntry, false);
return;
}
}
}

// 队伍建立
void OnTeamSetup(TaskInterface* pTask)
{
const int nMemNum = pTask->GetTeamMemberNum();
task_team_member_info mi;
int i;
float pos[3];
unsigned long ulWorldId = pTask->GetPos(pos);

for (i = 1; i < nMemNum; i++)
{
pTask->GetTeamMemberInfo(i, &mi);
if (mi.m_ulWorldId != ulWorldId) continue;
OnTeamAddMember(pTask, &mi);
}
}

/*
* 处理队长、队员退出
*/

bool _teammember_leave(TaskInterface* pTask)
{
ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
ActiveTaskEntry* pEntries = pLst->m_TaskEntries;
unsigned char i;

for (i = 0; i < pLst->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = pEntries;

if (!CurEntry.IsSuccess())
continue;

const ATaskTempl* pCapTempl = CurEntry.GetCapOrSelf();
const ATaskTempl* pTempl = CurEntry.GetTempl();

if (!pCapTempl || !pCapTempl->m_bTeamwork)
continue;

if (pCapTempl->m_bDismAsSelfFail)
{
CurEntry.ClearSuccess();
CurEntry.GetTempl()->OnSetFinished(pTask, pLst, &CurEntry);
return true;
}

if (pTempl && pTempl->m_bMarriage)
{
CurEntry.ClearSuccess();
pTempl->OnSetFinished(pTask, pLst, &CurEntry);
return true;
}
}

return false;
}

void OnTeamMemberLeave(TaskInterface* pTask)
{
while (_teammember_leave(pTask)) {}
}

void OnTeamDisband(TaskInterface* pTask)
{
OnTeamMemberLeave(pTask);
}

void OnTeamAddMember(TaskInterface* pTask, const task_team_member_info* pInfo)
{
ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
ActiveTaskEntry* pEntries = pLst->m_TaskEntries;
const ATaskTempl* pTempl;
unsigned long ulTask;
unsigned char i;

for (i = 0; i < pLst->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = pEntries;
pTempl = CurEntry.GetTempl();
if (!pTempl) continue;

if (pTempl->m_bTeamwork && pTempl->m_bSharedTask)
{
ulTask = pTempl->GetMemTaskByInfo(pInfo);
if (!ulTask) continue;

TaskNotifyPlayer(
pTask,
pInfo->m_ulId,
pTempl->m_ID,
TASK_PLY_NOTIFY_NEW_MEM_TASK);
}
}
}

void OnTeamDismissMember(TaskInterface* pTask, unsigned long ulPlayerId)
{
ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
ActiveTaskEntry* pEntries = pLst->m_TaskEntries;
const ATaskTempl* pCap;
int i,j;
const int nMemNum = pTask->GetTeamMemberNum();

for (i = 0; i < (int)pLst->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = pEntries;
pCap = CurEntry.GetCapOrSelf();

if (!pCap || !pCap->m_bTeamwork) continue;

if (pCap->HasAllTeamMemsWanted(pTask, false) != 0)
{
OnTaskForceFail(pTask, pCap->m_ID, false); // 自身失败

for (j = 1; j < nMemNum; j++) // 跳过队长
{
unsigned long ulId = pTask->GetTeamMemberId(j);
if (ulId == ulPlayerId) continue;

TaskNotifyPlayer(
pTask,
ulId,
pCap->m_ID,
TASK_PLY_NOTIFY_FORCE_FAIL);
}
// 若遍历已接任务列表的途中完成并清空了某个任务,则需要重新遍历列表
bool bCleared = true;
for (j = 0; j < (int)pLst->m_uTaskCount; j++)
{
ActiveTaskEntry& CurEntry = pEntries[j];

if (CurEntry.m_ID == pCap->m_ID || CurEntry.m_uCapTaskId == pCap->m_ID)
{
bCleared = false;
break;
}
}
if (bCleared) i = -1;
}
}
}

void OnTaskCheckAwardDirect(TaskInterface* pTask, unsigned long ulTaskId);
void OnTaskGiveUpOneTask(TaskInterface* pTask, unsigned long ulTaskId, bool bForce);
void OnTaskAutoDelv(TaskInterface* pTask, unsigned long ulTaskId);
void OnTaskReachSite(TaskInterface* pTask,unsigned long ulTaskId);
void OnTaskProtectNPC(TaskInterface* pTask, unsigned long ulTaskId, TaskGlobalData* pGlobal);
void OnTaskManualTrig(TaskInterface* pTask,unsigned long ulTaskId);
void OnTaskCheckTreasure(TaskInterface* pTask,unsigned long ulTaskId);
void OnTaskRequestTreasureIndex(TaskInterface* pTask,unsigned long ulTaskId);
void OnTaskChooseSubTask(TaskInterface* pTask, unsigned long ulTaskId);

void OnPlayerNotify(TaskInterface* pTask, unsigned long ulPlayerId, const void* pBuf, size_t sz)
{
if (sz != sizeof(task_player_notify)) return;
const task_player_notify* pNotify = static_cast<const task_player_notify*>(pBuf);
const ATaskTempl* pTempl;

char log[1024];
sprintf(log, "PlayerNotify: Sender = %d, Reason = %d", ulPlayerId, pNotify->reason);
TaskInterface::WriteLog(pTask->GetPlayerId(), 0, 1, log);

switch (pNotify->reason)
{
case TASK_PLY_NOTIFY_NEW_MEM_TASK:
if (!pTask->IsInTeam()) break;
pTempl = GetTaskTemplMan()->GetTopTaskByID(pNotify->task);
if (!pTempl) break;
if (pNotify->param
|| pTempl->CheckGlobalRequired(
pTask,
0,
NULL,
NULL,
TASK_GLOBAL_CHECK_ADD_MEM))
{
if (!pTempl->OnDeliverTeamMemTask(pTask, NULL)
&& pNotify->param)
{
// 通知队长失败
TaskNotifyPlayer(
pTask,
pTask->GetTeamMemberId(0),
pTempl->m_ID,
TASK_PLY_NOTIFY_FORCE_FAIL,
pNotify->param
);
}
}
break;
case TASK_PLY_NOTIFY_FORCE_FAIL:
OnTaskForceFail(pTask, pNotify->task, pNotify->param != 0);
break;
case TASK_PLY_NOTIFY_FORCE_SUCC:
OnTaskForceSucc(pTask, pNotify->task);
break;
default:
sprintf(log, "Player Notify, Sender = %d, Reason = %d", ulPlayerId, pNotify->reason);
TaskInterface::WriteLog(pTask->GetPlayerId(), 0, 0, log);
}
}

void OnClientNotify(TaskInterface* pTask, const void* pBuf, size_t sz)
{
if (sz != sizeof(task_notify_base)) return;
const task_notify_base* pNotify = static_cast<const task_notify_base*>(pBuf);

char log[1024];
sprintf(log, "Clt: Reason = %d", pNotify->reason);
TaskInterface::WriteLog(pTask->GetPlayerId(), pNotify->task, 1, log);

switch (pNotify->reason)
{
case TASK_CLT_NOTIFY_CHECK_FINISH:
OnTaskCheckAwardDirect(pTask, pNotify->task);
break;
case TASK_CLT_NOTIFY_CHECK_GIVEUP:
OnTaskGiveUpOneTask(pTask, pNotify->task, false);
break;
case TASK_CLT_NOTIFY_AUTO_DELV:
OnTaskAutoDelv(pTask, pNotify->task);
break;
case TASK_CLT_NOTIFY_REACH_SITE:
OnTaskReachSite(pTask, pNotify->task);
break;
case TASK_CLT_NOTIFY_DYN_TIMEMARK:
GetTaskTemplMan()->OnTaskGetDynTasksTimeMark(pTask);
break;
case TASK_CLT_NOTIFY_SPECIAL_AWARD:
GetTaskTemplMan()->OnTaskGetSpecialAward(pTask);
break;
case TASK_CLT_NOTIFY_DYN_DATA:
GetTaskTemplMan()->OnTaskGetDynTasksData(pTask);
break;
case TASK_CLT_NOTIFY_PQ_CHECK_INIT:
OnTaskCheckPQEnterWorldInit(pTask, pNotify->task);
break;
case TASK_CLT_NOTIFY_15DAYS_NOLOGIN:
OnTaskExternEvent(pTask,EX_TK_LOGIN_REWARD);
break;
case TASK_CLT_NOTIFY_SPECIAL_AWARD_MASK:
OnTaskSpecialAwardMask(pTask,pNotify->task);
break;
case TASK_CLT_NOTIFY_REQUEST_TREASURE_INDEX:
OnTaskRequestTreasureIndex(pTask,pNotify->task);
break;
case TASK_CLT_NOTIFY_TREASURE:
OnTaskCheckTreasure(pTask,pNotify->task);
break;
case TASK_CLT_NOTIFY_TITLE_TASK:
OnTaskTitle(pTask, pNotify->task);
break;
}
}

void OnTaskProtectNPC(TaskInterface* pTask, unsigned long ulTaskId, TaskGlobalData* pGlobal)
{
/*
ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
ActiveTaskEntry* pEntry = pLst->GetEntry(ulTaskId);
if (!pEntry || !pEntry->m_ulTemplAddr || pEntry->IsFinished()) return;

if (!pGlobal)
{
TaskPreservedData tpd;
tpd.m_ulSrcTask = ulTaskId;
tpd.reason = TASK_GLOBAL_PROTECT_NPC;

TaskQueryGlobalData(
ulTaskId,
pTask->GetPlayerId(),
&tpd,
sizeof(TaskPreservedData)
);

return;
}

const ATaskTempl* pTempl = pEntry->GetTempl();
if (pTempl->m_enumMethod != enumTMProtectNPC) return;

unsigned long ulCurTime = TaskInterface::GetCurTime();
unsigned long ulLimit = pEntry->m_ulTaskTime + pTempl->m_ulProtectTimeLen;

// NPC是否在任务期间被杀
if (pGlobal->m_ulKillTime >= pEntry->m_ulTaskTime
&& pGlobal->m_ulKillTime <= ulLimit)
{
pEntry->ClearSuccess();
pTempl->OnSetFinished(
pTask,
pLst,
pEntry);
}
else if (ulCurTime > ulLimit) // 成功
{
pTempl->OnSetFinished(
pTask,
pLst,
pEntry);
}
*/
}

void OnTaskAutoDelv(TaskInterface* pTask, unsigned long ulTaskId)
{
const ATaskTempl* pTempl = GetTaskTemplMan()->GetTopTaskByID(ulTaskId);
if (!pTempl || !pTempl->m_bAutoDeliver) return;

if (pTempl->CheckGlobalRequired(
pTask,
0,
NULL,
NULL,
TASK_GLOBAL_CHECK_RCV_NUM))
pTempl->CheckDeliverTask(pTask, 0, NULL);
}

void OnTaskReachSite(TaskInterface* pTask,unsigned long ulTaskId)
{
ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
ActiveTaskEntry* pEntry = pLst->GetEntry(ulTaskId);
if (!pEntry || pEntry->IsFinished()) return;

const ATaskTempl* pTaskTempl = GetTaskTemplMan()->GetTaskTemplByID(ulTaskId);
if (!pTaskTempl || pTaskTempl->m_enumMethod != enumTMReachSite) return;

float pos[3];
unsigned long ulWorldId = pTask->GetPos(pos);

if (ulWorldId != pTaskTempl->m_ulReachSiteId ||
!is_in_zone(
pTaskTempl->m_ReachSiteMin,
pTaskTempl->m_ReachSiteMax,
pos))
return;

pTaskTempl->OnSetFinished(
pTask,
pLst,
pEntry);
}

bool OnTaskCheckDeliver(TaskInterface* pTask, unsigned long ulTaskId)
{
TaskInterface::WriteLog(pTask->GetPlayerId(), ulTaskId, 1, "TaskCheckDeliverAtNPC");

const ATaskTempl* pTaskTempl = GetTaskTemplMan()->GetTaskTemplByID(ulTaskId);
if (!pTaskTempl) return false;

if (pTaskTempl->m_pParent) pTaskTempl = pTaskTempl->m_pParent;
else ulTaskId = 0;

if (pTaskTempl->CheckGlobalRequired(
pTask,
ulTaskId,
NULL,
NULL,
TASK_GLOBAL_CHECK_RCV_NUM))
return pTaskTempl->CheckDeliverTask(pTask, ulTaskId, NULL) == 0;

return true;
}

void OnTaskManualTrig(TaskInterface* pTask, unsigned long ulTask)
{
// 只有不通过npc的任务才能手动触发
const ATaskTempl* pTaskTempl = GetTaskTemplMan()->GetTopTaskByID(ulTask);
if (!pTaskTempl || pTaskTempl->m_ulDelvNPC) return;

OnTaskCheckDeliver(pTask, ulTask);
}

void OnNPCDeliverTaskItem(TaskInterface* pTask, unsigned long ulNPCId, unsigned long ulTaskId)
{
DATA_TYPE dt;
elementdataman* pMan = GetTaskTemplMan()->GetEleDataMan();

NPC_ESSENCE* pNPC = (NPC_ESSENCE*)pMan->get_data_ptr(
ulNPCId,
ID_SPACE_ESSENCE,
dt
);

if (!pNPC || dt != DT_NPC_ESSENCE)
return;

if (!pNPC->id_task_matter_service) return;

NPC_TASK_MATTER_SERVICE* pSvr = (NPC_TASK_MATTER_SERVICE*)pMan->get_data_ptr(
pNPC->id_task_matter_service,
ID_SPACE_ESSENCE,
dt
);

if (!pSvr || dt != DT_NPC_TASK_MATTER_SERVICE)
return;

ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
const int sz = sizeof(pSvr->tasks) / sizeof(pSvr->tasks[0]);

int i, j;
for (i = 0; i < sz; i++)
{
unsigned int id = pSvr->tasks.id_task;

if (!id) break;
if (ulTaskId != id || !pLst->GetEntry(id)) continue;

const int matter_num = sizeof(pSvr->tasks[0].taks_matters) / sizeof(pSvr->tasks[0].taks_matters[0]);
int actual_num = 0;

for (j = 0; j < matter_num; j++)
{
unsigned int matter = pSvr->tasks.taks_matters[j].id_matter;
if (!matter) break;
actual_num++;
}

if (actual_num == 0 || !pTask->CanDeliverTaskItem(actual_num)) break;

for (j = 0; j < actual_num; j++)
{
unsigned int matter = pSvr->tasks.taks_matters[j].id_matter;
int matter_num = pSvr->tasks.taks_matters[j].num_matter;

if (pTask->GetTaskItemCount(matter)) continue;
pTask->DeliverTaskItem(matter, matter_num);
}

break;
}
}

void OnTaskCheckAward(TaskInterface* pTask, unsigned long ulTaskId, int nChoice)
{
ActiveTaskList* pList = (ActiveTaskList*)pTask->GetActiveTaskList();
ActiveTaskEntry* aEntries = pList->m_TaskEntries;
unsigned long ulCurTime = pTask->GetCurTime();

for (unsigned char i = 0; i < pList->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = aEntries;

if (CurEntry.m_ID != ulTaskId
|| !CurEntry.m_ulTemplAddr)
continue;

const ATaskTempl* pTempl = CurEntry.GetTempl();

if (pTempl->m_enumFinishType != enumTFTNPC)
{
TaskInterface::WriteLog(pTask->GetPlayerId(), ulTaskId, 0, "SvrCheckAward Not By NPC");
return;
}

if (pTempl->m_bMarriage)
{
if (pTask->IsCaptain() && pTempl->CheckMarriage(pTask) == 0)
pTask->CheckTeamRelationship(TASK_TEAM_RELATION_MARRIAGE);

return;
}

if (pTempl->m_enumMethod == enumTMCollectNumArticle)
pTempl->CheckCollectItem(pTask, pList, &CurEntry, true, nChoice);
else if (pTempl->m_enumMethod == enumTMKillNumMonster)
pTempl->CheckMonsterKilled(pTask, pList, &CurEntry, true, nChoice);
else if (pTempl->m_enumMethod == enumTMWaitTime)
pTempl->CheckWaitTime(pTask, pList, &CurEntry, ulCurTime, true, nChoice);
else if (pTempl->m_enumMethod == enumTMTalkToNPC)
{
CurEntry.SetFinished();
pTempl->DeliverAward(pTask, pList, &CurEntry, nChoice);
}
else if (pTempl->m_enumMethod == enumTMGlobalValOK)
{
if (pTempl->CheckGlobalKeyValue(pTask, true) == 0)
{
CurEntry.SetFinished();
pTempl->DeliverAward(pTask, pList, &CurEntry, nChoice);
}
}
else if (pTempl->m_enumMethod == enumTMStatefulPacket)
{
if (pTask->GetTaskCondition() == pTempl->m_iStatefulPacketWanted)
{
CurEntry.SetFinished();
pTempl->DeliverAward(pTask, pList, &CurEntry, nChoice);
}
}
else if (pTempl->m_enumMethod == enumTMSimpleClientTask)
{
CurEntry.SetFinished();
pTempl->DeliverAward(pTask, pList, &CurEntry, nChoice);
}
else if (CurEntry.IsFinished())
pTempl->DeliverAward(pTask, pList, &CurEntry, nChoice);
else
TaskInterface::WriteLog(pTask->GetPlayerId(), ulTaskId, 0, "CheckAwardAtNPC: Task Not Finished");

return;
}
}

void OnTaskCheckAwardDirect(TaskInterface* pTask, unsigned long ulTaskId)
{
ActiveTaskList* pList = static_cast<ActiveTaskList*>(pTask->GetActiveTaskList());
ActiveTaskEntry* aEntries = pList->m_TaskEntries;
unsigned long ulCurTime = pTask->GetCurTime();

TaskInterface::WriteLog(pTask->GetPlayerId(), ulTaskId, 1, "SvrCheckAwardDirect");

for (unsigned char i = 0; i < pList->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = aEntries;

if (CurEntry.m_ID != ulTaskId
|| !CurEntry.m_ulTemplAddr)
continue;

const ATaskTempl* pTempl = CurEntry.GetTempl();

// PQ任务时戳不一致
if (pTempl->m_bPQSubTask)
{
if(!pTempl->m_pParent || CurEntry.m_ParentIndex == 0xff)
return;

ActiveTaskEntry& ParentEntry = aEntries[CurEntry.m_ParentIndex];

if(pTempl->m_pNextSibling) // 有子任务才会检查
{
if(ParentEntry.m_ulTaskTime != PublicQuestInterface::GetCurTaskStamp(ParentEntry.GetTempl()->m_ID))
{
CurEntry.ClearSuccess();
CurEntry.GetTempl()->OnSetFinished(pTask, pList, &CurEntry);
return;
}
else // 时戳一致,当前已接PQ子任务的下一阶段为服务器端PQ子任务时,才会完成
{
if(pTempl->m_pNextSibling->m_ID != PublicQuestInterface::GetCurSubTask(ParentEntry.GetTempl()->m_ID) &&
pTempl->m_ID != PublicQuestInterface::GetCurSubTask(ParentEntry.GetTempl()->m_ID))
{
CurEntry.ClearSuccess();
CurEntry.GetTempl()->OnSetFinished(pTask, pList, &CurEntry);
return;
}
}
}
}

if (CurEntry.IsFinished() && !CurEntry.IsSuccess()) // 失败
{
pTempl->DeliverAward(pTask, pList, &CurEntry, -1);
return;
}

if (pTempl->m_ulTimeLimit
&& CurEntry.m_ulTaskTime + pTempl->m_ulTimeLimit < ulCurTime) // 超时
{
CurEntry.ClearSuccess();
CurEntry.GetTempl()->OnSetFinished(pTask, pList, &CurEntry);
return;
}

// 进入or离开区域任务失败
float pos[3];
unsigned long ulWorldId = pTask->GetPos(pos);
unsigned long iRegion;

if (pTempl->m_bEnterRegionFail && ulWorldId == pTempl->m_ulEnterRegionWorld)
{
for (iRegion = 0;iRegion<pTempl->m_ulEnterRegionCnt;iRegion++)
{
const Task_Region& t = pTempl->m_pEnterRegion[iRegion];
if (is_in_zone(t.zvMin, t.zvMax, pos))
{
CurEntry.ClearSuccess();
CurEntry.GetTempl()->OnSetFinished(pTask, pList, &CurEntry);
return;
}
}
}

if (pTempl->m_bLeaveRegionFail)
{
bool bLeaveRegion = false;
if (ulWorldId != pTempl->m_ulLeaveRegionWorld) bLeaveRegion = true;
else
{
for (iRegion = 0;iRegion<pTempl->m_ulLeaveRegionCnt;iRegion++)
{
const Task_Region& t = pTempl->m_pLeaveRegion[iRegion];
if (is_in_zone(t.zvMin, t.zvMax, pos))
break;
}
if (iRegion >= pTempl->m_ulLeaveRegionCnt) bLeaveRegion = true;
}
if (bLeaveRegion)
{
CurEntry.ClearSuccess();
CurEntry.GetTempl()->OnSetFinished(pTask, pList, &CurEntry);
return;
}
}

if (pTempl->m_enumFinishType != enumTFTDirect)
{
if (!pTempl->m_ulTimeLimit)
TaskInterface::WriteLog(pTask->GetPlayerId(), ulTaskId, 0, "SvrCheckAward Not Direct");

return;
}

// 婚姻任务只能在npc处完成
if (pTempl->m_bMarriage)
return;

if (pTempl->m_enumMethod == enumTMCollectNumArticle)
pTempl->CheckCollectItem(pTask, pList, &CurEntry, false, -1);
else if (pTempl->m_enumMethod == enumTMKillNumMonster)
pTempl->CheckMonsterKilled(pTask, pList, &CurEntry, false, -1);
else if (pTempl->m_enumMethod == enumTMWaitTime)
pTempl->CheckWaitTime(pTask, pList, &CurEntry, ulCurTime, false, -1);
else if (pTempl->m_enumMethod == enumTMGlobalValOK)
{
if (pTempl->CheckGlobalKeyValue(pTask, true) == 0)
{
CurEntry.SetFinished();
pTempl->DeliverAward(pTask, pList, &CurEntry, -1);
}
}
else if (pTempl->m_enumMethod == enumTMStatefulPacket)
{
if (pTask->GetTaskCondition() == pTempl->m_iStatefulPacketWanted)
{
CurEntry.SetFinished();
pTempl->DeliverAward(pTask, pList, &CurEntry, -1);
}
}
else if (pTempl->m_enumMethod == enumTMSimpleClientTask) // 简单任务,服务器不验证,只客户端检查
{
CurEntry.SetFinished();
pTempl->DeliverAward(pTask, pList, &CurEntry, -1);
}
else if (CurEntry.IsFinished())
pTempl->DeliverAward(pTask, pList, &CurEntry, -1);
else if (!pTempl->m_ulTimeLimit)
TaskInterface::WriteLog(pTask->GetPlayerId(), ulTaskId, 0, "SvrCheckAward Wrong Method");

return;
}
}

inline void _on_kill_monster(
TaskInterface* pTask,
unsigned long ulTemplId,
unsigned long ulLev,
bool bTeam,
float fRand)
{
ActiveTaskList* pList = static_cast<ActiveTaskList*>(pTask->GetActiveTaskList());
ActiveTaskEntry* aEntries = pList->m_TaskEntries;

for (int i = 0; i < (int)pList->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = aEntries;

const ATaskTempl* pTempl = CurEntry.GetTempl();

if (!pTempl)
continue;

pTempl->CheckKillMonster(
pTask,
pList,
&CurEntry,
ulTemplId,
ulLev,
bTeam,
fRand);

// 若遍历已接任务列表的途中完成并清空了某个任务,则需要重新遍历列表
bool bCleared = pTempl->m_ID != (unsigned long)CurEntry.m_ID;
if (bCleared) i = -1;
}
}

void OnTaskKillMonster(TaskInterface* pTask, unsigned long ulTemplId, unsigned long ulLev, float fRand)
{
_on_kill_monster(pTask, ulTemplId, ulLev, false, fRand);
}

void OnTaskTeamKillMonster(TaskInterface* pTask, unsigned long ulTemplId, unsigned long ulLev, float fRand)
{
_on_kill_monster(pTask, ulTemplId, ulLev, true, fRand);
}

void OnTaskMining(TaskInterface* pTask, unsigned long ulTaskId)
{
ActiveTaskList* pList = static_cast<ActiveTaskList*>(pTask->GetActiveTaskList());
ActiveTaskEntry* pEntry = pList->GetEntry(ulTaskId);

if (!pEntry || !pEntry->GetTempl()) return;
pEntry->GetTempl()->CheckMining(pTask, pList, pEntry);
}

bool _on_player_killed(TaskInterface* pTask)
{
ActiveTaskList* pList = static_cast<ActiveTaskList*>(pTask->GetActiveTaskList());
ActiveTaskEntry* aEntries = pList->m_TaskEntries;

for (unsigned char i = 0; i < pList->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = aEntries;

if (!CurEntry.IsSuccess())
continue;

const ATaskTempl* pTempl = CurEntry.GetTempl();

if (pTempl && pTempl->m_bFailAsPlayerDie)
{
CurEntry.ClearSuccess();
pTempl->OnSetFinished(pTask, pList, &CurEntry);
return true;
}
}

return false;
}

void OnTaskPlayerKilled(TaskInterface* pTask)
{
while (_on_player_killed(pTask)) {}
GetTaskTemplMan()->CheckDeathTrig(pTask);
}

void OnTaskGiveUpOneTask(TaskInterface* pTask, unsigned long ulTaskId, bool bForce)
{
ActiveTaskList* pList = static_cast<ActiveTaskList*>(pTask->GetActiveTaskList());

for (unsigned char i = 0; i < pList->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = pList->m_TaskEntries;
if (!CurEntry.m_ulTemplAddr) continue;
const ATaskTempl* pTempl = CurEntry.GetTempl();
if (!pTempl || pTempl->m_ID != ulTaskId) continue;
// 超时不考虑任务是否完成,已完成的任务必须在时限前回到NPC
pTempl->GiveUpOneTask(pTask, pList, &CurEntry, bForce);
return;
}
}

void OnTaskCheckAllTimeLimits(unsigned long ulCurTime)
{
GetTaskTemplMan()->OnTaskCheckAllTimeLimits(ulCurTime);
}

void OnTaskReceivedGlobalData(
TaskInterface* pTask,
unsigned long ulTaskId,
unsigned char pData[TASK_GLOBAL_DATA_SIZE],
const void* pPreservedData,
size_t size)
{
const TaskPreservedData* pPreserve = (const TaskPreservedData*)pPreservedData;
ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
TaskGlobalData* pGlobal = (TaskGlobalData*)pData;
unsigned short reason = pPreserve->reason;

switch (reason)
{
case TASK_GLOBAL_NPC_KILLED_TIME:
return;
case TASK_GLOBAL_PROTECT_NPC:
OnTaskProtectNPC(pTask, ulTaskId, pGlobal);
return;
}

const ATaskTempl* pTempl = GetTaskTemplMan()->GetTaskTemplByID(pPreserve->m_ulSrcTask);

if (!pTempl)
return;

pGlobal->CheckRcvUpdateTime(pTask->GetCurTime(), pTempl->m_lAvailFrequency);

switch (reason)
{
case TASK_GLOBAL_CHECK_RCV_NUM:
case TASK_GLOBAL_CHECK_COTASK:
if (pTempl->CheckGlobalRequired(pTask, pPreserve->m_ulSubTaskId, pPreserve, pGlobal, reason))
pTempl->CheckDeliverTask(pTask, pPreserve->m_ulSubTaskId, pGlobal);
else
{
pTempl->NotifyClient(
pTask,
NULL,
TASK_SVR_NOTIFY_ERROR_CODE,
0,
TASK_PREREQU_FAIL_MAX_RCV);
}
break;
case TASK_GLOBAL_CHECK_ADD_MEM:
if (pTempl->CheckGlobalRequired(pTask, 0, pPreserve, pGlobal, TASK_GLOBAL_CHECK_ADD_MEM))
pTempl->OnDeliverTeamMemTask(pTask, pGlobal);
break;
case TASK_GLOBAL_ADD_TIME_MARK:
break;
case TASK_GLOBAL_DEL_TIME_MARK:
break;
}
}

void OnForgetLivingSkill(TaskInterface* pTask)
{
GetTaskTemplMan()->OnForgetLivingSkill(pTask);
}

void OnTaskPlayerLevelUp(TaskInterface* pTask)
{
}

// PQ任务初始化
bool InitPublicQuestSystem()
{
const ATaskTempl* pTempl;
TaskTemplMap& PQTemplMap = GetTaskTemplMan()->GetPQTemplMap();
TaskTemplMap::iterator it = PQTemplMap.begin();
bool bInitSucc = true;

for(; it != PQTemplMap.end(); ++it)
{
pTempl = it->second;

if(!pTempl || !(pTempl->m_pFirstChild))
{
printf("InitPublicQuestSystem(): cannot find task or task has no child. task id = %d", (pTempl) ? pTempl->m_ID : -1);
bInitSucc = false;
continue;
}

int global_value[TASK_AWARD_MAX_DISPLAY_EXP_CNT], i;
for(i=0;i<pTempl->m_ulPQExpCnt; i++)
{
global_value = atoi(pTempl->m_pszPQExp);
}

if(!PublicQuestInterface::InitAddQuest(pTempl->GetID(), pTempl->m_pFirstChild->GetID(), global_value, pTempl->m_ulPQExpCnt))
{
printf("InitPublicQuestSystem(): InitAddQuest() error, task id = %d.", pTempl->GetID());
bInitSucc = false;
continue;
}

for(i=0;i<pTempl->m_pFirstChild->m_ulPQExpCnt; i++)
{
global_value = atoi(pTempl->m_pFirstChild->m_pszPQExp);
}

// 启动刚初始化的PQ任务
PublicQuestInterface::QuestSetStart(pTempl->GetID(), global_value, pTempl->m_pFirstChild->m_ulPQExpCnt,pTempl->m_pFirstChild->IsNotChangePQRanking());

// 启动怪物控制器
if(pTempl->m_pFirstChild->m_ulMonsCtrlNum)
{
for (int i = 0;i < pTempl->m_pFirstChild->m_ulMonsCtrlNum;++i)
{
PublicQuestInterface::SetMonsterController(pTempl->m_pFirstChild->m_pMonsCtrl.iMonsCtrl, pTempl->m_pFirstChild->m_pMonsCtrl.bSwitch);
}
}
}

return bInitSucc;
}

// PQ任务的heartbeat
void OnTaskPublicQuestHeartbeat()
{
const ATaskTempl* pTempl;
TaskTemplMap& PQTemplMap = GetTaskTemplMan()->GetPQTemplMap();

unsigned int uMapSize = PQTemplMap.size();
if (uMapSize == 0)
{
return;
}

TaskTemplMap::iterator it = PQTemplMap.begin();

/* unsigned short* pFinishedTaskID = new unsigned short[uMapSize];

if (!pFinishedTaskID)
{
return;
}
memset(pFinishedTaskID,0,sizeof(unsigned short*) * uMapSize);
*/
for(; it != PQTemplMap.end(); ++it)
{
pTempl = it->second;

if(!pTempl)
return;

int iSubTaskId = PublicQuestInterface::GetCurSubTask(pTempl->m_ID);
const ATaskTempl* pSubTempl = GetTaskTemplMan()->GetTaskTemplByID(iSubTaskId);

if(!pSubTempl)
return;

int iIndexFinished = 0;
// 判断PQ任务的当前子任务是否完成
if(pSubTempl->CheckGlobalPQKeyValue(true) == 0)
{
// 增加当前子任务贡献度(固定&随机)
PublicQuestInterface::QuestSetRandContrib(pTempl->m_ID, pSubTempl->m_Award_S->m_ulContrib, pSubTempl->m_Award_S->m_ulRandContrib, pSubTempl->m_Award_S->m_ulLowestcontrib);

// 启动奖励怪物控制器
if(pSubTempl->m_Award_S->m_ulMonsCtrlNum)
{
for (int i = 0;i < pSubTempl->m_Award_S->m_ulMonsCtrlNum;++i)
{
PublicQuestInterface::SetMonsterController(pSubTempl->m_Award_S->m_pMonsCtrl.iMonsCtrl, pSubTempl->m_Award_S->m_pMonsCtrl.bSwitch);
}
}


int global_value[TASK_AWARD_MAX_DISPLAY_EXP_CNT], i;
if(pSubTempl->m_pNextSibling)
{
for(i=0;i<pSubTempl->m_pNextSibling->m_ulPQExpCnt; i++)
{
global_value = atoi(pSubTempl->m_pNextSibling->m_pszPQExp);
}

PublicQuestInterface::QuestSetNextChildTask(pTempl->m_ID, pSubTempl->m_pNextSibling->m_ID, global_value, pSubTempl->m_pNextSibling->m_ulPQExpCnt,pSubTempl->m_pNextSibling->IsNotChangePQRanking());

// 启动怪物控制器
if(pSubTempl->m_pNextSibling->m_ulMonsCtrlNum)
{
for (int i = 0;i < pSubTempl->m_pNextSibling->m_ulMonsCtrlNum;++i)
{
PublicQuestInterface::SetMonsterController(pSubTempl->m_pNextSibling->m_pMonsCtrl.iMonsCtrl, pSubTempl->m_pNextSibling->m_pMonsCtrl.bSwitch);
}
}

}
else // 若PQ任务已经完成,重新启动一个新的
{
PublicQuestInterface::QuestSetFinish(pTempl->m_ID);

//pFinishedTaskID[iIndexFinished++] = pTempl->m_ID;
for(i=0;i<pTempl->m_pFirstChild->m_ulPQExpCnt; i++)
{
global_value = atoi(pTempl->m_pFirstChild->m_pszPQExp);
}

PublicQuestInterface::QuestSetStart(pTempl->m_ID, global_value, pTempl->m_pFirstChild->m_ulPQExpCnt,pTempl->m_pFirstChild->IsNotChangePQRanking());

// 启动怪物控制器
if(pTempl->m_pFirstChild->m_ulMonsCtrlNum)
{
for (int i = 0;i < pTempl->m_pFirstChild->m_ulMonsCtrlNum;++i)
{
PublicQuestInterface::SetMonsterController(pTempl->m_pFirstChild->m_pMonsCtrl.iMonsCtrl, pTempl->m_pFirstChild->m_pMonsCtrl.bSwitch);
}
}

}
}
}
/*
for (unsigned int i = 0;i < uMapSize;++i)
{
if (pFinishedTaskID)
{
GetTaskTemplMan()->RemoveOnePQTask(pFinishedTaskID);
}
}
*/
}

// PQ任务杀怪贡献度分配
/*
ulTemplId: 所杀怪的ID
bOwner: 是否为怪物所属(分享模式时,该参数无用)
fTeamContrib: 队伍贡献。如果玩家不在队伍中,则为个人贡献(独享模式时,该参数无用)
iTeamMemberCnt: 队伍中队员数量。如果玩家不在队伍中,则为1;
*/
void OnTaskKillPQMonster(TaskInterface* pTask, unsigned long ulTemplId, bool bOwner,float fTeamContrib,int iTeamMemberCnt,float fPersonalContib)
{
ActiveTaskList* pList = static_cast<ActiveTaskList*>(pTask->GetActiveTaskList());
ActiveTaskEntry* aEntries = pList->m_TaskEntries;

for(unsigned char i=0;i<pList->m_uTaskCount; i++)
{
ActiveTaskEntry& CurEntry = aEntries;

if (!CurEntry.m_ulTemplAddr)
continue;

const ATaskTempl* pTempl = CurEntry.GetTempl();

// 若为PQ子任务(且子任务时间戳与当前PQ任务一致),则进行贡献度分配
if(pTempl->m_bPQSubTask)
{
// 检查时间戳是否一致
if (CurEntry.m_ParentIndex != 0xff)
{
ActiveTaskEntry& ParentEntry = aEntries[CurEntry.m_ParentIndex];

if(ParentEntry.m_ulTaskTime != PublicQuestInterface::GetCurTaskStamp(pTempl->m_pParent->m_ID))
return;
}

for (unsigned char j=0; j<pTempl->m_ulMonsterContribCnt; j++)
{
const MONSTERS_CONTRIB& MonstersContrib = pTempl->m_MonstersContrib[j];

if(ulTemplId == MonstersContrib.m_ulMonsterTemplId)
{
int iTotalContrib = 0;

// 独享贡献度
if(bOwner)
iTotalContrib += MonstersContrib.m_iWholeContrib/iTeamMemberCnt;

// 分享贡献度
iTotalContrib += (int)((MonstersContrib.m_iShareContrib * fTeamContrib)/iTeamMemberCnt + 0.5f);

PublicQuestInterface::QuestUpdatePlayerContrib(pTempl->m_pParent->m_ID, pTask->GetPlayerId(), iTotalContrib);
return;
}
}

return;
}
}
}

// PQ任务初始化link信息
void OnTaskCheckPQEnterWorldInit(TaskInterface* pTask, unsigned long ulTaskId)
{
pTask->PQEnterWorldInit(ulTaskId);
}


void OnTaskExternEvent(TaskInterface* pTask, int Event)
{
switch (Event)
{
case EX_TK_SENDAUMAIL_LEVEL1:
OnTaskManualTrig(pTask,16939);
break;
case EX_TK_SENDAUMAIL_LEVEL2:
OnTaskManualTrig(pTask,16940);
break;
case EX_TK_SENDAUMAIL_LEVEL3:
OnTaskManualTrig(pTask,16941);
break;
case EX_TK_SENDAUMAIL_EXAWARD:
OnTaskManualTrig(pTask,16942);
break;
case EX_TK_LOGIN_REWARD:
{
if (pTask->GetCurTime() - pTask->GetLastLoginTime() >= EX_TK_15DAYS_SECONDS)
{
OnTaskManualTrig(pTask,17034);
}
}
break;
case EX_TK_MOSTKILL_BONUS:
OnTaskManualTrig(pTask,17309);
break;
case EX_TK_MOSTDEATH_BONUS:
OnTaskManualTrig(pTask,17310);
break;
case EX_TK_MOSTPROFIT_BONUS:
OnTaskManualTrig(pTask,17311);
break;
}
}

void OnTaskSpecialAwardMask(TaskInterface* pTask,unsigned long ulTaskID)
{
special_award sa;
pTask->GetSpecailAwardInfo(&sa);
for (int i = 0;i < NUM_SPECIAL_AWARD;i++)
{
if ((sa.special_mask & (1 << i)) && TASK_SPECIAL_AWARD == ulTaskID)
{
OnTaskManualTrig(pTask,TASK_SPECIAL_AWARD);
}
}
}
void OnTaskRequestTreasureIndex(TaskInterface* pTask,unsigned long ulTaskId)
{
ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
ActiveTaskEntry* pEntry = pLst->GetEntry(ulTaskId);
if (!pEntry || pEntry->IsFinished()) return;

unsigned char buf[20];
svr_treasure_map* pNotify = reinterpret_cast<svr_treasure_map*>(buf);
size_t sz = sizeof(svr_treasure_map);

pNotify->reason = TASK_SVR_NOTIFY_TREASURE_MAP;

pNotify->task = static_cast<unsigned short>(ulTaskId);
pNotify->treasure_index = pEntry->m_iUsefulData1;

pTask->NotifyClient(buf,sz);
}
void OnTaskCheckTreasure(TaskInterface* pTask,unsigned long ulTaskId)
{
ActiveTaskList* pLst = (ActiveTaskList*)pTask->GetActiveTaskList();
ActiveTaskEntry* pEntry = pLst->GetEntry(ulTaskId);
if (!pEntry || pEntry->IsFinished()) return;

const ATaskTempl* pTaskTempl = GetTaskTemplMan()->GetTaskTemplByID(ulTaskId);
if (!pTaskTempl || pTaskTempl->m_enumMethod != enumTMReachTreasureZone) return;

float pos[3];
unsigned long ulWorldId = pTask->GetPos(pos);

if (ulWorldId != 1)
return;

unsigned short uTreasureLocIndex = pEntry->m_iUsefulData1 & 0xFFFF;
float fTreasureLocX = pTaskTempl->m_TreasureStartZone.x + (uTreasureLocIndex % pTaskTempl->m_ucZonesNumX - 1) * pTaskTempl->m_ucZoneSide;
float fTreasureLocZ = pTaskTempl->m_TreasureStartZone.z + (uTreasureLocIndex / pTaskTempl->m_ucZonesNumX) * pTaskTempl->m_ucZoneSide;

if (pos[0] >= fTreasureLocX && pos[2] >= fTreasureLocZ && pos[0] <= fTreasureLocX + pTaskTempl->m_ucZoneSide && pos[2] <= fTreasureLocZ + pTaskTempl->m_ucZoneSide)
{
pTaskTempl->OnSetFinished(pTask,pLst,pEntry);
}
}

void OnTaskTitle(TaskInterface* pTask, unsigned long ulTaskID)
{
const ATaskTempl* pTempl = GetTaskTemplMan()->GetTopTaskByID(ulTaskID);
if (!pTempl || !pTempl->m_bDisplayInTitleTaskUI) return;

if (pTempl->CheckGlobalRequired(
pTask,
0,
NULL,
NULL,
TASK_GLOBAL_CHECK_RCV_NUM))
pTempl->CheckDeliverTask(pTask, 0, NULL);
}

#endif
 
Newbie Spellweaver
Joined
Nov 19, 2022
Messages
6
Reaction score
1
hi , Wrechid

Thanks for your share!

I am newfisher to there! is the file support all version of w2i client?
 
Newbie Spellweaver
Joined
Feb 28, 2024
Messages
5
Reaction score
0
Simple elements and tasks data editor for pay2play world2...

elements - v29
tasks - v78
npcgen
aipolicy - v4

can this tool be used to activate Dungeon and Homestead quests? I'm still learning, it's been a few days of trying to activate the quest but it doesn't work. I tried to run the server offline using Oracle Virtual Box, I could only log in, but all dungeon quests were inactive, including other maps, I could only teleport around the world map o_O There are masters here who can teach how to activate maps and dungeon quests in teleport stones step by step. Thanks.
 

Attachments

You must be registered for see attachments list
Elite Diviner
Joined
Jan 5, 2017
Messages
476
Reaction score
348
this editor will not work for server 165, this is a special remake of the editor specifically for elements.data v29... that one is an old version but also a pay to play version W2...

Answer to your question, it looks like the other maps are not running, they are run as separate services. Editors and most tools do not offer the ability to start and stop the server or maps. its best to start maps via command prompt. you may need to check the start script or the method you use to start the server in why the maps are not loaded...
 
Back
Top