3450fd015f
# Conflicts: # Assets/PerfectWorld/Config.meta # Assets/PerfectWorld/Editor.meta # Assets/PerfectWorld/Scripts/Inventory/EC_IvtrType.cs # Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs # Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs # Assets/PerfectWorld/Scripts/Move/CECPlayer.cs # Assets/PerfectWorld/Scripts/NPC/CECNPC.cs # Assets/PerfectWorld/Scripts/Network/CSNetwork/CSNetwork.csproj.meta # Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs # Assets/Scenes/NPCRender.unity # Assets/Scenes/a61.unity # Assets/Scripts/CECGameRun.cs # Assets/Scripts/CECHostPlayer.Task.cs # Assets/Scripts/CECHostPlayer.cs # Assets/Scripts/CECPlayer_Inventory.cs # Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset
1445 lines
49 KiB
C#
1445 lines
49 KiB
C#
using BrewMonster.Network;
|
||
using BrewMonster.Scripts.Managers;
|
||
using BrewMonster.Scripts.Player;
|
||
using CSNetwork.GPDataType;
|
||
using PerfectWorld.Scripts.Task;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Runtime.InteropServices;
|
||
using UnityEngine;
|
||
|
||
namespace BrewMonster.Scripts.Task
|
||
{
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||
public class Kill_Player_Requirements
|
||
{
|
||
public const uint MAX_OCCPU_MASK = ((uint)1 << TaskInterfaceConstants.MAX_OCCUPATIONS) - 1u;
|
||
|
||
public uint m_ulOccupations;
|
||
public int m_iMinLevel;
|
||
public int m_iMaxLevel;
|
||
public int m_iGender;
|
||
public int m_iForce;
|
||
|
||
public Kill_Player_Requirements()
|
||
{
|
||
m_iMinLevel = 10;
|
||
m_iMaxLevel = 100;
|
||
m_iGender = 0;
|
||
m_iForce = 0;
|
||
m_ulOccupations = MAX_OCCPU_MASK;
|
||
}
|
||
|
||
public bool IsMeetAllOccupation()
|
||
{
|
||
return m_ulOccupations == MAX_OCCPU_MASK;
|
||
}
|
||
|
||
public bool CheckRequirements(int iOccupation, int iLevel, bool bGender, int iForce)
|
||
{
|
||
bool bForce = false;
|
||
// �༭����1Ϊ�У�2ΪŮ // In editor: 1 is male, 2 is female
|
||
int iGender = bGender ? 2 : 1;
|
||
// �༭����0����û������Ҫ�� // In editor: 0 means no force requirement
|
||
if (m_iForce == 0)
|
||
{
|
||
bForce = true;
|
||
}
|
||
// �����ʾ������Ҫ�� // Otherwise indicates there is a force requirement
|
||
else
|
||
{
|
||
// �༭���ﻪ�⡢�����ͻ�ҹ�ֱ��õ�һ����������������λ��ʾ // Map force ids to bit positions
|
||
int iForceMask = 0;
|
||
if (iForce == 0)
|
||
{
|
||
return false;
|
||
}
|
||
else if (iForce == 1004)
|
||
{
|
||
iForceMask = 1 << 0;
|
||
}
|
||
else if (iForce == 1005)
|
||
{
|
||
iForceMask = 1 << 1;
|
||
}
|
||
else if (iForce == 1006)
|
||
{
|
||
iForceMask = 1 << 2;
|
||
}
|
||
bForce = (m_iForce & iForceMask) != 0;
|
||
}
|
||
return ((m_ulOccupations & (1u << iOccupation)) != 0)
|
||
&& m_iMinLevel <= iLevel
|
||
&& m_iMaxLevel >= iLevel
|
||
&& (m_iGender != 0 ? m_iGender == iGender : true)
|
||
&& bForce;
|
||
}
|
||
}
|
||
|
||
#if _TASK_CLIENT
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||
public struct Task_State_info
|
||
{
|
||
public uint m_ulTimeLimit;
|
||
public uint m_ulTimePassed;
|
||
public uint m_ulNPCToProtect;
|
||
public uint m_ulProtectTime;
|
||
public uint m_ulWaitTime;
|
||
public uint m_ulErrCode;
|
||
public uint m_ulGoldWanted;
|
||
public uint m_ulReachLevel;
|
||
public uint m_ulReachReincarnation;
|
||
public uint m_ulReachRealm;
|
||
public uint m_ulPremLevelMin;
|
||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||
public struct m_MonsterWanted_s
|
||
{
|
||
public uint m_ulMonsterId;
|
||
public uint m_ulMonstersToKill;
|
||
public uint m_ulMonstersKilled;
|
||
}
|
||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.MAX_MONSTER_WANTED)]
|
||
public m_MonsterWanted_s[] m_MonsterWanted;
|
||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||
public struct m_ItemsWanted_s
|
||
{
|
||
public uint m_ulItemId;
|
||
public uint m_ulItemsToGet;
|
||
public uint m_ulItemsGained;
|
||
public uint m_ulMonsterId;
|
||
}
|
||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.MAX_ITEM_WANTED)]
|
||
public m_ItemsWanted_s[] m_ItemsWanted;
|
||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||
public struct TASK_INFO_PLAYER
|
||
{
|
||
public uint m_ulPlayersToKill;
|
||
public uint m_ulPlayersKilled;
|
||
public Kill_Player_Requirements m_Requirements;
|
||
}
|
||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.MAX_PLAYER_WANTED)]
|
||
public TASK_INFO_PLAYER[] m_PlayerWanted;
|
||
|
||
// abase::vector<wchar_t*> m_TaskCharArr (assumed 3 pointers: start, finish, end_of_storage; 32-bit layout)
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||
public struct abase_vector_wchar_t_ptr
|
||
{
|
||
public uint _start;
|
||
public uint _finish;
|
||
public uint _end_of_storage;
|
||
}
|
||
public abase_vector_wchar_t_ptr m_TaskCharArr;
|
||
}
|
||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||
public struct Task_Award_Preview
|
||
{
|
||
public uint m_ulGold;
|
||
public uint m_ulExp;
|
||
public uint m_ulRealmExp;
|
||
public uint m_ulSP;
|
||
public bool m_bHasItem;
|
||
public bool m_bItemKnown;
|
||
public uint m_ulItemTypes;
|
||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.MAX_ITEM_AWARD)]
|
||
public uint[] m_ItemsId;
|
||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.MAX_ITEM_AWARD)]
|
||
public uint[] m_ItemsNum;
|
||
public int m_iForceActivity;
|
||
public int m_iForceContrib;
|
||
public int m_iForceRepu;
|
||
}
|
||
|
||
#endif
|
||
|
||
public class TaskInterfaceConstants
|
||
{
|
||
// Task Prerequisite Error Code
|
||
public const int TASK_PREREQU_FAIL_INDETERMINATE = 1;
|
||
public const int TASK_PREREQU_FAIL_NOT_ROOT = 2;
|
||
public const int TASK_PREREQU_FAIL_SAME_TASK = 3;
|
||
public const int TASK_PREREQU_FAIL_NO_SPACE = 4;
|
||
public const int TASK_PREREQU_FAIL_FULL = 5;
|
||
public const int TASK_PREREQU_FAIL_CANT_REDO = 6;
|
||
public const int TASK_PREREQU_FAIL_BELOW_LEVEL = 7;
|
||
public const int TASK_PREREQU_FAIL_ABOVE_LEVEL = 8;
|
||
public const int TASK_PREREQU_FAIL_NO_ITEM = 9;
|
||
public const int TASK_PREREQU_FAIL_BELOW_REPU = 10;
|
||
public const int TASK_PREREQU_FAIL_CLAN = 11;
|
||
public const int TASK_PREREQU_FAIL_WRONG_GENDER = 12;
|
||
public const int TASK_PREREQU_FAIL_NOT_IN_OCCU = 13;
|
||
public const int TASK_PREREQU_FAIL_WRONG_PERIOD = 14;
|
||
public const int TASK_PREREQU_FAIL_PREV_TASK = 15;
|
||
public const int TASK_PREREQU_FAIL_MAX_RCV = 16;
|
||
public const int TASK_PREREQU_FAIL_NO_DEPOSIT = 17;
|
||
public const int TASK_PREREQU_FAIL_NO_TASK = 18;
|
||
public const int TASK_PREREQU_FAIL_NOT_CAPTAIN = 19;
|
||
public const int TASK_PREREQU_FAIL_ILLEGAL_MEM = 20;
|
||
public const int TASK_PREREQU_FAIL_WRONG_TIME = 21;
|
||
public const int TASK_PREREQU_FAIL_NO_SUCH_SUB = 22;
|
||
public const int TASK_PREREQU_FAIL_MUTEX_TASK = 23;
|
||
public const int TASK_PREREQU_FAIL_NOT_IN_ZONE = 24;
|
||
public const int TASK_PREREQU_FAIL_WRONG_SUB = 25;
|
||
public const int TASK_PREREQU_FAIL_OUTOF_DIST = 26;
|
||
public const int TASK_PREREQU_FAIL_GIVEN_ITEM = 27;
|
||
public const int TASK_PREREQU_FAIL_LIVING_SKILL = 28;
|
||
public const int TASK_PREREQU_FAIL_SPECIAL_AWARD = 29;
|
||
public const int TASK_PREREQU_FAIL_GM = 30;
|
||
public const int TASK_PREREQU_FAIL_GLOBAL_KEYVAL = 31;
|
||
public const int TASK_PREREQU_FAIL_SHIELD_USER = 32;
|
||
public const int TASK_PREREQU_FAIL_ALREADY_HAS_PQ = 33;
|
||
public const int TASK_PREREQU_FAIL_MAX_ACC_CNT = 34;
|
||
public const int TASK_PREREQU_FAIL_RMB_NOT_ENOUGH = 35;
|
||
public const int TASK_PREREQU_FAIL_NOT_COUPLE = 36;
|
||
public const int TASK_PREREQU_FAIL_ERR_CHAR_TIME = 37;
|
||
public const int TASK_PREREQU_FAIL_NOT_IVTRSLOTNUM = 38; // version 81
|
||
public const int TASK_PREREQU_FAIL_BELOW_FACTION_CONTRIB = 39; // version 87
|
||
public const int TASK_PREREQU_FAIL_BELOW_RECORD_TASKS_NUM = 40; // version 91
|
||
public const int TASK_PREREQU_FAIL_OVER_RECEIVE_PER_DAY = 41;
|
||
public const int TASK_PREREQU_FAIL_TRANSFORM_MASK = 42;
|
||
public const int TASK_PREREQU_FAIL_FORCE = 43;
|
||
public const int TASK_PREREQU_FAIL_FORCE_REPUTATION = 44;
|
||
public const int TASK_PREREQU_FAIL_FORCE_CONTRIBUTION = 45;
|
||
public const int TASK_PREREQU_FAIL_EXP = 46;
|
||
public const int TASK_PREREQU_FAIL_SP = 47;
|
||
public const int TASK_PREREQU_FAIL_FORCE_AL = 48;
|
||
public const int TASK_PREREQU_FAIL_WEDDING_OWNER = 49;
|
||
public const int TASK_PREREQU_FAIL_CROSSSERVER_NO_ACOUNT_LIMIT = 50;
|
||
public const int TASK_PREREQU_FAIL_CROSSSERVER_NO_MARRIAGE = 51;
|
||
public const int TASK_PREREQU_FAIL_CROSSSERVER_NO_FORCE = 52;
|
||
public const int TASK_PREREQU_FAIL_KING = 53;
|
||
public const int TASK_PREREQU_FAIL_IN_TEAM = 54;
|
||
public const int TASK_PREREQU_FAIL_TITLE = 55;
|
||
public const int TASK_PREREQU_FAIL_HISTORYSTAGE = 56;
|
||
public const int TASK_PREREQU_FAIL_NO_GIFTCARD_TASK = 57;
|
||
public const int TASK_PREREQU_FAIL_BELOW_REINCARNATION = 57;
|
||
public const int TASK_PREREQU_FAIL_ABOVE_REINCARNATION = 58;
|
||
public const int TASK_PREREQU_FAIL_BELOW_REALMLEVEL = 59;
|
||
public const int TASK_PREREQU_FAIL_ABOVE_REALMLEVEL = 60;
|
||
public const int TASK_PREREQU_FAIL_REALM_EXP_FULL = 61;
|
||
public const int TASK_PREREQU_FAIL_CARD_COUNT_COLLECTION = 62;
|
||
public const int TASK_PREREQU_FAIL_MAX_ROLE_CNT = 63;
|
||
public const int TASK_PREREQU_FAIL_CARD_COUNT_RANK = 64;
|
||
public const int TASK_PREREQU_FAIL_TASK_FORBID = 65;
|
||
public const int TASK_PREREQU_FAIL_NO_NAVIGATE_INSHPAED = 66;
|
||
|
||
public const int TASK_AWARD_FAIL_GIVEN_ITEM = 150;
|
||
public const int TASK_AWARD_FAIL_NEW_TASK = 151;
|
||
public const int TASK_AWARD_FAIL_REPUTATION = 152;
|
||
public const int TASK_AWARD_FAIL_GLOBAL_KEYVAL = 153;
|
||
public const int TASK_AWARD_FAIL_CROSSSERVER_NO_ACOUNT_LIMIT = 154;
|
||
public const int TASK_AWARD_FAIL_CROSSSERVER_NO_ACOUNT_STORAGE = 155;
|
||
public const int TASK_AWARD_FAIL_CROSSSERVER_NO_DIVORCE = 156;
|
||
public const int TASK_AWARD_FAIL_CROSSSERVER_NO_FACTION_RALATED = 157;
|
||
public const int TASK_AWARD_FAIL_CROSSSERVER_NO_FORCE_RALATED = 158;
|
||
public const int TASK_AWARD_FAIL_CROSSSERVER_NO_DIVIEND = 159;
|
||
public const int TASK_AWARD_FAIL_LEVEL_CHECK = 160;
|
||
|
||
|
||
// Task messages
|
||
public const int TASK_MSG_NEW = 1;
|
||
public const int TASK_MSG_SUCCESS = 2;
|
||
public const int TASK_MSG_FAIL = 3;
|
||
|
||
public const int TASK_ACTIVE_LIST_HEADER_LEN = 8;
|
||
public const int TASK_ACTIVE_LIST_MAX_LEN = 175;
|
||
public const int TASK_FINISHED_LIST_MAX_LEN = 2040;
|
||
public const int TASK_DATA_BUF_MAX_LEN = 32;
|
||
public const int TASK_FINISH_TIME_MAX_LEN = 1700;
|
||
public const int TASK_FINISH_COUNT_MAX_LEN = 730;
|
||
|
||
// 库任务 // Library tasks
|
||
public const int TASK_MAX_DELIVER_COUNT = 5;
|
||
public const int TASK_STORAGE_COUNT = 32;
|
||
public const int TASK_STORAGE_LEN = 10;
|
||
public const int TASK_STORAGE_WHELL_SCALE = 10000; // 10000.f originally
|
||
|
||
// 当前激活的任务列表缓冲区大小 // Current active task list buffer size
|
||
public const int TASK_ACTIVE_LIST_BUF_SIZE = (TASK_ACTIVE_LIST_MAX_LEN * TASK_DATA_BUF_MAX_LEN + TASK_ACTIVE_LIST_HEADER_LEN);
|
||
// 已完成的任务列表缓冲区大小 // Completed task list buffer size
|
||
public const int TASK_FINISHED_LIST_BUF_SIZE = 8192;
|
||
public const int TASK_FINISHED_LIST_BUF_SIZE_OLD = 4096;
|
||
// 任务全局数据大小 // Task global data size
|
||
public const int TASK_GLOBAL_DATA_SIZE = 256;
|
||
// 任务完成时间 // Task completion time
|
||
public const int TASK_FINISH_TIME_LIST_BUF_SIZE = 10240;
|
||
//任务完成次数 // Task completion count
|
||
public const int TASK_FINISH_COUNT_LIST_BUF_SIZE = 10240;
|
||
// 库任务 // Library tasks
|
||
public const int TASK_STORAGE_LIST_BUF_SIZE = 1024;
|
||
|
||
|
||
// Masks
|
||
public const int TASK_MASK_KILL_MONSTER = 0x00000001;
|
||
public const int TASK_MASK_COLLECT_ITEM = 0x00000002;
|
||
public const int TASK_MASK_TALK_TO_NPC = 0x00000004;
|
||
public const int TASK_MASK_REACH_SITE = 0x00000008;
|
||
public const int TASK_MASK_ANSWER_QUESTION = 0x00000010;
|
||
public const int TASK_MASK_TINY_GAME = 0x00000020;
|
||
public const int TASK_MASK_KILL_PQ_MONSTER = 0x00000040;
|
||
public const int TASK_MASK_KILL_PLAYER = 0x00000080;
|
||
|
||
|
||
public const int MAX_MONSTER_WANTED = 3; // 受ActiveTaskEntry大小限制,最大3 // Limited by ActiveTaskEntry size, max 3
|
||
public const int MAX_PLAYER_WANTED = MAX_MONSTER_WANTED;
|
||
public const int MAX_ITEM_WANTED = 10;
|
||
public const int MAX_ITEM_AWARD = 64;
|
||
public const int MAX_MONSTER_SUMMONED = 32; // 最大召唤出的怪物数量 // Maximum number of summoned monsters
|
||
|
||
public const int MAX_OCCUPATIONS = 12; // 职业 // Occupations
|
||
|
||
public const int TASK_MSG_CHANNEL_LOCAL = 0;
|
||
public const int TASK_MSG_CHANNEL_WORLD = 1;
|
||
public const int TASK_MSG_CHANNEL_BROADCAST = 9;
|
||
|
||
public const int TASK_TEAM_RELATION_MARRIAGE = 1;
|
||
|
||
public const int TASK_AWARD_MAX_CHANGE_VALUE = 255;
|
||
public const int TASK_AWARD_MAX_DISPLAY_VALUE = 64;
|
||
|
||
public const int TASK_AWARD_MAX_DISPLAY_EXP_CNT = 32; // 表达式的个数 // Number of expressions
|
||
public const int TASK_AWARD_MAX_DISPLAY_CHAR_LEN = 64; // 表达式的长度 // Length of expression
|
||
|
||
public const int TASK_WORLD_CONTRIBUTION_SPEND_PER_DAY = 30; // 免费玩家每日消费贡献度上限 // Daily contribution spend cap for free players
|
||
|
||
}
|
||
public class CECTaskInterface : TaskInterface
|
||
{
|
||
// public const int TASK_MAX_DELIVER_COUNT = 5;
|
||
// public const int TASK_STORAGE_COUNT = 32;
|
||
// public const int TASK_STORAGE_LEN = 10;
|
||
// public const float TASK_STORAGE_WHELL_SCALE = 10000;
|
||
//
|
||
// public const int TASK_ACTIVE_LIST_HEADER_LEN = 8;
|
||
// public const int TASK_ACTIVE_LIST_MAX_LEN = 175;
|
||
// public const int TASK_FINISHED_LIST_MAX_LEN = 2040;
|
||
// public const int TASK_DATA_BUF_MAX_LEN = 32;
|
||
// public const int TASK_FINISH_TIME_MAX_LEN = 1700;
|
||
// public const int TASK_FINISH_COUNT_MAX_LEN = 730;
|
||
|
||
// µ±Ç°¼¤»îµÄÈÎÎñÁÐ±í»º³åÇø´óС
|
||
public int TASK_ACTIVE_LIST_BUF_SIZE =>
|
||
(TaskInterfaceConstants.TASK_ACTIVE_LIST_MAX_LEN * TaskInterfaceConstants.TASK_DATA_BUF_MAX_LEN + TaskInterfaceConstants.TASK_ACTIVE_LIST_HEADER_LEN);
|
||
|
||
CECHostPlayer m_pHost;
|
||
ActiveTaskList m_pActiveListBuf; // Active task list buffer
|
||
// private byte[] m_pActiveListRawBuf; // raw buffer backing for active list (converted from C++)
|
||
byte[] m_pFinishedListBuf; // Finished task list buffer
|
||
byte[] m_pFinishedTimeListBuf; // Finished time list buffer
|
||
byte[] m_pFinishedCountListBuf;// Finished count list buffer
|
||
byte[] m_pStorageTaskListBuf; // Storage tasks list buffer
|
||
private Dictionary<int, bool> m_TasksToConfirm = new Dictionary<int, bool>();
|
||
private readonly System.Collections.Generic.Dictionary<uint, bool> m_emotionTask = new System.Collections.Generic.Dictionary<uint, bool>();
|
||
private bool m_bForceNavigateFinish;
|
||
private int m_tmFinishDlgShown;
|
||
public CECTaskInterface()
|
||
{
|
||
|
||
}
|
||
public CECTaskInterface(CECHostPlayer pHost)
|
||
{
|
||
m_pHost = pHost;
|
||
|
||
m_pActiveListBuf = null;
|
||
m_pFinishedListBuf = null;
|
||
m_pFinishedTimeListBuf = null;
|
||
m_pFinishedCountListBuf = null;
|
||
m_pStorageTaskListBuf = null;
|
||
}
|
||
|
||
// Initialize object
|
||
public bool Init(byte[] pActiveListBuf, int iActiveListLen, byte[] pFinishedListBuf,
|
||
int iFinishedListLen, byte[] pFinishedTimeListBuf, int iFinishedTimeListLen,
|
||
byte[] pFinishedCountListBuf, int iFinishedCountListLen, byte[] pStorageTaskListBuf, int iStorageTaskListLen)
|
||
{
|
||
// basic argument check (converted from ASSERT)
|
||
if (pActiveListBuf == null || pFinishedListBuf == null || pFinishedTimeListBuf == null || pFinishedCountListBuf == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
BMLogger.Log($"pActiveListBuf: {pActiveListBuf.Length} - {TaskInterfaceConstants.TASK_ACTIVE_LIST_BUF_SIZE}");
|
||
|
||
// allocate internal buffers and copy; remaining bytes are zero-initialized in C#
|
||
// m_pActiveListRawBuf = new byte[TaskInterfaceConstants.TASK_ACTIVE_LIST_BUF_SIZE];
|
||
// {
|
||
// int copy = Mathf.Min(iActiveListLen, TaskInterfaceConstants.TASK_ACTIVE_LIST_BUF_SIZE);
|
||
// if (copy > 0) System.Buffer.BlockCopy(pActiveListBuf, 0, m_pActiveListRawBuf, 0, copy);
|
||
// }
|
||
m_pActiveListBuf = new ActiveTaskList();
|
||
m_pActiveListBuf.ReadFromBuffer(pActiveListBuf);
|
||
|
||
|
||
m_pFinishedListBuf = new byte[TaskInterfaceConstants.TASK_FINISHED_LIST_BUF_SIZE];
|
||
{
|
||
int copy = Mathf.Min(iFinishedListLen, TaskInterfaceConstants.TASK_FINISHED_LIST_BUF_SIZE);
|
||
if (copy > 0) System.Buffer.BlockCopy(pFinishedListBuf, 0, m_pFinishedListBuf, 0, copy);
|
||
}
|
||
|
||
m_pFinishedTimeListBuf = new byte[TaskInterfaceConstants.TASK_FINISH_TIME_LIST_BUF_SIZE];
|
||
{
|
||
int copy = Mathf.Min(iFinishedTimeListLen, TaskInterfaceConstants.TASK_FINISH_TIME_LIST_BUF_SIZE);
|
||
if (copy > 0) System.Buffer.BlockCopy(pFinishedTimeListBuf, 0, m_pFinishedTimeListBuf, 0, copy);
|
||
}
|
||
|
||
m_pFinishedCountListBuf = new byte[TaskInterfaceConstants.TASK_FINISH_COUNT_LIST_BUF_SIZE];
|
||
{
|
||
int copy = Mathf.Min(iFinishedCountListLen, TaskInterfaceConstants.TASK_FINISH_COUNT_LIST_BUF_SIZE);
|
||
if (copy > 0) System.Buffer.BlockCopy(pFinishedCountListBuf, 0, m_pFinishedCountListBuf, 0, copy);
|
||
}
|
||
|
||
m_pStorageTaskListBuf = new byte[TaskInterfaceConstants.TASK_STORAGE_LIST_BUF_SIZE];
|
||
{
|
||
int copy = Mathf.Min(iStorageTaskListLen, TaskInterfaceConstants.TASK_STORAGE_LIST_BUF_SIZE);
|
||
if (copy > 0) System.Buffer.BlockCopy(pStorageTaskListBuf, 0, m_pStorageTaskListBuf, 0, copy);
|
||
}
|
||
|
||
// Clear rest buffer // 清理剩余缓冲区
|
||
// No-op in C# because arrays are zero-initialized.
|
||
|
||
ATaskTemplMan pTaskMan = GetTaskTemplMan();
|
||
pTaskMan.Release();
|
||
|
||
#if UNITY_EDITOR
|
||
if (TaskTest.Instance &&
|
||
TaskTest.Instance.WasLoadTaskData &&
|
||
pTaskMan.TaskLoadedCount > 100)
|
||
{
|
||
Debug.Log($" [TaskInterface] Using TaskTest loaded data with {pTaskMan.TaskLoadedCount} tasks.");
|
||
}
|
||
else
|
||
{
|
||
string task_data_path = Path.Combine(Application.streamingAssetsPath, "data/tasks.data");
|
||
pTaskMan.LoadTasksFromPack(task_data_path, true);
|
||
}
|
||
#else
|
||
string task_data_path = Path.Combine(Application.streamingAssetsPath, "data/tasks.data");
|
||
pTaskMan.LoadTasksFromPack(task_data_path, true);
|
||
#endif
|
||
|
||
pTaskMan.LoadNPCInfoFromPack("data\\task_npc.data");
|
||
pTaskMan.VerifyDynTasksPack("userdata\\dyn_tasks.data");
|
||
InitActiveTaskList();
|
||
|
||
m_bForceNavigateFinish = false;
|
||
|
||
return true;
|
||
}
|
||
|
||
public void CheckPQEnterWorldInit()
|
||
{
|
||
return;
|
||
ActiveTaskList pList = GetActiveTaskList();
|
||
List<ActiveTaskEntry> aEntries = new List<ActiveTaskEntry>(pList.m_TaskEntries);
|
||
|
||
for(var i = 0; i < pList.m_uTaskCount; i++)
|
||
{
|
||
var CurEntry = aEntries[i];
|
||
|
||
if (CurEntry.m_ulTemplAddr == 0)
|
||
continue;
|
||
|
||
ATaskTempl pTempl = CurEntry.GetTempl();
|
||
if (pTempl == null || !pTempl.m_FixedData.m_bPQTask)
|
||
continue;
|
||
|
||
pTempl.IncValidCount();
|
||
// _notify_svr(this, TASK_CLT_NOTIFY_PQ_CHECK_INIT, CurEntry.m_ID);
|
||
}
|
||
}
|
||
|
||
public static void WriteLog(int nPlayerId, int nTaskId, int nType, string szLog)
|
||
{
|
||
//do something?
|
||
}
|
||
|
||
public bool IsDeliverLegal()
|
||
{
|
||
// return !m_pHost.IsTrading() && m_pHost.GetBoothState() == 0 && !m_pHost.IsDead();
|
||
return true;
|
||
// TODO: implement
|
||
return m_pHost.IsTrading() && m_pHost.GetBoothState() == 0 && !m_pHost.IsDead();
|
||
}
|
||
|
||
public int GetCommonItemCount(uint ulCommonItem)
|
||
{
|
||
// CECInventory pPack = m_pHost.GetPack();
|
||
// return pPack != null ? pPack.GetItemTotalNum((int)ulCommonItem) : 0;
|
||
|
||
var inv = m_pHost?.GetInventory(InventoryConst.IVTRTYPE_PACK);
|
||
return inv != null ? inv.GetItemTotalNum((int)ulCommonItem) : 0;
|
||
}
|
||
|
||
public int GetTaskItemCount(uint ulTaskItem)
|
||
{
|
||
// CECInventory* pPack = m_pHost.GetTaskPack();
|
||
// return pPack ? pPack.GetItemTotalNum((int)ulTaskItem) : 0;
|
||
|
||
var inv = m_pHost?.GetInventory(InventoryConst.IVTRTYPE_TASKPACK);
|
||
return inv != null ? inv.GetItemTotalNum((int)ulTaskItem) : 0;
|
||
}
|
||
|
||
public ATaskTemplMan GetTaskTemplMan()
|
||
{
|
||
return EC_Game.GetTaskTemplateMan();
|
||
}
|
||
public ActiveTaskList GetActiveTaskList()
|
||
{
|
||
return m_pActiveListBuf;
|
||
}
|
||
|
||
private void InitActiveTaskList()
|
||
{
|
||
ActiveTaskList pLst = GetActiveTaskList();
|
||
if (pLst == null) return;
|
||
|
||
ATaskTemplMan pMan = GetTaskTemplMan();
|
||
if (pMan == null) return;
|
||
|
||
// reset counters
|
||
pLst.m_uTopShowTaskCount = 0;
|
||
pLst.m_uTopHideTaskCount = 0;
|
||
pLst.m_uTitleTaskCount = 0;
|
||
|
||
byte i = 0;
|
||
while (i < pLst.m_uTaskCount)
|
||
{
|
||
ActiveTaskEntry entry = pLst.m_TaskEntries[i];
|
||
if (entry == null)
|
||
{
|
||
i++;
|
||
continue;
|
||
}
|
||
|
||
// repair sibling linkage
|
||
if (entry.m_NextSblIndex != (char)0xff)
|
||
{
|
||
ActiveTaskEntry entryNextSbl = pLst.m_TaskEntries[entry.m_NextSblIndex];
|
||
if (entryNextSbl == null || entryNextSbl.m_PrevSblIndex != (char)i)
|
||
{
|
||
entry.m_NextSblIndex = (char)0xff;
|
||
}
|
||
}
|
||
|
||
// resolve template for top-level entries; children left unresolved in C#
|
||
if (entry.m_ParentIndex == (char)0xff)
|
||
{
|
||
// entry.m_ulTemplAddr = 0u;
|
||
entry.m_ulTemplAddr = pMan.GetTopTaskByID(entry.m_ID) != null ? 1u : 0u;
|
||
|
||
ATaskTempl topTempl = pMan.GetTopTaskByID(entry.m_ID);
|
||
if (topTempl != null)
|
||
{
|
||
if (topTempl.m_FixedData.m_bHidden)
|
||
pLst.m_uTopHideTaskCount++;
|
||
else if (topTempl.m_FixedData.m_bDisplayInTitleTaskUI)
|
||
pLst.m_uTitleTaskCount++;
|
||
else
|
||
pLst.m_uTopShowTaskCount++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
entry.m_ulTemplAddr = 0u;
|
||
}
|
||
|
||
// cap template best-effort (no pointer in managed)
|
||
if (entry.m_uCapTaskId != 0)
|
||
{
|
||
ATaskTempl cap = pMan.GetTopTaskByID(entry.m_uCapTaskId);
|
||
entry.m_ulCapTemplAddr = 0u;
|
||
if (cap == null)
|
||
{
|
||
entry.m_uCapTaskId = 0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
entry.m_ulCapTemplAddr = 0u;
|
||
}
|
||
|
||
i++;
|
||
}
|
||
|
||
// approximate used count
|
||
pLst.m_uUsedCount = pLst.m_uTaskCount;
|
||
}
|
||
|
||
public bool CheckTaskForbid(uint task_id){ return false; }
|
||
|
||
public bool IsAtCrossServer()
|
||
{
|
||
// TODO: cross server
|
||
// return CECCrossServer.Instance().IsOnSpecialServer();
|
||
return false;
|
||
}
|
||
|
||
public uint GetPlayerLevel()
|
||
{
|
||
return (uint)m_pHost.GetBasicProps().iLevel;
|
||
}
|
||
|
||
public uint GetGoldNum()
|
||
{
|
||
return (uint)m_pHost.GetMoneyAmount();
|
||
}
|
||
|
||
public int GetGlobalValue(int lKey)
|
||
{
|
||
return EC_Game.GetGameRun().GetCommonData(lKey);
|
||
}
|
||
// C++: long CECTaskInterface::GetGlobalValue(long lKey)
|
||
public long GetGlobalValue(long key)
|
||
{
|
||
// NOTE: Engine exposes only int common data; cast to long
|
||
return EC_Game.GetGameRun().GetCommonData((int)key);
|
||
}
|
||
|
||
public byte GetShapeMask()
|
||
{
|
||
return m_pHost.GetShapeMask();
|
||
}
|
||
|
||
public int GetPos(float[] pos)
|
||
{
|
||
A3DVECTOR3 vPos = m_pHost.GetPos();
|
||
if (pos != null && pos.Length >= 3)
|
||
{
|
||
pos[0] = vPos.x;
|
||
pos[1] = vPos.y;
|
||
pos[2] = vPos.z;
|
||
}
|
||
var world = World.CECWorld.Instance;
|
||
//TODO: world.GetInstanceID()
|
||
return world != null ? 0 /*world.GetInstanceID()*/ : 0;
|
||
}
|
||
|
||
public bool CheckSimpleTaskFinshConditon(uint task_id)
|
||
{
|
||
ATaskTempl pTempl = GetTaskTemplMan().GetTaskTemplByID(task_id);
|
||
if (pTempl == null) return false;
|
||
|
||
if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTask && pTempl.m_FixedData.m_uiEmotion != 0)
|
||
{
|
||
if (m_emotionTask != null && m_emotionTask.TryGetValue(task_id, out bool finished))
|
||
return finished;
|
||
return false;
|
||
}
|
||
else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTaskForceNavi)
|
||
{
|
||
return GetForceNavigateFinishFlag();
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public int GetFactionConsumeContrib()
|
||
{
|
||
return m_pHost.GetContribInfo().consume_contrib;
|
||
}
|
||
|
||
public int GetFactionExpContrib()
|
||
{
|
||
return m_pHost.GetContribInfo().exp_contrib;
|
||
}
|
||
|
||
public bool HasTask(uint ulTaskId)
|
||
{
|
||
ActiveTaskList pLst = GetActiveTaskList();
|
||
if (pLst == null) return false;
|
||
for (int i = 0; i < pLst.m_uTaskCount; i++)
|
||
{
|
||
ActiveTaskEntry entry = pLst.m_TaskEntries[i];
|
||
if ((uint)entry.m_ID == ulTaskId && entry.GetTempl() != null)
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// ===== Additional TaskInterface methods ported from C++ =====
|
||
public uint GetMaxHistoryLevel()
|
||
{
|
||
// TODO: Use reincarnation tome when available (GetReincarnationTome().max_level)
|
||
return (uint)m_pHost.GetBasicProps().iLevel;
|
||
}
|
||
|
||
public uint GetReincarnationCount()
|
||
{
|
||
// TODO: Hook to host reincarnation count when available
|
||
return 0u;
|
||
}
|
||
|
||
public bool IsRealmExpFull()
|
||
{
|
||
// TODO: Implement via host API when available
|
||
return false;
|
||
}
|
||
|
||
public uint GetReputation()
|
||
{
|
||
// TODO: Expose reputation on host; return 0 for now
|
||
return 0u;
|
||
}
|
||
|
||
public int GetFactionRole()
|
||
{
|
||
// TODO: Expose faction role id on host
|
||
return 0;
|
||
}
|
||
|
||
public bool IsInFaction(uint factionId)
|
||
{
|
||
// TODO: Expose faction id on host; cannot verify now
|
||
return false;
|
||
}
|
||
|
||
public bool IsMale()
|
||
{
|
||
return m_pHost.m_iGender == GENDER.GENDER_MALE;
|
||
}
|
||
|
||
public uint GetPlayerOccupation()
|
||
{
|
||
return (uint)m_pHost.m_iProfession;
|
||
}
|
||
|
||
public uint GetCurPeriod()
|
||
{
|
||
// Maps to "second level" in basic props (realm level)
|
||
return (uint)m_pHost.GetBasicProps().iLevel2;
|
||
}
|
||
|
||
public bool IsGM()
|
||
{
|
||
// TODO: Expose GM flag on host
|
||
return false;
|
||
}
|
||
|
||
public bool IsShieldUser()
|
||
{
|
||
// TODO: Expose ShieldUser flag on host
|
||
return false;
|
||
}
|
||
|
||
public bool IsMarried()
|
||
{
|
||
// TODO: Expose spouse id on host
|
||
return false;
|
||
}
|
||
|
||
public bool IsWeddingOwner()
|
||
{
|
||
// TODO: Expose wedding scene info and compare with host id
|
||
return false;
|
||
}
|
||
|
||
public uint GetInvEmptySlot()
|
||
{
|
||
var inv = m_pHost?.GetInventory(InventoryConst.IVTRTYPE_PACK);
|
||
return inv != null ? (uint)inv.GetEmptySlotNum() : 0u;
|
||
}
|
||
|
||
public int GetFactionContrib()
|
||
{
|
||
return m_pHost.GetContribInfo().cumulate_contrib;
|
||
}
|
||
|
||
public int GetForce()
|
||
{
|
||
// TODO: Expose force id on host
|
||
return 0;
|
||
}
|
||
|
||
public int GetForceReputation()
|
||
{
|
||
// TODO: Expose force reputation on host
|
||
return 0;
|
||
}
|
||
|
||
public int GetForceContribution()
|
||
{
|
||
// TODO: Expose force contribution on host
|
||
return 0;
|
||
}
|
||
|
||
public int GetExp()
|
||
{
|
||
return m_pHost.GetBasicProps().iExp;
|
||
}
|
||
|
||
public int GetSP()
|
||
{
|
||
return m_pHost.GetBasicProps().iSP;
|
||
}
|
||
|
||
public int GetForceActivityLevel()
|
||
{
|
||
// TODO: Expose force activity level on host
|
||
return -1;
|
||
}
|
||
|
||
public bool IsKing()
|
||
{
|
||
// TODO: Expose king status on host
|
||
return false;
|
||
}
|
||
|
||
public bool IsInTeam()
|
||
{
|
||
// TODO: Implement team system and check membership
|
||
return false;
|
||
}
|
||
|
||
public uint GetAccountTotalCash()
|
||
{
|
||
// TODO: Expose account total cash on host/session
|
||
return 0u;
|
||
}
|
||
|
||
#if _TASK_CLIENT
|
||
// Prepare award preview based on task and state
|
||
public void GetTaskAwardPreview(uint ulTaskId, ref Task_Award_Preview p, bool bActiveTask=true)
|
||
{
|
||
// Zero and init output
|
||
p = default;
|
||
if (p.m_ItemsId == null) p.m_ItemsId = new uint[TaskInterfaceConstants.MAX_ITEM_AWARD];
|
||
if (p.m_ItemsNum == null) p.m_ItemsNum = new uint[TaskInterfaceConstants.MAX_ITEM_AWARD];
|
||
|
||
// Gather context
|
||
ActiveTaskList pLst = GetActiveTaskList();
|
||
uint ulCurTime = GetCurTime();
|
||
ATaskTempl pTempl = null;
|
||
AWARD_DATA ad = default;
|
||
uint ulMulti = 1u;
|
||
|
||
// Resolve template and dynamic award when active
|
||
if (bActiveTask && pLst != null)
|
||
{
|
||
for (int i = 0; i < pLst.m_uTaskCount; i++)
|
||
{
|
||
ActiveTaskEntry CurEntry = pLst.m_TaskEntries[i];
|
||
if (CurEntry.m_ID != ulTaskId || CurEntry.m_ulTemplAddr == 0) continue;
|
||
|
||
pTempl = CurEntry.GetTempl();
|
||
|
||
// TODO: CalcAwardData/CalcAwardMulti not implemented yet in C#; use fixed success award and multiplier 1
|
||
if (pTempl != null)
|
||
{
|
||
ad = pTempl.m_FixedData.m_Award_S;
|
||
ulMulti = 1u;
|
||
}
|
||
|
||
if (ulMulti == 0u) return;
|
||
break;
|
||
}
|
||
}
|
||
// Fallback to top template when inactive
|
||
else
|
||
{
|
||
pTempl = GetTaskTemplMan().GetTopTaskByID(ulTaskId);
|
||
if (pTempl == null) return;
|
||
ad = pTempl.m_FixedData.m_Award_S;
|
||
}
|
||
|
||
// Fill basic award fields
|
||
unchecked
|
||
{
|
||
p.m_ulGold = ad.m_ulGoldNum * ulMulti;
|
||
p.m_ulExp = ad.m_ulExp * ulMulti;
|
||
p.m_ulSP = ad.m_ulSP * ulMulti;
|
||
}
|
||
p.m_iForceActivity = ad.m_iForceActivity;
|
||
p.m_iForceContrib = ad.m_iForceContribution;
|
||
p.m_iForceRepu = ad.m_iForceReputation;
|
||
p.m_ulRealmExp = ad.m_ulRealmExp;
|
||
|
||
// Apply level coefficient if configured (coefficient table not available; skip scaling)
|
||
if (ad.m_bUseLevCo)
|
||
{
|
||
uint ulLev = GetPlayerLevel();
|
||
if (ulLev == 0) ulLev = 1;
|
||
|
||
uint ulUpper = 0;
|
||
if (pTempl != null && pTempl.GetTopTask() != null)
|
||
ulUpper = pTempl.GetTopTask().m_FixedData.m_ulPremise_Lev_Max;
|
||
if (ulUpper != 0 && ulLev > ulUpper) ulLev = ulUpper;
|
||
|
||
// NOTE: Original code multiplies by _lev_co[ulLev-1]. Not available here; keep as-is.
|
||
}
|
||
|
||
// Candidate items handling
|
||
if (ad.m_ulCandItems == 1 && ad.m_CandItems != null && ad.m_CandItems.Length > 0)
|
||
{
|
||
p.m_bHasItem = true;
|
||
p.m_bItemKnown = true;
|
||
|
||
AWARD_ITEMS_CAND ic = ad.m_CandItems[0];
|
||
if (ic.m_bRandChoose)
|
||
{
|
||
p.m_bItemKnown = false;
|
||
}
|
||
else
|
||
{
|
||
for (int j = 0; j < ic.m_ulAwardItems; j++)
|
||
{
|
||
ITEM_WANTED wi = ic.m_AwardItems[j];
|
||
if (!wi.m_bCommonItem) continue;
|
||
else if (wi.m_fProb != 1.0f)
|
||
{
|
||
p.m_bItemKnown = false;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
// Period conversion not implemented; assume valid
|
||
if (p.m_ulItemTypes < TaskInterfaceConstants.MAX_ITEM_AWARD)
|
||
{
|
||
p.m_ItemsId[p.m_ulItemTypes] = wi.m_ulItemTemplId;
|
||
p.m_ItemsNum[p.m_ulItemTypes] = wi.m_ulItemNum;
|
||
p.m_ulItemTypes++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (ad.m_ulCandItems > 1)
|
||
{
|
||
p.m_bHasItem = true;
|
||
}
|
||
|
||
// Done
|
||
return;
|
||
}
|
||
|
||
public uint GetTaskCount()
|
||
{
|
||
ActiveTaskList pLst = GetActiveTaskList();
|
||
uint ulCount = 0;
|
||
|
||
if (pLst == null) return 0u;
|
||
|
||
for (int i = 0; i < pLst.m_uTaskCount; i++)
|
||
{
|
||
ActiveTaskEntry CurEntry = pLst.m_TaskEntries[i];
|
||
ATaskTempl pTempl = CurEntry.GetTempl();
|
||
|
||
if (pTempl != null
|
||
&& !pTempl.m_FixedData.m_bDisplayInTitleTaskUI
|
||
&& CurEntry.m_ParentIndex == (char)0xff)
|
||
{
|
||
if (!pTempl.m_FixedData.m_bHidden || pTempl.m_FixedData.m_bShowPrompt)
|
||
{
|
||
ulCount++;
|
||
}
|
||
}
|
||
}
|
||
|
||
return ulCount;
|
||
}
|
||
|
||
public uint GetTaskId(uint ulIndex)
|
||
{
|
||
ActiveTaskList pLst = GetActiveTaskList();
|
||
byte uTopCount = 0;
|
||
int uCount = 0;
|
||
if (pLst == null) return 0u;
|
||
|
||
while (uCount < pLst.m_uTaskCount)
|
||
{
|
||
ActiveTaskEntry CurEntry = pLst.m_TaskEntries[uCount];
|
||
ATaskTempl pTempl = CurEntry.GetTempl();
|
||
|
||
if (pTempl != null
|
||
&& !pTempl.m_FixedData.m_bDisplayInTitleTaskUI
|
||
&& CurEntry.m_ParentIndex == (char)0xff)
|
||
{
|
||
if (!pTempl.m_FixedData.m_bHidden || pTempl.m_FixedData.m_bShowPrompt)
|
||
{
|
||
if (ulIndex == uTopCount)
|
||
return CurEntry.m_ID;
|
||
else
|
||
uTopCount++;
|
||
}
|
||
}
|
||
|
||
uCount++;
|
||
}
|
||
|
||
return 0u;
|
||
}
|
||
|
||
public uint CanDeliverTask(uint ulTaskId)
|
||
{
|
||
ATaskTempl pTempl = GetTaskTemplMan().GetTopTaskByID(ulTaskId);
|
||
if (pTempl == null) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_NO_TASK;
|
||
|
||
if (!IsDeliverLegal()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_INDETERMINATE;
|
||
|
||
// return pTempl.CheckPrerequisite(this, static_cast<ActiveTaskList*>(GetActiveTaskList()), GetCurTime(), true, true, false);
|
||
return pTempl.CheckPrerequisite(this, GetActiveTaskList(), GetCurTime(), true, true, false);
|
||
|
||
// if (!pTempl.CheckReachLevel(this)) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_BELOW_LEVEL;
|
||
// uint keyCheck = pTempl.CheckGlobalKeyValue(this, false);
|
||
// if (keyCheck != 0u) return keyCheck;
|
||
|
||
return 0u;
|
||
}
|
||
|
||
public void ShowPunchBagMessage(bool bSucced,bool bMax,uint MonsterTemplID,int dps,int dph)
|
||
{
|
||
// TODO : implement UI message box
|
||
|
||
// CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan();
|
||
//
|
||
// if (pGameUI == NULL) return;
|
||
//
|
||
// elementdataman *pDataMan = g_pGame->GetElementDataMan();
|
||
//
|
||
// DATA_TYPE dt;
|
||
// MONSTER_ESSENCE *pMonster = (MONSTER_ESSENCE *)pDataMan->get_data_ptr(MonsterTemplID, ID_SPACE_ESSENCE, dt);
|
||
//
|
||
// ACString strNpcName;
|
||
// if( dt == DT_MONSTER_ESSENCE )
|
||
// {
|
||
// if( pMonster)
|
||
// strNpcName = pMonster->name;
|
||
// }
|
||
//
|
||
// ACString str;
|
||
// if (!bSucced)
|
||
// {
|
||
// str.Format(pGameUI->GetStringFromTable(303),strNpcName);
|
||
// pGameUI->MessageBox("",str,MB_OK,A3DCOLORRGBA(255, 255, 255, 160));
|
||
// }
|
||
//
|
||
// else if (bMax)
|
||
// {
|
||
// str.Format(pGameUI->GetStringFromTable(304),dph);
|
||
// pGameUI->MessageBox("",str,MB_OK,A3DCOLORRGBA(255, 255, 255, 160));
|
||
// }
|
||
// else
|
||
// {
|
||
// str.Format(pGameUI->GetStringFromTable(305),dph);
|
||
// pGameUI->MessageBox("",str,MB_OK,A3DCOLORRGBA(255, 255, 255, 160));
|
||
// }
|
||
|
||
}
|
||
#endif
|
||
|
||
|
||
private bool GetForceNavigateFinishFlag()
|
||
{
|
||
return m_bForceNavigateFinish;
|
||
}
|
||
|
||
public void GetTaskStateInfo(uint ulTaskId, ref Task_State_info pInfo, bool bActiveTask=true)
|
||
{
|
||
// 清零并准备输出结构 // Zero and prepare output struct
|
||
pInfo = default;
|
||
if (pInfo.m_MonsterWanted == null)
|
||
pInfo.m_MonsterWanted = new Task_State_info.m_MonsterWanted_s[TaskInterfaceConstants.MAX_MONSTER_WANTED];
|
||
if (pInfo.m_ItemsWanted == null)
|
||
pInfo.m_ItemsWanted = new Task_State_info.m_ItemsWanted_s[TaskInterfaceConstants.MAX_ITEM_WANTED];
|
||
if (pInfo.m_PlayerWanted == null)
|
||
pInfo.m_PlayerWanted = new Task_State_info.TASK_INFO_PLAYER[TaskInterfaceConstants.MAX_PLAYER_WANTED];
|
||
|
||
ActiveTaskList pLst = GetActiveTaskList();
|
||
uint ulCurTime = GetCurTime(); // 当前时间 // current time
|
||
ATaskTempl pTempl = null;
|
||
ActiveTaskEntry foundEntry = default;
|
||
bool hasFoundEntry = false;
|
||
|
||
if (bActiveTask)
|
||
{
|
||
// 在激活任务列表中查找 // Search in active task list
|
||
for (int i = 0; i < pLst.m_uTaskCount; i++)
|
||
{
|
||
ActiveTaskEntry CurEntry = pLst.m_TaskEntries[i];
|
||
if (CurEntry.m_ID != ulTaskId || CurEntry.m_ulTemplAddr == 0) continue;
|
||
|
||
pTempl = CurEntry.GetTempl();
|
||
foundEntry = CurEntry;
|
||
hasFoundEntry = true;
|
||
|
||
// 检查任务是否可以完成 // Check if task can be completed
|
||
if (pTempl != null && pTempl.CanFinishTask(this, CurEntry, ulCurTime))
|
||
{
|
||
pInfo.m_ulErrCode = pTempl.RecursiveCheckAward(this, pLst, CurEntry, ulCurTime, -1);
|
||
if (pInfo.m_ulErrCode == TaskInterfaceConstants.TASK_AWARD_FAIL_LEVEL_CHECK)
|
||
{
|
||
ATaskTempl pParent = pTempl;
|
||
while (pParent != null && pParent.m_FixedData.m_ulPremise_Lev_Min == 0)
|
||
pParent = pParent.m_pParent;
|
||
if (pParent != null)
|
||
pInfo.m_ulPremLevelMin = pParent.m_FixedData.m_ulPremise_Lev_Min;
|
||
}
|
||
}
|
||
|
||
pInfo.m_ulTimePassed = ulCurTime > CurEntry.m_ulTaskTime ? (ulCurTime - CurEntry.m_ulTaskTime) : 0;
|
||
|
||
if (pTempl != null && pTempl.m_FixedData.m_ulPremise_Lev_Min != 0)
|
||
{
|
||
if (pTempl.m_FixedData.m_bPremCheckMaxHistoryLevel != 0 && GetPlayerLevel() < pTempl.m_FixedData.m_ulPremise_Lev_Min)
|
||
{
|
||
pInfo.m_ulErrCode = TaskInterfaceConstants.TASK_AWARD_FAIL_LEVEL_CHECK;
|
||
pInfo.m_ulPremLevelMin = pTempl.m_FixedData.m_ulPremise_Lev_Min;
|
||
}
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pTempl = GetTaskTemplMan().GetTopTaskByID(ulTaskId);
|
||
}
|
||
|
||
if (pTempl == null)
|
||
return;
|
||
|
||
// 基本任务要求 // Basic task requirements
|
||
if (pTempl.m_FixedData.m_ulTimeLimit != 0) pInfo.m_ulTimeLimit = pTempl.m_FixedData.m_ulTimeLimit;
|
||
if (pTempl.m_FixedData.m_ulGoldWanted != 0) pInfo.m_ulGoldWanted = pTempl.m_FixedData.m_ulGoldWanted;
|
||
|
||
// 任务类型分支 // Task method branches
|
||
if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMCollectNumArticle)
|
||
{
|
||
for (int j = 0; j < pTempl.m_FixedData.m_ulItemsWanted; j++)
|
||
{
|
||
var iw = pTempl.m_FixedData.m_ItemsWanted[j];
|
||
pInfo.m_ItemsWanted[j].m_ulItemId = iw.m_ulItemTemplId;
|
||
pInfo.m_ItemsWanted[j].m_ulItemsToGet = iw.m_ulItemNum;
|
||
pInfo.m_ItemsWanted[j].m_ulItemsGained = ATaskTempl._get_item_count(this, iw.m_ulItemTemplId, iw.m_bCommonItem);
|
||
}
|
||
}
|
||
else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMKillNumMonster)
|
||
{
|
||
int ulItemCount = 0;
|
||
int ulMonsterCount = 0;
|
||
|
||
for (int j = 0; j < pTempl.m_FixedData.m_ulMonsterWanted; j++)
|
||
{
|
||
var mw = pTempl.m_FixedData.m_MonsterWanted[j];
|
||
|
||
if (mw.m_ulDropItemId != 0)
|
||
{
|
||
pInfo.m_ItemsWanted[ulItemCount].m_ulMonsterId = mw.m_ulMonsterTemplId;
|
||
pInfo.m_ItemsWanted[ulItemCount].m_ulItemId = mw.m_ulDropItemId;
|
||
pInfo.m_ItemsWanted[ulItemCount].m_ulItemsToGet = mw.m_ulDropItemCount;
|
||
pInfo.m_ItemsWanted[ulItemCount].m_ulItemsGained = ATaskTempl._get_item_count(this, mw.m_ulDropItemId, mw.m_bDropCmnItem);
|
||
ulItemCount++;
|
||
}
|
||
else
|
||
{
|
||
pInfo.m_MonsterWanted[ulMonsterCount].m_ulMonsterId = mw.m_ulMonsterTemplId;
|
||
pInfo.m_MonsterWanted[ulMonsterCount].m_ulMonstersToKill = mw.m_ulMonsterNum;
|
||
|
||
if (bActiveTask && hasFoundEntry)
|
||
{
|
||
pInfo.m_MonsterWanted[ulMonsterCount].m_ulMonstersKilled = foundEntry.m_wMonsterNum[j];
|
||
}
|
||
|
||
ulMonsterCount++;
|
||
}
|
||
}
|
||
}
|
||
else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMKillPlayer)
|
||
{
|
||
int ulItemCount = 0;
|
||
int ulPlayerCount = 0;
|
||
|
||
for (int j = 0; j < pTempl.m_FixedData.m_ulPlayerWanted; j++)
|
||
{
|
||
var pw = pTempl.m_FixedData.m_PlayerWanted[j];
|
||
|
||
if (pw.m_ulDropItemId != 0)
|
||
{
|
||
pInfo.m_ItemsWanted[ulItemCount].m_ulItemId = pw.m_ulDropItemId;
|
||
pInfo.m_ItemsWanted[ulItemCount].m_ulItemsToGet = pw.m_ulDropItemCount;
|
||
pInfo.m_ItemsWanted[ulItemCount].m_ulItemsGained = ATaskTempl._get_item_count(this, pw.m_ulDropItemId, pw.m_bDropCmnItem);
|
||
ulItemCount++;
|
||
}
|
||
else
|
||
{
|
||
pInfo.m_PlayerWanted[ulPlayerCount].m_ulPlayersToKill = pw.m_ulPlayerNum;
|
||
|
||
if (bActiveTask && hasFoundEntry)
|
||
{
|
||
pInfo.m_PlayerWanted[ulPlayerCount].m_ulPlayersKilled = foundEntry.m_wMonsterNum[j];
|
||
}
|
||
|
||
pInfo.m_PlayerWanted[ulPlayerCount].m_Requirements = pw.m_Requirements;
|
||
|
||
ulPlayerCount++;
|
||
}
|
||
}
|
||
}
|
||
else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMProtectNPC)
|
||
{
|
||
pInfo.m_ulNPCToProtect = pTempl.m_FixedData.m_ulNPCToProtect;
|
||
pInfo.m_ulProtectTime = pTempl.m_FixedData.m_ulProtectTimeLen;
|
||
}
|
||
else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMWaitTime)
|
||
{
|
||
pInfo.m_ulWaitTime = pTempl.m_FixedData.m_ulWaitTime;
|
||
}
|
||
else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMGlobalValOK)
|
||
{
|
||
pTempl.GetGlobalTaskChar(this, pInfo.m_TaskCharArr);
|
||
}
|
||
else if (pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMReachLevel)
|
||
{
|
||
pInfo.m_ulReachLevel = pTempl.m_FixedData.m_ulReachLevel;
|
||
pInfo.m_ulReachReincarnation = pTempl.m_FixedData.m_ulReachReincarnationCount;
|
||
pInfo.m_ulReachRealm = pTempl.m_FixedData.m_ulReachRealmLevel;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
public uint GetCurTime()
|
||
{
|
||
// use this to avoid task hack by changing the system time
|
||
return (uint)EC_Game.GetServerAbsTime();
|
||
}
|
||
|
||
private const string SYMBOL_HOSTNAME = "$name";
|
||
|
||
public string FormatTaskTalk(string taskTalk)
|
||
{
|
||
string ret = taskTalk ?? string.Empty;
|
||
if (taskTalk == null) return ret;
|
||
|
||
string strName = m_pHost.GetName(); // assumes string; use ToString() if needed
|
||
return ret.Replace(SYMBOL_HOSTNAME, $"&{strName}&");
|
||
}
|
||
|
||
public bool GetAwardCandidates(uint ulTaskId, ref AWARD_DATA pAward)
|
||
{
|
||
ActiveTaskList pLst = GetActiveTaskList() as ActiveTaskList;
|
||
ActiveTaskEntry pEntry = pLst.GetEntry(ulTaskId);
|
||
if (pEntry == null || pEntry.m_ulTemplAddr == 0) return false;
|
||
|
||
uint ulCurTime = GetCurTime();
|
||
pEntry.GetTempl().CalcAwardData(
|
||
this,
|
||
ref pAward,
|
||
pEntry,
|
||
pEntry.m_ulTaskTime,
|
||
ulCurTime);
|
||
|
||
return true;
|
||
}
|
||
|
||
public uint GetTaskFinishedTime(uint value) { return 0; }
|
||
|
||
bool IsCaptain()
|
||
{
|
||
// TO DO: fix later
|
||
//CECTeam pTeam = m_pHost.GetTeam();
|
||
//if (!pTeam)
|
||
// return false;
|
||
|
||
//return pTeam.GetLeaderID() == m_pHost.GetCharacterID();
|
||
|
||
return true;
|
||
}
|
||
|
||
public bool CanFinishTask(uint ulTaskId)
|
||
{
|
||
ActiveTaskEntry pEntry = (GetActiveTaskList() as ActiveTaskList).GetEntry(ulTaskId);
|
||
|
||
if (pEntry == null)
|
||
return false;
|
||
|
||
ATaskTempl pTempl = pEntry.GetTempl();
|
||
|
||
if (pTempl == null)
|
||
return false;
|
||
|
||
if (pTempl.m_FixedData.m_bMarriage && !IsCaptain())
|
||
return false;
|
||
|
||
return pTempl.CanFinishTask(this, pEntry, GetCurTime());
|
||
}
|
||
|
||
public bool CanShowTask(uint ulTaskId)
|
||
{
|
||
ATaskTempl pTempl = GetTaskTemplMan().GetTopTaskByID(ulTaskId);
|
||
return pTempl != null && pTempl.CanShowTask(this);
|
||
}
|
||
|
||
public void SetFinishDlgShowTime(int t) { m_tmFinishDlgShown = t; }
|
||
|
||
public void OnUIDialogEnd(uint ulTask)
|
||
{
|
||
SetFinishDlgShowTime(0);
|
||
ActiveTaskList pLst = GetActiveTaskList() as ActiveTaskList;
|
||
ActiveTaskEntry pEntry = pLst.GetEntry(ulTask);
|
||
if (pEntry == null || pEntry.m_ulTemplAddr == 0) return;
|
||
//ATaskTempl pTempl = (pEntry.m_ulTemplAddr) as ATaskTempl;
|
||
ATaskTempl pTempl = GetTaskTemplMan().GetTaskTemplByID(pEntry.m_ulTemplAddr);
|
||
|
||
switch (pTempl.m_FixedData.m_enumMethod)
|
||
{
|
||
case (uint)TaskCompletionMethod.enumTMReachSite:
|
||
pTempl.IncValidCount();
|
||
_notify_svr(this, 3, (ushort)ulTask); //TASK_CLT_NOTIFY_REACH_SITE = 3
|
||
break;
|
||
}
|
||
}
|
||
|
||
public void GiveUpTask(uint ulTaskId)
|
||
{
|
||
ActiveTaskEntry pEntry = (GetActiveTaskList() as ActiveTaskList).GetEntry(ulTaskId);
|
||
if (pEntry == null || pEntry.GetTempl() == null) return;
|
||
_notify_svr(this, 2, (ushort)(pEntry.GetTempl().GetTopTask().GetID())); //TASK_CLT_NOTIFY_CHECK_GIVEUP = 2
|
||
}
|
||
|
||
void _notify_svr(TaskInterface pTask, byte uReason, ushort uTaskID)
|
||
{
|
||
|
||
}
|
||
|
||
public bool IsTaskReadyToConfirm(int iTaskID)
|
||
{
|
||
if (m_TasksToConfirm == null) return false;
|
||
bool ret;
|
||
if (m_TasksToConfirm.TryGetValue(iTaskID, out ret)) return ret;
|
||
return false;
|
||
}
|
||
|
||
public void NotifyServer(ref task_notify_base pBuf, uint sz)
|
||
{
|
||
UnityGameSession.c2s_CmdTaskNotify(ref pBuf, sz);
|
||
}
|
||
|
||
public bool CheckVersion()
|
||
{
|
||
// return static_cast<ActiveTaskList*>(GetActiveTaskList())->m_Version == TASK_ENTRY_DATA_CUR_VER;
|
||
return GetActiveTaskList().m_Version == TaskTemplConstants.TASK_ENTRY_DATA_CUR_VER;
|
||
}
|
||
|
||
public StorageTaskList GetStorageTaskList()
|
||
{
|
||
StorageTaskList ret = new StorageTaskList();
|
||
ret.ReadByte(m_pStorageTaskListBuf);
|
||
return ret;
|
||
}
|
||
|
||
public uint GetTaskMask()
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
public byte[] GetFinishedTimeList()
|
||
{
|
||
return m_pFinishedTimeListBuf;
|
||
}
|
||
|
||
void SetForceNavigateFinishFlag(bool bFinish) { m_bForceNavigateFinish = bFinish;} //
|
||
public void OnNewTask(int iTaskID)
|
||
{
|
||
ATaskTempl pTempl = GetTaskTemplMan().GetTaskTemplByID((uint)iTaskID);
|
||
if (pTempl != null
|
||
&& pTempl.m_FixedData.m_enumMethod== (uint)TaskCompletionMethod.enumTMSimpleClientTaskForceNavi)
|
||
{
|
||
SetForceNavigateFinishFlag(false);
|
||
|
||
// TODO: trigger navigation event
|
||
// m_pHost.OnNaviageEvent(iTaskID,CECNavigateCtrl::EM_PREPARE);
|
||
}
|
||
}
|
||
|
||
public void OnTaskConfirmUpdate()
|
||
{
|
||
// TODO: update task confirm UI
|
||
// CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan();
|
||
// if (pGameUI) pGameUI->UpdateTaskConfirm();
|
||
}
|
||
|
||
public void UpdateConfirmTasksMap()
|
||
{
|
||
m_TasksToConfirm.Clear();
|
||
TaskClient.OnTaskCheckStatus(this);
|
||
OnTaskConfirmUpdate();
|
||
}
|
||
|
||
public void OnCompleteTask(int iTaskID)
|
||
{
|
||
ATaskTempl pTempl = GetTaskTemplMan().GetTaskTemplByID((uint)iTaskID);
|
||
if (pTempl != null &&
|
||
pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTaskForceNavi)
|
||
{
|
||
//TODO: trigger navigation end event
|
||
// m_pHost.OnNaviageEvent(iTaskID,CECNavigateCtrl::EM_END);
|
||
SetForceNavigateFinishFlag(false);
|
||
}
|
||
}
|
||
|
||
public void TakeAwayCommonItem(uint ulTemplId, uint ulNum) {}
|
||
|
||
public void TakeAwayTaskItem(uint ulTemplId, uint ulNum) {}
|
||
public void TakeAwayGold(uint ulNum) {}
|
||
public void TakeAwayFactionConsumeContrib(int ulNum){}
|
||
public void OnGiveupTask(int iTaskID)
|
||
{
|
||
ATaskTempl pTempl = GetTaskTemplMan().GetTaskTemplByID((uint)iTaskID);
|
||
if (pTempl != null &&
|
||
pTempl.m_FixedData.m_enumMethod == (uint)TaskCompletionMethod.enumTMSimpleClientTaskForceNavi)
|
||
{
|
||
// TODO: trigger navigation end event
|
||
// m_pHost.OnNaviageEvent(iTaskID,CECNavigateCtrl::EM_END);
|
||
SetForceNavigateFinishFlag(false);
|
||
}
|
||
}
|
||
|
||
public void UpdateTaskUI(uint idTask, int reason)
|
||
{
|
||
// TODO: update task UI
|
||
// CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan();
|
||
// if (pGameUI)
|
||
// {
|
||
// pGameUI->UpdateTask(idTask, reason);
|
||
// }
|
||
}
|
||
|
||
public bool IsTitleDataReady()
|
||
{
|
||
return m_pHost.IsTitleDataReady();
|
||
}
|
||
|
||
public FinishedTaskList GetFinishedTaskList()
|
||
{
|
||
FinishedTaskList ret = new FinishedTaskList();
|
||
ret.ReadFromBytes(m_pFinishedListBuf);
|
||
return ret;
|
||
}
|
||
|
||
public int GetPlayerId()
|
||
{
|
||
return m_pHost.GetCharacterID();
|
||
}
|
||
|
||
public void PopChatMessage(int iIndex,int dwNum=0)
|
||
{
|
||
switch((FixedMsg)iIndex)
|
||
{
|
||
case FixedMsg.FIXMSG_TASK_LIMIT_INCREASED:
|
||
// TODO: show chat message
|
||
// g_pGame->GetGameRun()->AddFixedChannelMsg(FIXMSG_TASK_LIMIT_INCREASED,GP_CHAT_SYSTEM);
|
||
// EC_Game.GetGameRun().AddFixedChannelMsg(FIXMSG_TASK_LIMIT_INCREASED,GP_CHAT_SYSTEM);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
}
|