using UnityEngine; using System.IO; using System.Runtime.InteropServices; using System; using BrewMonster; using CSNetwork.GPDataType; using ModelRenderer.Scripts.Common; using PerfectWorld.Scripts.Task; using UnityEngine.Serialization; using UnityEngine.UIElements; namespace BrewMonster.Scripts.Task { public class TaskTemplConstants { public const uint _task_templ_cur_version = 121; public const int MAX_TASK_NAME_LEN = 30; public const int MAX_AWARD_NPC_NUM = 8; public const int MAX_PREM_TASK_COUNT = 20; public const int MAX_MUTEX_TASK_COUNT = 5; public const int MAX_OCCUPATIONS = 12; // 职业 // Occupations public const int MAX_TEAM_MEM_WANTED = MAX_OCCUPATIONS; public const int MAX_TIMETABLE_SIZE = 24; public const int TASK_AWARD_MAX_DISPLAY_CHAR_LEN = 64; public const int MAX_ITEM_WANTED = 10; public const int MAX_AWARD_SCALES = 5; public const int MAX_AWARD_CANDIDATES = 12; public const int MAX_LIVING_SKILLS = 4; public const int MAX_CONTRIB_MONSTERS = 100; // PQ子任务贡献度最大怪物种类 // Maximum monster types for PQ subtask contribution public const int MAX_AWARD_PQ_RANKING = 32; // PQ子任务奖励最大排名数 // Maximum ranking count for PQ subtask rewards public const int MAX_TITLE_NUM = 10; public const int MAX_TASKREGION = 8; // 最大区域个数 // Maximum number of regions public const int TASK_GENDER_NONE = 0; public const int TASK_GENDER_MALE = 1; public const int TASK_GENDER_FEMALE = 2; public const int TASK_MAX_PATH = 260; public const uint INVALID_VAL = uint.MaxValue; public const int TASK_MAX_LINE_LEN = TASK_MAX_PATH; public const int TASK_MAX_VALID_COUNT = 6; public const int TASK_TREASURE_MAP_SIDE_MULTIPLE = 30; // 藏宝图边长与小区域边长的比 // Ratio of treasure map side length to small region side length public const int NUM_SPECIAL_AWARD = 2; public static readonly int[] TASK_SPECIAL_AWARD = new int[NUM_SPECIAL_AWARD] { 26969, 26970 }; public const uint TASK_PACK_MAGIC = 0x93858361; // Race-occupation mapping array public static readonly uint[] _race_occ_map = new uint[MAX_OCCUPATIONS]; /* * Server Notifications */ // 新任务发放 // New task issued public const int TASK_SVR_NOTIFY_NEW = 1; // 任务完毕 // Task completed public const int TASK_SVR_NOTIFY_COMPLETE = 2; // 任务放弃 // Task abandoned public const int TASK_SVR_NOTIFY_GIVE_UP = 3; // 杀怪数量 // Monster kill count public const int TASK_SVR_NOTIFY_MONSTER_KILLED = 4; // 处于得到奖励状态 // In reward receiving state public const int TASK_SVR_NOTIFY_FINISHED = 5; // 错误码 // Error code public const int TASK_SVR_NOTIFY_ERROR_CODE = 6; // 遗忘生活技能 // Forget life skill public const int TASK_SVR_NOTIFY_FORGET_SKILL = 7; // 动态任务时间标记 // Dynamic task time mark public const int TASK_SVR_NOTIFY_DYN_TIME_MARK = 8; // 动态任务数据 // Dynamic task data public const int TASK_SVR_NOTIFY_DYN_DATA = 9; // 特殊奖励信息 // Special reward info public const int TASK_SVR_NOTIFY_SPECIAL_AWARD = 10; // 仓库数据 // Storage data public const int TASK_SVR_NOTIFY_STORAGE = 11; // 显示全局变量 // Display global variables public const int TASK_SVR_NOTIFY_DIS_GLOBAL_VAL = 12; // 藏宝位置 // Treasure location public const int TASK_SVR_NOTIFY_TREASURE_MAP = 13; // 设置任务列表上限 // Set task list limit public const int TASK_SVR_NOTIFY_SET_TASK_LIMIT = 14; // 杀人数量 // Player kill count public const int TASK_SVR_NOTIFY_PLAYER_KILLED = 15; public const int TASK_ENTRY_DATA_CUR_VER = 1; public const int MAX_SUB_TAGS = 32; public const int TASK_STORAGE_COUNT = 32; public const int TASK_STORAGE_LEN = 10; public const int TASK_DEFAULT_MAX_SIMULTANEOUS_COUT = 20; public const int TASK_MAX_SIMULTANEOUS_COUT = 30; public const int TASK_HIDDEN_COUNT = 30; // formally 6, for test public const int TASK_TITLE_TASK_COUNT = 10 ; // 锟狡猴拷锟斤拷锟斤拷锟斤拷锟斤拷 } public enum DynTaskType { enumDTTNone = 0, enumDTTSpecialAward, enumDTTNormal, enumDTTGiftCard, } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct NPC_INFO { public uint id; // uint in C++ // uint in C++ public short x; public short y; public short z; //Add padding to because the c++ struct size is auto add 2 bytes padding if not have pragmapack. public byte padding1; // 1 byte padding to match C++ struct size (12 bytes total) // 1字节填充以匹配C++结构体大小(总共12字节) public byte padding2; // 1 byte padding to match C++ struct size (12 bytes total) // 1字节填充以匹配C++结构体大小(总共12字节) } // public class ServerNotificationConstants // { // // 新任务发放 // New task issued // public const int TASK_SVR_NOTIFY_NEW = 1; // // // 任务完毕 // Task completed // public const int TASK_SVR_NOTIFY_COMPLETE = 2; // // // 任务放弃 // Task abandoned // public const int TASK_SVR_NOTIFY_GIVE_UP = 3; // // // 杀怪数量 // Monster kill count // public const int TASK_SVR_NOTIFY_MONSTER_KILLED = 4; // // // 处于得到奖励状态 // In reward receiving state // public const int TASK_SVR_NOTIFY_FINISHED = 5; // // // 错误码 // Error code // public const int TASK_SVR_NOTIFY_ERROR_CODE = 6; // // // 遗忘生活技能 // Forget life skill // public const int TASK_SVR_NOTIFY_FORGET_SKILL = 7; // // // 动态任务时间标记 // Dynamic task time mark // public const int TASK_SVR_NOTIFY_DYN_TIME_MARK = 8; // // // 动态任务数据 // Dynamic task data // public const int TASK_SVR_NOTIFY_DYN_DATA = 9; // // // 特殊奖励信息 // Special reward info // public const int TASK_SVR_NOTIFY_SPECIAL_AWARD = 10; // // // 仓库数据 // Storage data // public const int TASK_SVR_NOTIFY_STORAGE = 11; // // // 显示全局变量 // Display global variables // public const int TASK_SVR_NOTIFY_DIS_GLOBAL_VAL = 12; // // // 藏宝位置 // Treasure location // public const int TASK_SVR_NOTIFY_TREASURE_MAP = 13; // // // 设置任务列表上限 // Set task list limit // public const int TASK_SVR_NOTIFY_SET_TASK_LIMIT = 14; // // // 杀人数量 // Player kill count // public const int TASK_SVR_NOTIFY_PLAYER_KILLED = 15; // } public class ClientNotificationConstants { // 检查完成 // Check completion public const int TASK_CLT_NOTIFY_CHECK_FINISH = 1; // 检查放弃 // Check abandonment public const int TASK_CLT_NOTIFY_CHECK_GIVEUP = 2; // 到达地点 // Reach location public const int TASK_CLT_NOTIFY_REACH_SITE = 3; // 自动交付 // Auto delivery public const int TASK_CLT_NOTIFY_AUTO_DELV = 4; // 手动触发 // Manual trigger public const int TASK_CLT_NOTIFY_MANUAL_TRIG = 5; // 强制放弃 // Force abandon public const int TASK_CLT_NOTIFY_FORCE_GIVEUP = 6; // 动态任务时间标记 // Dynamic task time mark public const int TASK_CLT_NOTIFY_DYN_TIMEMARK = 7; // 动态任务数据 // Dynamic task data public const int TASK_CLT_NOTIFY_DYN_DATA = 8; // 特殊奖励 // Special reward public const int TASK_CLT_NOTIFY_SPECIAL_AWARD = 9; // 离开地点 // Leave location public const int TASK_CLT_NOTIFY_LEAVE_SITE = 10; // PQ检查初始化 // PQ check initialization public const int TASK_CLT_NOTIFY_PQ_CHECK_INIT = 11; // 仓库 // Storage public const int TASK_CLT_NOTIFY_STORAGE = 12; // 请求宝藏索引 // Request treasure index public const int TASK_CLT_NOTIFY_REQUEST_TREASURE_INDEX = 14; // 15天未登录 // 15 days no login public const int TASK_CLT_NOTIFY_15DAYS_NOLOGIN = 15; // 特殊奖励掩码 // Special reward mask public const int TASK_CLT_NOTIFY_SPECIAL_AWARD_MASK = 16; // 称号任务 // Title task public const int TASK_CLT_NOTIFY_TITLE_TASK = 17; // 选择奖励 // Choose reward public const int TASK_CLT_NOTIFY_CHOOSE_AWARD = 18; // 购买代币商店物品 // Buy token shop item public const int TASK_CLT_NOTIFY_BUY_TOKENSHOP_ITEM = 20; // 通过世界贡献完成任务 // Complete task by world contribution public const int TASK_CLT_NOTIFY_FINISH_TASK_BY_WORLD_CONTRIBUTION = 21; // 移除完成任务 // Remove completed task public const int TASK_CLT_NOTIFY_RM_FINISH_TASK = 150; } public static class PlayerNotificationConstants { // Notify receiving team member task // 通知接收队员任务 public const int TASK_PLY_NOTIFY_NEW_MEM_TASK = 1; // Whole team fails // 全队失败 public const int TASK_PLY_NOTIFY_FORCE_FAIL = 2; // Whole team succeeds // 全队成功 public const int TASK_PLY_NOTIFY_FORCE_SUCC = 3; } public static class GlobalDataReasonConstants { public const int TASK_GLOBAL_CHECK_RCV_NUM = 1; public const int TASK_GLOBAL_CHECK_COTASK = 2; public const int TASK_GLOBAL_CHECK_ADD_MEM = 3; public const int TASK_GLOBAL_NPC_KILLED_TIME = 4; public const int TASK_GLOBAL_ADD_TIME_MARK = 5; public const int TASK_GLOBAL_DEL_TIME_MARK = 6; public const int TASK_GLOBAL_PROTECT_NPC = 7; } public static class CotaskConditionConstants { public const int COTASK_CORRESPOND = 0; public const int COTASK_ONCE = 1; } // 任务类型 // Task types public enum ENUM_TASK_TYPE { enumTTDaily = 100, // 每日 // Daily enumTTLevel2, // 修真 // Cultivation enumTTMajor, // 主线 // Main quest enumTTBranch, // 支线 // Branch quest enumTTEvent, // 活动 // Event enumTTQiShaList, // 七杀榜 // Seven Killers List enumTTFaction, // 帮派 // Faction enumTTFunction, // 经营 // Management enumTTLegend, // 传奇 // Legend enumTTQuestion, // 答题 // Quiz enumTTEnd, } // 完成方式 // Completion methods public enum TaskCompletionMethod { enumTMNone = 0, // 无 // None enumTMKillNumMonster, // 杀数量怪 // Kill specific number of monsters enumTMCollectNumArticle, // 获得数量道具 // Collect specific number of items enumTMTalkToNPC, // 与特定NPC对话 // Talk to specific NPC enumTMReachSite, // 到达特定地点 // Reach specific location enumTMWaitTime, // 等待特定时间 // Wait for specific time enumTMAnswerQuestion, // 选择问答 // Answer questions enumTMTinyGame, // 小游戏 // Mini game enumTMProtectNPC, // 保护特定NPC // Protect specific NPC enumTMNPCReachSite, // NPC到达特定地点 // NPC reaches specific location enumTMGlobalValOK, // 全局变量满足条件 // Global variable meets condition enumTMLeaveSite, // 离开特定地点 // Leave specific location enumTMReachTreasureZone, // 达到藏宝区域 // Reach treasure zone enumTMKillPlayer, // 杀死玩家 // Kill player enumTMTransform, // 变身状态 // Transform state enumTMReachLevel, // 检查等级:普通等级,转生次数,境界等级 // Check level: normal level, reincarnation count, realm level enumTMSimpleClientTask, // 简单任务,只做客户端验证,目前只验证表情动作 // Simple task, client-side verification only, currently only verifies emote actions enumTMSimpleClientTaskForceNavi, // 强制移动 // Force movement } // 完成条件 // Completion conditions public enum TaskFinishType { enumTFTDirect = 0, // 直接完成 // Direct completion enumTFTNPC, // NPC完成 // NPC completion enumTFTConfirm // 需要确认完成 // Need confirmation to complete } // 奖励方式 // Reward methods public enum TaskAwardType { enumTATNormal = 0, // 普通 // Normal enumTATEach, // 按杀怪数目、获得物品乘 // Multiply by monster kills, items obtained enumTATRatio, // 按时间比例 // By time ratio enumTATItemCount // 按获得物品个数分不同档次 // Different tiers based on number of items obtained } // 任务重复间隔 // Task repeat interval public enum TaskAwardFreq { enumTAFNormal = 0, // 普通 // Normal enumTAFEachDay, // 每天 // Daily enumTAFEachWeek, // 每周 // Weekly enumTAFEachMonth, // 每月 // Monthly enumTAFEachYear // 每年 // Yearly } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TASK_PACK_HEADER { public uint magic; public uint version; public uint item_count; } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct ZONE_VERT { public float x; public float y; public float z; // Property to access as array (union equivalent) // 作为数组访问的属性(联合体等价) // Property to access as array (union equivalent) public float[] v { get { return new float[] { x, y, z }; } } // Indexer for array-like access // 数组式访问的索引器 // Indexer for array-like access public float this[int index] { get { switch (index) { case 0: return x; case 1: return y; case 2: return z; default: throw new IndexOutOfRangeException(); } } set { switch (index) { case 0: x = value; break; case 1: y = value; break; case 2: z = value; break; default: throw new IndexOutOfRangeException(); } } } public static bool operator ==(ZONE_VERT left, ZONE_VERT right) { return (left.x == right.x && left.y == right.y && left.z == right.z); } public static bool operator !=(ZONE_VERT left, ZONE_VERT right) { return !(left == right); } public override bool Equals(object obj) { if (obj is ZONE_VERT) { return this == (ZONE_VERT)obj; } return false; } public override int GetHashCode() { return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode(); } public bool great_than(float[] v) { return x >= v[0] && y >= v[1] && z >= v[2]; } public bool less_than(float[] v) { return x <= v[0] && y <= v[1] && z <= v[2]; } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct PLAYER_WANTED { // old data of DUCK // public uint m_ulTemplID; // Player Template ID // public uint m_ulCount; // Count // public uint m_ulLevel; // Level // MH: New data public uint m_ulPlayerNum; public uint m_ulDropItemId; public uint m_ulDropItemCount; [MarshalAs(UnmanagedType.U1)] public bool m_bDropCmnItem; public float m_fDropProb; public Kill_Player_Requirements m_Requirements; public string GetLog() { return string.Format("PLAYER_WANTED: Num={0}, DropItemID={1}, DropItemCount={2}, DropCmnItem={3}, DropProb={4}", m_ulPlayerNum, m_ulDropItemId, m_ulDropItemCount, m_bDropCmnItem, m_fDropProb); } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MONSTER_WANTED { public uint m_ulMonsterTemplId; // Monster template ID public uint m_ulMonsterNum; // Number of monsters public uint m_ulDropItemId; // Drop item ID public uint m_ulDropItemCount; // Drop item count [MarshalAs(UnmanagedType.U1)] public bool m_bDropCmnItem; // Is common item drop public float m_fDropProb; // Drop probability [MarshalAs(UnmanagedType.U1)] public bool m_bKillerLev; // Killer level flag public int m_iDPH; // Damage per hit public int m_iDPS; // Damage per second public bool Equals(MONSTER_WANTED src) { return (m_ulMonsterTemplId == src.m_ulMonsterTemplId && m_ulMonsterNum == src.m_ulMonsterNum && m_ulDropItemId == src.m_ulDropItemId && m_ulDropItemCount == src.m_ulDropItemCount && m_bDropCmnItem == src.m_bDropCmnItem && m_fDropProb == src.m_fDropProb && m_bKillerLev == src.m_bKillerLev); } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct ITEM_WANTED { public uint m_ulItemTemplId; // when check bool . m_bCommonItem > 0 == true [MarshalAs(UnmanagedType.U1)] public bool m_bCommonItem; public uint m_ulItemNum; public float m_fProb; public int m_lPeriod; public bool Equals(ITEM_WANTED src) { return (m_ulItemTemplId == src.m_ulItemTemplId && m_bCommonItem == src.m_bCommonItem && m_ulItemNum == src.m_ulItemNum && m_lPeriod == src.m_lPeriod); } public string GetLog() { return string.Format("ITEM_WANTED: ID={0}, Common={1}, Num={2}, Period={3}", m_ulItemTemplId, m_bCommonItem, m_ulItemNum, m_lPeriod); } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TITLE_AWARD { public uint m_ulTitleID; public int m_lPeriod; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TEAM_MEM_ITEM_WANTED { public uint m_ulItemTemplId; public bool m_bCommonItem; public uint m_ulItemNum; } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MONSTERS_SUMMONED { public uint m_ulMonsterTemplId; public uint m_ulMonsterNum; public float m_fSummonProb; public int m_lPeriod; public bool Equals(MONSTERS_SUMMONED src) { return (m_ulMonsterTemplId == src.m_ulMonsterTemplId && m_ulMonsterNum == src.m_ulMonsterNum && m_fSummonProb == src.m_fSummonProb && m_lPeriod == src.m_lPeriod); } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MONSTERS_CONTRIB { public uint m_ulMonsterTemplId; // Monster ID // 怪物ID public int m_iWholeContrib; // Team exclusive contribution // 组队间独享贡献度 public int m_iShareContrib; // Team shared contribution // 组队间共享贡献度 public int m_iPersonalWholeContrib; // Personal exclusive contribution // 个人独享贡献度 public bool Equals(MONSTERS_CONTRIB src) { return (m_ulMonsterTemplId == src.m_ulMonsterTemplId && m_iWholeContrib == src.m_iWholeContrib && m_iShareContrib == src.m_iShareContrib && m_iPersonalWholeContrib == src.m_iPersonalWholeContrib); } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct RANKING_AWARD { public uint m_iRankingStart; public uint m_iRankingEnd; [MarshalAs(UnmanagedType.U1)] public bool m_bCommonItem; public uint m_ulAwardItemId; public uint m_ulAwardItemNum; public int m_lPeriod; public bool Equals(RANKING_AWARD src) { return (m_iRankingStart == src.m_iRankingStart && m_iRankingEnd == src.m_iRankingEnd && m_bCommonItem == src.m_bCommonItem && m_ulAwardItemId == src.m_ulAwardItemId && m_ulAwardItemNum == src.m_ulAwardItemNum && m_lPeriod == src.m_lPeriod); } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct AWARD_MONSTERS_SUMMONED { public uint m_ulMonsterNum; [MarshalAs(UnmanagedType.U1)] public bool m_bRandChoose; public uint m_ulSummonRadius; [MarshalAs(UnmanagedType.U1)] public bool m_bDeathDisappear; [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.MAX_MONSTER_SUMMONED)] public MONSTERS_SUMMONED[] m_Monsters; public int MarshalBasicData(byte[] pData) { int offset = 0; pData[offset] = m_bRandChoose ? (byte)1 : (byte)0; offset++; pData[offset] = (byte)m_ulSummonRadius; offset++; pData[offset] = (byte)m_ulMonsterNum; offset++; pData[offset] = m_bDeathDisappear ? (byte)1 : (byte)0; offset++; int sz = Marshal.SizeOf(typeof(MONSTERS_SUMMONED)) * (int)m_ulMonsterNum; if (sz > 0) { // Copy MONSTERS_SUMMONED array to byte array GCHandle handle = GCHandle.Alloc(m_Monsters, GCHandleType.Pinned); try { IntPtr ptr = handle.AddrOfPinnedObject(); Marshal.Copy(ptr, pData, offset, sz); } finally { handle.Free(); } offset += sz; } return offset; } public int UnmarshalBasicData(byte[] pData) { int offset = 0; m_bRandChoose = pData[offset] != 0; offset++; m_ulSummonRadius = pData[offset]; offset++; m_ulMonsterNum = pData[offset]; offset++; m_bDeathDisappear = pData[offset] != 0; offset++; if (m_ulMonsterNum > 0) { m_Monsters = new MONSTERS_SUMMONED[m_ulMonsterNum]; int sz = Marshal.SizeOf(typeof(MONSTERS_SUMMONED)) * (int)m_ulMonsterNum; // Copy byte array to MONSTERS_SUMMONED array for (uint i = 0; i < m_ulMonsterNum; i++) { IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MONSTERS_SUMMONED))); try { Marshal.Copy(pData, offset, ptr, Marshal.SizeOf(typeof(MONSTERS_SUMMONED))); m_Monsters[i] = (MONSTERS_SUMMONED)Marshal.PtrToStructure(ptr, typeof(MONSTERS_SUMMONED)); } finally { Marshal.FreeHGlobal(ptr); } offset += Marshal.SizeOf(typeof(MONSTERS_SUMMONED)); } } return offset; } public static bool operator ==(AWARD_MONSTERS_SUMMONED a, AWARD_MONSTERS_SUMMONED b) { if (a.m_ulMonsterNum != b.m_ulMonsterNum) { return false; } for (uint i = 0; i < a.m_ulMonsterNum; ++i) { if (!(a.m_Monsters[i].Equals(b.m_Monsters[i]))) { return false; } } return (a.m_bRandChoose == b.m_bRandChoose && a.m_ulSummonRadius == b.m_ulSummonRadius && a.m_bDeathDisappear == b.m_bDeathDisappear); } public static bool operator !=(AWARD_MONSTERS_SUMMONED a, AWARD_MONSTERS_SUMMONED b) { return !(a == b); } public override bool Equals(object obj) { if (obj is AWARD_MONSTERS_SUMMONED) return this == (AWARD_MONSTERS_SUMMONED)obj; return false; } public override int GetHashCode() { return m_ulMonsterNum.GetHashCode() ^ m_bRandChoose.GetHashCode() ^ m_ulSummonRadius.GetHashCode() ^ m_bDeathDisappear.GetHashCode(); } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct AWARD_PQ_RANKING { [MarshalAs(UnmanagedType.U1)] public bool m_bAwardByProf; public uint m_ulRankingAwardNum; [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_AWARD_PQ_RANKING)] public RANKING_AWARD[] m_RankingAward; public int MarshalBasicData(byte[] pData) { int offset = 0; pData[offset] = m_bAwardByProf ? (byte)1 : (byte)0; offset++; pData[offset] = (byte)m_ulRankingAwardNum; offset++; int sz = Marshal.SizeOf(typeof(RANKING_AWARD)) * (int)m_ulRankingAwardNum; if (sz > 0) { // Copy RANKING_AWARD array to byte array GCHandle handle = GCHandle.Alloc(m_RankingAward, GCHandleType.Pinned); try { IntPtr ptr = handle.AddrOfPinnedObject(); Marshal.Copy(ptr, pData, offset, sz); } finally { handle.Free(); } offset += sz; } return offset; } public int UnmarshalBasicData(byte[] pData) { int offset = 0; m_bAwardByProf = pData[offset] != 0; offset++; m_ulRankingAwardNum = pData[offset]; offset++; if (m_ulRankingAwardNum > 0) { m_RankingAward = new RANKING_AWARD[m_ulRankingAwardNum]; int sz = Marshal.SizeOf(typeof(RANKING_AWARD)) * (int)m_ulRankingAwardNum; // Copy byte array to RANKING_AWARD array for (uint i = 0; i < m_ulRankingAwardNum; i++) { IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(RANKING_AWARD))); try { Marshal.Copy(pData, offset, ptr, Marshal.SizeOf(typeof(RANKING_AWARD))); m_RankingAward[i] = (RANKING_AWARD)Marshal.PtrToStructure(ptr, typeof(RANKING_AWARD)); } finally { Marshal.FreeHGlobal(ptr); } offset += Marshal.SizeOf(typeof(RANKING_AWARD)); } } return offset; } public static bool operator ==(AWARD_PQ_RANKING a, AWARD_PQ_RANKING b) { if (a.m_bAwardByProf != b.m_bAwardByProf) { return false; } if (a.m_ulRankingAwardNum != b.m_ulRankingAwardNum) { return false; } for (uint i = 0; i < a.m_ulRankingAwardNum; ++i) { if (!(a.m_RankingAward[i].Equals(b.m_RankingAward[i]))) { return false; } } return true; } public static bool operator !=(AWARD_PQ_RANKING a, AWARD_PQ_RANKING b) { return !(a == b); } public override bool Equals(object obj) { if (obj is AWARD_PQ_RANKING) return this == (AWARD_PQ_RANKING)obj; return false; } public override int GetHashCode() { return m_bAwardByProf.GetHashCode() ^ m_ulRankingAwardNum.GetHashCode(); } } public class TaskTemplUtils { /// /// 必须定义operator == // Must define operator == /// /// The type of the objects to compare /// First object to compare /// Second object to compare /// True if both objects are equal or both are null public static bool CompareTwoPointer(T_NAME p1, T_NAME p2) { if (p1 == null && p2 == null) { return true; } else if (p1 != null && p2 != null) { return p1.Equals(p2); } else return false; } public static ushort uint_to_ushort(uint id) { return (ushort)(id & 0xFF); } public static void convert_txt(ref ushort[] str, int len, ushort code) { for (int i = 0; i < len; i++) { str[i] ^= code; } } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct task_tm { public int year; public int month; public int day; public int hour; public int min; public int wday; public string GetLog() { return string.Format("{0}-{1}-{2} {3}:{4} (wday:{5})", year, month, day, hour, min, wday); } // ===== C++ task_tm time comparison helpers ===== // [中文] 对齐 C++ 的 task_tm::after/before 等比较逻辑(含“月/周/日”模式) // [English] Parity with C++ task_tm::after/before and per-month/week/day variants // C++: bool after(const tm* _tm) const public bool after(DateTime t) { int ty = t.Year; int tm = t.Month; int td = t.Day; int th = t.Hour; int tmin = t.Minute; if (year < ty) return false; if (year > ty) return true; if (month < tm) return false; if (month > tm) return true; if (day < td) return false; if (day > td) return true; if (hour < th) return false; return hour > th || min > tmin; } // C++: bool before(const tm* _tm) const public bool before(DateTime t) { int ty = t.Year; int tm = t.Month; int td = t.Day; int th = t.Hour; int tmin = t.Minute; if (year > ty) return false; if (year < ty) return true; if (month > tm) return false; if (month < tm) return true; if (day > td) return false; if (day < td) return true; if (hour > th) return false; return hour < th || min <= tmin; } // C++: bool after_per_month(const tm* _tm, bool bLastDay) const public bool after_per_month(DateTime t, bool bLastDay) { int td = t.Day; int th = t.Hour; int tmin = t.Minute; if (day < td) return false; if (!bLastDay && day > td) return true; if (hour < th) return false; return hour > th || min > tmin; } // C++: bool before_per_month(const tm* _tm, bool bLastDay) const public bool before_per_month(DateTime t, bool bLastDay) { int td = t.Day; int th = t.Hour; int tmin = t.Minute; if (day < td) return true; if (!bLastDay && day > td) return false; if (hour > th) return false; return hour < th || min <= tmin; } // task_week_map (C++): { 7,1,2,3,4,5,6 } with tm_wday Sunday=0 private static readonly int[] s_task_week_map = { 7, 1, 2, 3, 4, 5, 6 }; // C++: bool after_per_week(const tm* _tm) const public bool after_per_week(DateTime t) { int w = s_task_week_map[(int)t.DayOfWeek]; if (wday < w) return false; if (wday > w) return true; int th = t.Hour; int tmin = t.Minute; if (hour < th) return false; return hour > th || min > tmin; } // C++: bool before_per_week(const tm* _tm) const public bool before_per_week(DateTime t) { int w = s_task_week_map[(int)t.DayOfWeek]; if (wday > w) return false; if (wday < w) return true; int th = t.Hour; int tmin = t.Minute; if (hour > th) return false; return hour < th || min <= tmin; } // C++: bool after_per_day(const tm* _tm) const public bool after_per_day(DateTime t) { int th = t.Hour; int tmin = t.Minute; if (hour < th) return false; return hour > th || min > tmin; } // C++: bool before_per_day(const tm* _tm) const public bool before_per_day(DateTime t) { int th = t.Hour; int tmin = t.Minute; if (hour > th) return false; return hour < th || min <= tmin; } } // Define task_team_member_info struct required by TEAM_MEM_WANTED [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct task_team_member_info { public uint m_ulLevel; public uint m_ulOccupation; public int m_iForce; [MarshalAs(UnmanagedType.U1)] public bool m_bMale; } // Race-occupation mapping array public static class TaskTemplMapping { public static readonly uint[] _race_occ_map = new uint[TaskTemplConstants.MAX_OCCUPATIONS]; } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TEAM_MEM_WANTED { public uint m_ulLevelMin; public uint m_ulLevelMax; public uint m_ulRace; public uint m_ulOccupation; public uint m_ulGender; public uint m_ulMinCount; public uint m_ulMaxCount; public uint m_ulTask; public int m_iForce; // public uint m_ulTeamMemsItemWanted; // public TEAM_MEM_ITEM_WANTED[] m_TeamMemItemWanted; //[MAX_ITEM_WANTED]; // public bool m_bJustCheck; // Initialize fields with default values to avoid constructor issues public static TEAM_MEM_WANTED Create() { TEAM_MEM_WANTED result = new TEAM_MEM_WANTED(); result.Init(); return result; } public bool IsMeetBaseInfo(task_team_member_info pInfo) { if (m_ulLevelMin != 0 && pInfo.m_ulLevel < m_ulLevelMin) return false; if (m_ulLevelMax != 0 && pInfo.m_ulLevel > m_ulLevelMax) return false; if (m_ulRace != 0) { if (pInfo.m_ulOccupation >= TaskTemplConstants.MAX_OCCUPATIONS) return false; if (TaskTemplMapping._race_occ_map[pInfo.m_ulOccupation] != m_ulRace) return false; } else if (m_ulOccupation != TaskTemplConstants.INVALID_VAL && pInfo.m_ulOccupation != m_ulOccupation) return false; if (m_iForce != 0) { if (m_iForce == -1) { if (pInfo.m_iForce == 0) return false; } else if (pInfo.m_iForce != m_iForce) return false; } #if !_TASK_CLIENT if (m_ulGender == TaskTemplConstants.TASK_GENDER_MALE && !pInfo.m_bMale || m_ulGender == TaskTemplConstants.TASK_GENDER_FEMALE && pInfo.m_bMale) return false; #endif return true; } public bool IsMeetCount(uint ulCount) { if (m_ulMinCount != 0 && ulCount < m_ulMinCount) return false; if (m_ulMaxCount != 0 && ulCount > m_ulMaxCount) return false; return true; } public void Init() { m_ulLevelMin = 0; m_ulLevelMax = 0; m_ulRace = 0; m_ulOccupation = TaskTemplConstants.INVALID_VAL; m_ulGender = 0; m_ulMinCount = 0; m_ulMaxCount = 0; m_ulTask = 0; m_iForce = 0; // m_ulTeamMemsItemWanted = 0; // m_TeamMemItemWanted = null; // m_bJustCheck = false; } public bool IsValid() { return !( m_ulLevelMin == 0 && m_ulLevelMax == 0 && m_ulRace == 0 && m_ulOccupation == TaskTemplConstants.INVALID_VAL && m_ulGender == 0 && m_ulMinCount == 0 && m_ulMaxCount == 0 && m_ulTask == 0 // && // m_ulTeamMemsItemWanted == 0 && // m_TeamMemItemWanted == null && // m_bJustCheck == false ); } public static bool operator ==(TEAM_MEM_WANTED a, TEAM_MEM_WANTED b) { return ( a.m_ulLevelMin == b.m_ulLevelMin && a.m_ulLevelMax == b.m_ulLevelMax && a.m_ulRace == b.m_ulRace && a.m_ulOccupation == b.m_ulOccupation && a.m_ulGender == b.m_ulGender && a.m_ulMinCount == b.m_ulMinCount && a.m_ulMaxCount == b.m_ulMaxCount && a.m_ulTask == b.m_ulTask // && // a.m_ulTeamMemsItemWanted == b.m_ulTeamMemsItemWanted && // *a.m_TeamMemItemWanted == *(b.m_TeamMemItemWanted) && // a.m_bJustCheck == b.m_bJustCheck ); } public static bool operator !=(TEAM_MEM_WANTED a, TEAM_MEM_WANTED b) { return !(a == b); } public override bool Equals(object obj) { if (obj is TEAM_MEM_WANTED) return this == (TEAM_MEM_WANTED)obj; return false; } public override int GetHashCode() { return m_ulLevelMin.GetHashCode() ^ m_ulLevelMax.GetHashCode() ^ m_ulRace.GetHashCode() ^ m_ulOccupation.GetHashCode(); } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct AWARD_RATIO_SCALE { static uint g_ulNewCount; // Static counter for memory tracking // Default constructor not available in C# 9.0, fields are initialized directly public uint m_ulScales; [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_AWARD_SCALES)] public float[] m_Ratios; [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_AWARD_SCALES)] public AWARD_DATA[] m_Awards; //[MAX_AWARD_SCALES]; // Initialize method instead of constructor public void Initialize() { m_ulScales = 0; m_Ratios = new float[TaskTemplConstants.MAX_AWARD_SCALES]; m_Awards = null; #if TASK_TEMPL_EDITOR m_Awards = new AWARD_DATA[TaskTemplConstants.MAX_AWARD_SCALES]; g_ulNewCount++; #endif } public static bool operator ==(AWARD_RATIO_SCALE a, AWARD_RATIO_SCALE b) { if (a.m_ulScales != b.m_ulScales) { return false; } for (uint i = 0; i < a.m_ulScales; ++i) { // Add null check if (a.m_Ratios[i] != b.m_Ratios[i] || (a.m_Awards != null && b.m_Awards != null && i < a.m_Awards.Length && i < b.m_Awards.Length && !(a.m_Awards[i] == b.m_Awards[i]))) { return false; } } return true; } public static bool operator !=(AWARD_RATIO_SCALE a, AWARD_RATIO_SCALE b) { return !(a == b); } public override bool Equals(object obj) { if (obj is AWARD_RATIO_SCALE) return this == (AWARD_RATIO_SCALE)obj; return false; } public override int GetHashCode() { return m_ulScales.GetHashCode(); } // Copy constructor equivalent method public static AWARD_RATIO_SCALE CreateCopy(AWARD_RATIO_SCALE src) { AWARD_RATIO_SCALE result = new AWARD_RATIO_SCALE(); result.m_ulScales = src.m_ulScales; result.m_Ratios = new float[TaskTemplConstants.MAX_AWARD_SCALES]; // Copy the ratios array for (int i = 0; i < src.m_Ratios.Length && i < TaskTemplConstants.MAX_AWARD_SCALES; i++) { result.m_Ratios[i] = src.m_Ratios[i]; } #if !TASK_TEMPL_EDITOR if (src.m_ulScales > 0) { result.m_Awards = new AWARD_DATA[src.m_ulScales]; g_ulNewCount++; } #else result.m_Awards = new AWARD_DATA[TaskTemplConstants.MAX_AWARD_SCALES]; g_ulNewCount++; #endif // Copy awards if available if (src.m_Awards != null && result.m_Awards != null) { for (uint i = 0; i < src.m_ulScales && i < result.m_Awards.Length && i < src.m_Awards.Length; i++) { result.m_Awards[i] = src.m_Awards[i]; } } return result; } public bool HasAward() { if (m_Awards == null) return false; for (uint i = 0; i < m_ulScales && i < m_Awards.Length; i++) if (m_Awards[i].HasAward()) return true; return false; } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct AWARD_ITEMS_SCALE { static uint g_ulNewCount; // Static counter for memory tracking // Default constructor not available in C# 9.0, fields are initialized directly public uint m_ulScales; public uint m_ulItemId; [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_AWARD_SCALES)] public uint[] m_Counts; [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_AWARD_SCALES)] public AWARD_DATA[] m_Awards; //[MAX_AWARD_SCALES]; // Initialize method instead of constructor public void Initialize() { m_ulScales = 0; m_ulItemId = 0; m_Counts = new uint[TaskTemplConstants.MAX_AWARD_SCALES]; m_Awards = null; #if TASK_TEMPL_EDITOR m_Awards = new AWARD_DATA[TaskTemplConstants.MAX_AWARD_SCALES]; g_ulNewCount++; #endif } public static bool operator ==(AWARD_ITEMS_SCALE a, AWARD_ITEMS_SCALE b) { if (a.m_ulScales != b.m_ulScales) { return false; } for (uint i = 0; i < a.m_ulScales; ++i) { // Add null check if (a.m_Counts[i] != b.m_Counts[i] || (a.m_Awards != null && b.m_Awards != null && i < a.m_Awards.Length && i < b.m_Awards.Length && !(a.m_Awards[i] == b.m_Awards[i]))) { return false; } } return a.m_ulItemId == b.m_ulItemId; } public static bool operator !=(AWARD_ITEMS_SCALE a, AWARD_ITEMS_SCALE b) { return !(a == b); } public override bool Equals(object obj) { if (obj is AWARD_ITEMS_SCALE) return this == (AWARD_ITEMS_SCALE)obj; return false; } public override int GetHashCode() { return m_ulScales.GetHashCode() ^ m_ulItemId.GetHashCode(); } // Copy constructor equivalent method public static AWARD_ITEMS_SCALE CreateCopy(AWARD_ITEMS_SCALE src) { AWARD_ITEMS_SCALE result = new AWARD_ITEMS_SCALE(); result.m_ulScales = src.m_ulScales; result.m_ulItemId = src.m_ulItemId; result.m_Counts = new uint[TaskTemplConstants.MAX_AWARD_SCALES]; // Copy the counts array for (int i = 0; i < src.m_Counts.Length && i < TaskTemplConstants.MAX_AWARD_SCALES; i++) { result.m_Counts[i] = src.m_Counts[i]; } #if !TASK_TEMPL_EDITOR if (src.m_ulScales > 0) { result.m_Awards = new AWARD_DATA[src.m_ulScales]; g_ulNewCount++; } #else result.m_Awards = new AWARD_DATA[TaskTemplConstants.MAX_AWARD_SCALES]; g_ulNewCount++; #endif // Copy awards if available if (src.m_Awards != null && result.m_Awards != null) { for (uint i = 0; i < src.m_ulScales && i < result.m_Awards.Length && i < src.m_Awards.Length; i++) { result.m_Awards[i] = src.m_Awards[i]; } } return result; } public bool HasAward() { if (m_Awards == null) return false; for (uint i = 0; i < m_ulScales && i < m_Awards.Length; i++) if (m_Awards[i].HasAward()) return true; return false; } } public enum task_tm_type { enumTaskTimeDate = 0, enumTaskTimeMonth, enumTaskTimeWeek, enumTaskTimeDay }; /// /// Completion Method /// // public enum TaskCompletionMethod // { // enumTMNone = 0, // None // enumTMKillNumMonster, // Kill a number of monsters // enumTMCollectNumArticle, // Collect a number of items // enumTMTalkToNPC, // Talk to a specific NPC // enumTMReachSite, // Reach a specific location // enumTMWaitTime, // Wait for a specified time // enumTMAnswerQuestion, // Answer a question // enumTMTinyGame, // Mini-game // enumTMProtectNPC, // Protect a specific NPC // enumTMNPCReachSite, // NPC reaches a specific location // enumTMGlobalValOK, // Global variable condition satisfied // enumTMLeaveSite, // Leave a specific location // enumTMReachTreasureZone, // Reach the treasure area // enumTMKillPlayer, // Kill another player // enumTMTransform, // Transform state // enumTMReachLevel, // Check level: normal level, rebirth count, realm level // enumTMSimpleClientTask, // Simple client task (only client-side validation, currently just checks UI triggers) // enumTMSimpleClientTaskForceNavi // Force navigation // } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct COMPARE_KEY_VALUE { public int nLeftType; public int lLeftNum; public int nCompOper; public int nRightType; public int lRightNum; public static bool operator ==(COMPARE_KEY_VALUE a, COMPARE_KEY_VALUE b) { return (a.nLeftType == b.nLeftType && a.lLeftNum == b.lLeftNum && a.nCompOper == b.nCompOper && a.nRightType == b.nRightType && a.lRightNum == b.lRightNum); } public static bool operator !=(COMPARE_KEY_VALUE a, COMPARE_KEY_VALUE b) { return !(a == b); } public override bool Equals(object obj) { if (obj is COMPARE_KEY_VALUE) return this == (COMPARE_KEY_VALUE)obj; return false; } public override int GetHashCode() { return nLeftType.GetHashCode() ^ lLeftNum.GetHashCode() ^ nCompOper.GetHashCode() ^ nRightType.GetHashCode() ^ lRightNum.GetHashCode(); } } [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Task_Region { public ZONE_VERT zvMin; public ZONE_VERT zvMax; public bool Equals(Task_Region src) { return (zvMin.x == src.zvMin.x && zvMin.y == src.zvMin.y && zvMin.z == src.zvMin.z && zvMax.x == src.zvMax.x && zvMax.y == src.zvMax.y && zvMax.z == src.zvMax.z); } public static bool operator ==(Task_Region a, Task_Region b) { return a.Equals(b); } public static bool operator !=(Task_Region a, Task_Region b) { return !a.Equals(b); } public override bool Equals(object obj) { if (obj is Task_Region) return Equals((Task_Region)obj); return false; } public override int GetHashCode() { return zvMin.GetHashCode() ^ zvMax.GetHashCode(); } public string GetLog() { return $"Min({zvMin.x}, {zvMin.y}, {zvMin.z}) - Max({zvMax.x}, {zvMax.y}, {zvMax.z})"; } } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TaskFinishTimeEntry { public ushort m_uTaskId; public uint m_ulTimeMark; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TaskFinishTimeList { public ushort m_uCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN)] public TaskFinishTimeEntry[] m_aList; public TaskFinishTimeList(byte[] data) { int offset = 0; m_uCount = BitConverter.ToUInt16(data, offset); offset += sizeof(ushort); m_aList = new TaskFinishTimeEntry[TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN]; for (int i = 0; i < TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN; i++) { m_aList[i].m_uTaskId = BitConverter.ToUInt16(data, offset); offset += sizeof(ushort); m_aList[i].m_ulTimeMark = BitConverter.ToUInt32(data, offset); offset += sizeof(uint); } } public void ReadFromBuffer(byte[] data) { int offset = 0; m_uCount = BitConverter.ToUInt16(data, offset); offset += sizeof(ushort); m_aList = new TaskFinishTimeEntry[TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN]; for (int i = 0; i < TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN; i++) { m_aList[i].m_uTaskId = BitConverter.ToUInt16(data, offset); offset += sizeof(ushort); m_aList[i].m_ulTimeMark = BitConverter.ToUInt32(data, offset); offset += sizeof(uint); } } public uint Search(uint ulID) { for (int i = 0; i < m_uCount; i++) if (m_aList[i].m_uTaskId == (ushort)ulID) return m_aList[i].m_ulTimeMark; return 0; } public void AddOrUpdate(uint ulID, uint ulTime){ for (int i = 0; i < m_uCount; i++) { if (m_aList[i].m_uTaskId == (ushort)ulID) { m_aList[i].m_ulTimeMark = ulTime; return; } } if (m_uCount >= TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN) return; m_aList[m_uCount].m_uTaskId = (ushort)ulID; m_aList[m_uCount].m_ulTimeMark = ulTime; m_uCount++; } public void RemoveAll() { m_uCount = 0; for (int i = 0; i < TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN; i++) { m_aList[i].m_uTaskId = 0; m_aList[i].m_ulTimeMark = 0; } } public bool IsValid() { return m_uCount <= TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN; } // Persist this list back into the underlying buffer returned by TaskInterface.GetFinishedTimeList(). // Buffer layout: ushort count + TASK_FINISH_TIME_MAX_LEN * (ushort taskId + uint timeMark) public void WriteToBuffer(byte[] data) { if (data == null) return; int entrySize = sizeof(ushort) + sizeof(uint); int expected = sizeof(ushort) + entrySize * TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN; if (data.Length < expected) return; int offset = 0; Array.Copy(BitConverter.GetBytes(m_uCount), 0, data, offset, sizeof(ushort)); offset += sizeof(ushort); if (m_aList == null || m_aList.Length != TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN) { // Keep buffer consistent even if list isn't initialized. Array.Clear(data, offset, data.Length - offset); return; } for (int i = 0; i < TaskInterfaceConstants.TASK_FINISH_TIME_MAX_LEN; i++) { Array.Copy(BitConverter.GetBytes(m_aList[i].m_uTaskId), 0, data, offset, sizeof(ushort)); offset += sizeof(ushort); Array.Copy(BitConverter.GetBytes(m_aList[i].m_ulTimeMark), 0, data, offset, sizeof(uint)); offset += sizeof(uint); } } }; /*public bool judge_time_date(task_tm tmStart, task_tm tmEnd, uint ulCurTime, task_tm_type tm_type) { tm _time, _time_tomorrow; uint ulTimeTomorrow; bool last_day; #if _TASK_CLIENT ulCurTime -= (uint)(TaskInterface.GetTimeZoneBias() * 60); if ((long)(ulCurTime) < 0) ulCurTime = 0; _time = DateTimeOffset.FromUnixTimeSeconds(ulCurTime).UtcDateTime; _time_tomorrow = _time.AddDays(1); #else _time = *localtime((time_t*)&ulCurTime); ulTimeTomorrow = ulCurTime + 24 * 3600; _time_tomorrow = *localtime((time_t*)&ulTimeTomorrow); #endif last_day = (_time.tm_mon != _time_tomorrow.tm_mon); switch (tm_type) { case enumTaskTimeDate: return tmStart->before(&_time) && tmEnd->after(&_time); case enumTaskTimeMonth: return tmStart->before_per_month(&_time, last_day) && tmEnd->after_per_month(&_time, last_day); case enumTaskTimeWeek: return tmStart->before_per_week(&_time) && tmEnd->after_per_week(&_time); case enumTaskTimeDay: return tmStart->before_per_day(&_time) && tmEnd->after_per_day(&_time); } return false; }*/ /// /// 任务模板类 // Task Template Class /// include /// [Serializable] public partial class ATaskTempl { [SerializeField] public ATaskTemplFixedData m_FixedData; public bool is_in_zone(ZONE_VERT _min, ZONE_VERT _max, float[] pos) { return _min.less_than(pos) && _max.great_than(pos); } //Hierarchy public ATaskTempl m_pParent = null; public uint ParentID; public ATaskTempl m_pPrevSibling = null; public uint PrevSiblingID; public ATaskTempl m_pNextSibling = null; public uint NextSiblingID; public ATaskTempl m_pFirstChild = null; public uint FirstChildID; public byte m_uDepth; // 深度 // Depth const int MAX_TASK_NAME_LEN = 30; const int TASK_AWARD_MAX_CHANGE_VALUE = 255; // 任务描述 // Task description public ushort[] m_pwstrDescript; // 接受时文本 // OK text public ushort[] m_pwstrOkText; // 拒绝时文本 // No text public ushort[] m_pwstrNoText; public ushort[] m_pwstrTribute; // 发放/验证/执行/奖励对话 // Delivery/Unqualified/Execute/Award talks public talk_proc m_DelvTaskTalk; // 发放任务对话 // Delivery task talk public talk_proc m_UnqualifiedTalk; // 不符合条件对话 // Unqualified talk public talk_proc m_DelvItemTalk; // 发放物品对话 // Deliver item talk public talk_proc m_ExeTalk; // 执行任务对话 // Execute task talk public talk_proc m_AwardTalk; // 任务奖励对话 // Award talk public int m_nSubCount; // 子任务数量 // Subtask count public byte m_uValidCount; private uint m_ulMask; // 任务掩码 // Task mask /* ÈÎÎñ½áÊøºóµÄ½±Àø */ public uint m_ID => m_FixedData.m_ID; public uint GetAwardType_S() => m_FixedData.m_ulAwardType_S; public uint GetAwardType_F() => m_FixedData.m_ulAwardType_F; // ʱ¼äÏÞÖÆ uint m_ulTimeLimit => m_FixedData.m_ulTimeLimit; /* ÆÕͨºÍ°´Ã¿¸ö·½Ê½ */ public AWARD_DATA m_Award_S => m_FixedData.m_Award_S; /* ³É¹¦ */ public AWARD_DATA m_Award_F => m_FixedData.m_Award_F; /* ʧ°Ü */ /* ʱ¼ä±ÈÀý·½Ê½ */ AWARD_RATIO_SCALE m_AwByRatio_S => m_FixedData.m_AwByRatio_S; AWARD_RATIO_SCALE m_AwByRatio_F => m_FixedData.m_AwByRatio_F; /* °´»ñµÃÎï±ÈÀý·½Ê½ */ AWARD_ITEMS_SCALE m_AwByItems_S => m_FixedData.m_AwByItems_S; AWARD_ITEMS_SCALE m_AwByItems_F => m_FixedData.m_AwByItems_F; uint g_ulNewCount = 0; public bool LoadFromBinFile(Stream fp) { LoadBinary(fp); CheckDepth(); return true; } public string GetDescription() { return ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrDescript); } public bool CanFinishTask(TaskInterface pTask, ActiveTaskEntry pEntry, uint ulCurTime) { bool ret = false; while (true) { // 若发放非法则不允许完成 // If delivery is illegal, cannot finish if (pTask == null || pEntry == null) break; if (!pTask.IsDeliverLegal()) break; // 已完成直接返回 // Already finished . true if (pEntry.IsFinished()) { ret = true; break; } switch ((TaskCompletionMethod)m_FixedData.m_enumMethod) { case TaskCompletionMethod.enumTMCollectNumArticle: // 背包中已拥有所有需要的物品 // Has all required items ret = HasAllItemsWanted(pTask); break; case TaskCompletionMethod.enumTMWaitTime: // 等待时间达成 // Wait time satisfied ret = (m_FixedData.m_ulWaitTime == 0) || (pEntry.m_ulTaskTime + (ulong)m_FixedData.m_ulWaitTime < (ulong)ulCurTime); break; case TaskCompletionMethod.enumTMTalkToNPC: // 对话类任务可直接完成 // Talk-to-NPC tasks complete immediately ret = true; break; case TaskCompletionMethod.enumTMGlobalValOK: // 全局变量满足条件 // Global variable meets condition ret = CheckGlobalKeyValue(pTask, true) == 0; break; case TaskCompletionMethod.enumTMTransform: { int playerShapeType = pTask.GetShapeMask(); // 变身职业判断 // Transform occupation check if (m_FixedData.m_ucTransformedForm == 0x80) { if ((playerShapeType >> 6) == 2) ret = true; } // 特定形态匹配 // Specific form match else if (m_FixedData.m_ucTransformedForm == playerShapeType) ret = true; } break; case TaskCompletionMethod.enumTMReachTreasureZone: { // 到达藏宝区网格 // Reach treasure zone grid float[] pos = new float[3]; uint ulWorldId = (uint)pTask.GetPos(pos); if (ulWorldId == 1) { ushort uTreasureLocIndex = (ushort)(pEntry.m_iUsefulData1 & 0xFFFF); float fTreasureLocX = m_FixedData.m_TreasureStartZone.x + ((uTreasureLocIndex % m_FixedData.m_ucZonesNumX) - 1) * (float)m_FixedData.m_ucZoneSide; float fTreasureLocZ = m_FixedData.m_TreasureStartZone.z + (uTreasureLocIndex / m_FixedData.m_ucZonesNumX) * (float)m_FixedData.m_ucZoneSide; ret = pos[0] >= fTreasureLocX && pos[2] >= fTreasureLocZ && pos[0] <= fTreasureLocX + (float)m_FixedData.m_ucZoneSide && pos[2] <= fTreasureLocZ + (float)m_FixedData.m_ucZoneSide; } } break; case TaskCompletionMethod.enumTMSimpleClientTask: case TaskCompletionMethod.enumTMSimpleClientTaskForceNavi: { // 简单客户端任务条件 // Simple client task condition ret = pTask.CheckSimpleTaskFinshConditon(m_FixedData.m_ID); } break; case TaskCompletionMethod.enumTMReachLevel: // 达到等级条件 // Reach level condition ret = CheckReachLevel(pTask); break; default: break; } break; } // 等级前置校验 // Premise level check if (m_FixedData.m_ulPremise_Lev_Min != 0) { if (m_FixedData.m_bPremCheckMaxHistoryLevel == 0 && pTask.GetPlayerLevel() < m_FixedData.m_ulPremise_Lev_Min) ret = false; } return ret; } public bool HasAllItemsWanted(TaskInterface pTask) { if (m_FixedData.m_ulGoldWanted != 0 && pTask.GetGoldNum() < m_FixedData.m_ulGoldWanted) return false; if (m_FixedData.m_iFactionContribWanted != 0 && pTask.GetFactionConsumeContrib() < m_FixedData.m_iFactionContribWanted) return false; if (m_FixedData.m_iFactionExpContribWanted != 0 && pTask.GetFactionExpContrib() < m_FixedData.m_iFactionExpContribWanted) return false; int i = 0; for (; i < (int)m_FixedData.m_ulItemsWanted; i++) { ITEM_WANTED iw = m_FixedData.m_ItemsWanted[i]; uint ulNum = _get_item_count( pTask, iw.m_ulItemTemplId, iw.m_bCommonItem); if (ulNum == 0 || ulNum < iw.m_ulItemNum) return false; } return true; } // 递归检查奖励条件并返回错误码 // Recursively check award prerequisites and return error code public uint RecursiveCheckAward(TaskInterface pTask, ActiveTaskList pList, ActiveTaskEntry pEntry, uint ulCurTime, int nChoice) { // 计数器与预算初始化 // Initialize counters and budget uint ulCmnCount = 0; uint ulTskCount = 0; uint ulTopCount = 0; byte uBudget = 0; long lReputation = 0; // Suppress unused warnings until RecursiveCalcAward is fully ported. _ = ulCmnCount; _ = ulTskCount; _ = lReputation; // 任务屏蔽检查 // Task forbid check if (pTask.CheckTaskForbid(m_FixedData.m_ID)) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_TASK_FORBID; // 跨服限制检查 // Cross-server account limit check if (m_FixedData.m_bAccountTaskLimit && pTask.IsAtCrossServer()) return (uint)TaskInterfaceConstants.TASK_AWARD_FAIL_CROSSSERVER_NO_ACOUNT_LIMIT; // TODO: Implement recursive award calculation // Recursively calculate award and return early on error // uint ulRet = RecursiveCalcAward(pTask, pList, pEntry, ulCurTime, nChoice, out ulCmnCount, out ulTskCount, out ulTopCount, out uBudget, out lReputation); // if (ulRet != 0) return ulRet; // 顶部任务计数拆分 // Split top task counters uint ulTopShowCount = (ulTopCount & 0xffff0000u) >> 16; uint ulTopHideCount = (ulTopCount & 0x000000ffu); uint ulTitleTaskCount = (ulTopCount & 0x0000ff00u) >> 8; // 顶部任务数量上限检查 // Top task caps check if ((ulTopShowCount != 0 && (uint)pList.m_uTopShowTaskCount + ulTopShowCount > (uint)GetMaxSimultaneousCount(pList)) || (ulTopHideCount != 0 && (uint)pList.m_uTopHideTaskCount + ulTopHideCount > (uint)TASK_HIDDEN_COUNT) || (ulTitleTaskCount != 0 && (uint)pList.m_uTitleTaskCount + ulTitleTaskCount > (uint)TASK_TITLE_TASK_COUNT)) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_FULL; // 活动列表容量检查 // Active list capacity check if (uBudget != 0 && (uint)pList.m_uUsedCount + uBudget > (uint)TaskInterfaceConstants.TASK_ACTIVE_LIST_MAX_LEN) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_NO_SPACE; // TODO: Item grant legality check // if ((ulCmnCount != 0 && !pTask.CanDeliverCommonItem(ulCmnCount)) // || (ulTskCount != 0 && !pTask.CanDeliverTaskItem(ulTskCount))) // return (uint)TaskInterfaceConstants.TASK_AWARD_FAIL_GIVEN_ITEM; // TODO: Reputation non-negative check // if (lReputation != 0 && pTask.GetReputation() + lReputation < 0) // return (uint)TaskInterfaceConstants.TASK_AWARD_FAIL_REPUTATION; // 一切正常 // All good return 0u; } public static uint _get_item_count(TaskInterface pTask, uint ulItemId, bool bCommon) { return (uint)( bCommon ? pTask.GetCommonItemCount(ulItemId) : pTask.GetTaskItemCount(ulItemId) ); } // 占位:最大同时任务上限 // Placeholder: maximum simultaneous tasks cap private static int GetMaxSimultaneousCount(ActiveTaskList list) { return int.MaxValue; } // 占位:隐藏与标题任务上限 // Placeholder: hidden/title task caps private const int TASK_HIDDEN_COUNT = int.MaxValue; private const int TASK_TITLE_TASK_COUNT = int.MaxValue; private void LoadBinary(Stream fp) { LoadFixedDataFromBinFile(fp); // BMLogger.Log($"---- Pointer Log {m_FixedData.m_ID} ---- \n {pointerLog} "); LoadDescriptionBin(fp); pointerLog += $" After LoadDescriptionBin : {fp.Position}\n"; LoadTributeBin(fp); pointerLog += $" After LoadTributeBin : {fp.Position}\n"; // Check task type consistency # if _TASK_CLIENT SyncTaskType(); #else CheckMask(); #endif // namechar code = (namechar)m_ID; // m_DelvTaskTalk.load(fp); // convert_talk_text(&m_DelvTaskTalk, code); // 加载并转换发放任务对话 // Load and convert delivery task talk m_DelvTaskTalk = new talk_proc(); m_DelvTaskTalk.Read(fp); convert_talk_text(ref m_DelvTaskTalk, (char)m_FixedData.m_ID); // m_UnqualifiedTalk.load(fp); // convert_talk_text(&m_UnqualifiedTalk, code); // 加载并转换不符合条件对话 // Load and convert unqualified talk m_UnqualifiedTalk = new talk_proc(); m_UnqualifiedTalk.Read(fp); convert_talk_text(ref m_UnqualifiedTalk, (char)m_FixedData.m_ID); // m_DelvItemTalk.load(fp); // convert_talk_text(&m_DelvItemTalk, code); // 加载并转换发放物品对话 // Load and convert deliver item talk m_DelvItemTalk = new talk_proc(); m_DelvItemTalk.Read(fp); convert_talk_text(ref m_DelvItemTalk, (char)m_FixedData.m_ID); // m_ExeTalk.load(fp); // convert_talk_text(&m_ExeTalk, code); // 加载并转换执行任务对话 // Load and convert execute task talk m_ExeTalk = new talk_proc(); m_ExeTalk.Read(fp); convert_talk_text(ref m_ExeTalk, (char)m_FixedData.m_ID); // m_AwardTalk.load(fp); // convert_talk_text(&m_AwardTalk, code); // 加载并转换任务奖励对话 // Load and convert award talk m_AwardTalk = new talk_proc(); m_AwardTalk.Read(fp); convert_talk_text(ref m_AwardTalk, (char)m_FixedData.m_ID); // fread(&m_nSubCount, sizeof(m_nSubCount), 1, fp); // 读取子任务数量 // Read subtask count long readBytes = 0; m_nSubCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); pointerLog += $" After m_nSubCount : {fp.Position}\n"; // BMLogger.Log($"---- Pointer Log {m_FixedData.m_ID} ---- \n {pointerLog} "); // for (int i = 0; i < m_nSubCount; i++) // { // ATaskTempl* pSub = new ATaskTempl; // g_ulNewCount++; // AddSubTaskTempl(pSub); // pSub.LoadBinary(fp); // } // 上述C++逻辑的C#实现 // C# implementation of the above C++ logic if (m_nSubCount > 0) { for (int i = 0; i < m_nSubCount; i++) { var pSub = new ATaskTempl(); AddSubTaskTempl(pSub); pSub.LoadBinary(fp); } } SynchID(); //return true; } #region LoadFixedDataFromBinFile Handle private bool LoadFixedDataFromBinFile(Stream fp) { // for (int j = 1; j <= 20; j++) // { // Debug.LogError($"==== {j} ==="); // ConvertFixedData(fp, j); // Debug.LogError($"=========="); // } ConvertFixedData(fp, 1); return true; } public void convert_txt(char[] buffer, int len, char code) { if (buffer == null) return; if (len < 0) len = 0; if (len > buffer.Length) len = buffer.Length; for (int i = 0; i < len; i++) { buffer[i] = (char)(buffer[i] ^ code); } } public void convert_txt(ushort[] buffer, int len, char code) { if (buffer == null) return; if (len < 0) len = 0; if (len > buffer.Length) len = buffer.Length; for (int i = 0; i < len; i++) { buffer[i] = (ushort)(buffer[i] ^ code); } } private string pointerLog = ""; private void ConvertFixedData(Stream fp, int x2) { long readBytes = 0; // BMLogger.Log($"LoadFixedDataFromBinFile: {fp.Length}"); ATaskTemplFixedData fixedData = new ATaskTemplFixedData(); string logContent = ""; var originalPos = fp.Position; pointerLog += $" Berfore Read m_ID Position: {fp.Position}\n"; // Task ID fixedData.m_ID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // unsigned long m_ID; logContent += $"m_ID: {fixedData.m_ID} \n"; // Task Name (task_char m_szName[MAX_TASK_NAME_LEN];) fixedData.m_szName = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TASK_NAME_LEN, ref readBytes); //64 convert_txt(fixedData.m_szName, TaskTemplConstants.MAX_TASK_NAME_LEN, (char)(fixedData.m_ID)); logContent += $"m_szName: {ByteToStringUtils.UshortArrayToUnicodeString(fixedData.m_szName)}\n"; //68 // Has Signature (bool m_bHasSign;) fixedData.m_bHasSign = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bHasSign: {fixedData.m_bHasSign}\n"; //68 // Signature pointer (task_char* m_pszSignature;) // Only the pointer address is stored in the binary (skip 4 bytes) fp.Seek(4, SeekOrigin.Current); logContent += $"m_pszSignature: ushort[] and skip 4 bytes \n"; // Task Type (unsigned long m_ulType;) fixedData.m_ulType = AAssit.ReadFromBinaryOf(fp, ref readBytes);//value 103 logContent += $"Type: {fixedData.m_ulType}\n"; // Time Limit (unsigned long m_ulTimeLimit;) fixedData.m_ulTimeLimit = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulTimeLimit: {fixedData.m_ulTimeLimit}\n"; // Offline Fail (bool m_bOfflineFail;) fixedData.m_bOfflineFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bOfflineFail: {fixedData.m_bOfflineFail}\n"; // Absolute Fail (bool m_bAbsFail;) fixedData.m_bAbsFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bAbsFail: {fixedData.m_bAbsFail}\n"; // Absolute Fail Time (task_tm m_tmAbsFailTime;) fixedData.m_tmAbsFailTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_tmAbsFailTime.day: {fixedData.m_tmAbsFailTime.day}\n"; // (unsigned long m_ulAbsFailTime;) // commented out in C++ source // Item Not Take Off (bool m_bItemNotTakeOff;) fixedData.m_bItemNotTakeOff = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bItemNotTakeOff: {fixedData.m_bItemNotTakeOff}\n"; // Absolute Time (bool m_bAbsTime;) fixedData.m_bAbsTime = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bAbsTime: {fixedData.m_bAbsTime}\n"; // Timetable count (unsigned long m_ulTimetable;) fixedData.m_ulTimetable = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulTimetable: {fixedData.m_ulTimetable}\n"; // Timetable type (char m_tmType[MAX_TIMETABLE_SIZE];) fixedData.m_tmType = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes); logContent += $"m_tmType: {fixedData.m_tmType}\n"; // Start time pointer (task_tm* m_tmStart; [MAX_TIMETABLE_SIZE]) // if (m_ulTimetable) // { // m_tmStart = new task_tm[m_ulTimetable]; // g_ulNewCount++; // m_tmEnd = new task_tm[m_ulTimetable]; // g_ulNewCount++; // } // Start time pointer (task_tm* m_tmStart; [MAX_TIMETABLE_SIZE]) // Only the pointer address is stored in the binary (skip 4 bytes) fp.Seek(4, SeekOrigin.Current); logContent += $"m_tmStart: task_tm[] and skip 4 bytes \n"; // End time pointer (task_tm* m_tmEnd; [MAX_TIMETABLE_SIZE]) // Only the pointer address is stored in the binary (skip 4 bytes) fp.Seek(4, SeekOrigin.Current); logContent += $"m_tmEnd: task_tm[] and skip 4 bytes \n"; // Available frequency (long m_lAvailFrequency;) fixedData.m_lAvailFrequency = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_lAvailFrequency: {fixedData.m_lAvailFrequency}\n"; // Period limit (long m_lPeriodLimit;) fixedData.m_lPeriodLimit = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_lPeriodLimit: {fixedData.m_lPeriodLimit}\n"; // Choose one subtask (bool m_bChooseOne;) fixedData.m_bChooseOne = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bChooseOne: {fixedData.m_bChooseOne}\n"; // Random one subtask (bool m_bRandOne;) fixedData.m_bRandOne = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bRandOne: {fixedData.m_bRandOne}\n"; // bool m_bExeChildInOrder; // Whether subtasks are executed in order fixedData.m_bExeChildInOrder = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 是否子任务有顺序 // Whether subtasks are executed in order logContent += $"m_bExeChildInOrder: {fixedData.m_bExeChildInOrder}\n"; // bool m_bParentAlsoFail; // Whether the parent task fails if this one does fixedData.m_bParentAlsoFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 失败后是否认为父任务也失败 // Whether the parent task fails if this one does logContent += $"m_bParentAlsoFail: {fixedData.m_bParentAlsoFail}\n"; // Whether parent task succeeds after subtask succeeds // bool m_bParentAlsoSucc; fixedData.m_bParentAlsoSucc = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 子任务成功后父任务成功 // Whether parent task succeeds after subtask succeeds logContent += $"m_bParentAlsoSucc: {fixedData.m_bParentAlsoSucc}\n"; // Whether this task can be abandoned // bool m_bCanGiveUp; fixedData.m_bCanGiveUp = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 能否放弃此任务 // Whether this task can be abandoned logContent += $"m_bCanGiveUp: {fixedData.m_bCanGiveUp}\n"; // Whether the task can be repeated/completed again // bool m_bCanRedo; fixedData.m_bCanRedo = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 是否可重复完成 // Whether the task can be repeated/completed again logContent += $"m_bCanRedo: {fixedData.m_bCanRedo}\n"; // Whether task can be repeated after failure // bool m_bCanRedoAfterFailure; fixedData.m_bCanRedoAfterFailure = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 失败后是否可重新完成 // Whether task can be repeated after failure logContent += $"m_bCanRedoAfterFailure: {fixedData.m_bCanRedoAfterFailure}\n"; // Give up clears the task // bool m_bClearAsGiveUp; fixedData.m_bClearAsGiveUp = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 放弃清空任务 // Give up clears the task logContent += $"m_bClearAsGiveUp: {fixedData.m_bClearAsGiveUp}\n"; // Whether recording is needed // bool m_bNeedRecord; fixedData.m_bNeedRecord = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 是否需要记录 // Whether recording is needed logContent += $"m_bNeedRecord: {fixedData.m_bNeedRecord}\n"; // Player's death causes failure // bool m_bFailAsPlayerDie; fixedData.m_bFailAsPlayerDie = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 玩家被击杀是否认为失败 // Player's death causes failure logContent += $"m_bFailAsPlayerDie: {fixedData.m_bFailAsPlayerDie}\n"; // Maximum number of receivers // unsigned long m_ulMaxReceiver; fixedData.m_ulMaxReceiver = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 接受者上限 // Maximum number of receivers logContent += $"m_ulMaxReceiver: {fixedData.m_ulMaxReceiver}\n"; // Is in delivery zone // bool m_bDelvInZone; fixedData.m_bDelvInZone = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 发放区域 // Is in delivery zone logContent += $"m_bDelvInZone: {fixedData.m_bDelvInZone}\n"; // Delivery world id // unsigned long m_ulDelvWorld; fixedData.m_ulDelvWorld = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 发放世界 // Delivery world id logContent += $"m_ulDelvWorld: {fixedData.m_ulDelvWorld}\n"; // Number of delivery regions // unsigned long m_ulDelvRegionCnt; fixedData.m_ulDelvRegionCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 发放区域计数 // Number of delivery regions logContent += $"m_ulDelvRegionCnt: {fixedData.m_ulDelvRegionCnt}\n"; // Delivery regions pointer (Task_Region* m_pDelvRegion;) // Only the pointer address is stored in the binary (skip 4 bytes) fp.Seek(4, SeekOrigin.Current); logContent += $"m_pDelvRegion: Task_Region[] and skip 4 bytes \n\n"; // Enter region fail (bool m_bEnterRegionFail;) fixedData.m_bEnterRegionFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 进入区域任务失败 // Task fails when entering region logContent += $"m_bEnterRegionFail: {fixedData.m_bEnterRegionFail}\n\n"; // Enter region world (unsigned long m_ulEnterRegionWorld;) fixedData.m_ulEnterRegionWorld = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulEnterRegionWorld: {fixedData.m_ulEnterRegionWorld}\n\n"; // Enter region count (unsigned long m_ulEnterRegionCnt;) fixedData.m_ulEnterRegionCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulEnterRegionCnt: {fixedData.m_ulEnterRegionCnt}\n\n"; // Enter region pointer (Task_Region* m_pEnterRegion;) // Only the pointer address is stored in the binary (skip 4 bytes) fp.Seek(4, SeekOrigin.Current); logContent += $"m_pEnterRegion: Task_Region[] and skip 4 bytes \n\n"; // Leave region fail (bool m_bLeaveRegionFail;) fixedData.m_bLeaveRegionFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 离开区域任务失败 // Task fails when leaving region logContent += $"m_bLeaveRegionFail: {fixedData.m_bLeaveRegionFail}\n\n"; // Leave region world (unsigned long m_ulLeaveRegionWorld;) fixedData.m_ulLeaveRegionWorld = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulLeaveRegionWorld: {fixedData.m_ulLeaveRegionWorld}\n\n"; // Leave region count (unsigned long m_ulLeaveRegionCnt;) fixedData.m_ulLeaveRegionCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulLeaveRegionCnt: {fixedData.m_ulLeaveRegionCnt}\n\n"; // Leave region pointer (Task_Region* m_pLeaveRegion;) // Only the pointer address is stored in the binary (skip 4 bytes) fp.Seek(4, SeekOrigin.Current); logContent += $"m_pLeaveRegion: Task_Region[] and skip 4 bytes \n\n"; // Leave force fail (bool m_bLeaveForceFail;) fixedData.m_bLeaveForceFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 离开阵营失败 // Fails when leaving force logContent += $"m_bLeaveForceFail: {fixedData.m_bLeaveForceFail}\n\n"; // Teleport to specific point (bool m_bTransTo;) fixedData.m_bTransTo = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 传送到特定点 // Teleport to specific point logContent += $"m_bTransTo: {fixedData.m_bTransTo}\n\n"; // Teleport world id (unsigned long m_ulTransWldId;) fixedData.m_ulTransWldId = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulTransWldId: {fixedData.m_ulTransWldId}\n\n"; // Teleport position (ZONE_VERT m_TransPt;) fixedData.m_TransPt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_TransPt: ({fixedData.m_TransPt.x}, {fixedData.m_TransPt.y}, {fixedData.m_TransPt.z})\n\n"; // Monster controller (long m_lMonsCtrl;) fixedData.m_lMonsCtrl = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_lMonsCtrl: {fixedData.m_lMonsCtrl}\n\n"; // Trigger controller (bool m_bTrigCtrl;) fixedData.m_bTrigCtrl = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bTrigCtrl: {fixedData.m_bTrigCtrl}\n\n"; // Auto deliver (bool m_bAutoDeliver;) fixedData.m_bAutoDeliver = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bAutoDeliver: {fixedData.m_bAutoDeliver}\n\n"; // Display in exclusive UI (bool m_bDisplayInExclusiveUI;) fixedData.m_bDisplayInExclusiveUI = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bDisplayInExclusiveUI: {fixedData.m_bDisplayInExclusiveUI}\n\n"; // Ready to notify server (bool m_bReadyToNotifyServer;) fixedData.m_bReadyToNotifyServer = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bReadyToNotifyServer: {fixedData.m_bReadyToNotifyServer}\n\n"; // Used in token shop (bool m_bUsedInTokenShop;) fixedData.m_bUsedInTokenShop = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bUsedInTokenShop: {fixedData.m_bUsedInTokenShop}\n\n"; // Death trigger (bool m_bDeathTrig;) fixedData.m_bDeathTrig = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bDeathTrig: {fixedData.m_bDeathTrig}\n\n"; // Clear acquired (bool m_bClearAcquired;) fixedData.m_bClearAcquired = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bClearAcquired: {fixedData.m_bClearAcquired}\n\n"; // Suitable level (uint m_ulSuitableLevel;) fixedData.m_ulSuitableLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulSuitableLevel: {fixedData.m_ulSuitableLevel}\n\n"; // Show prompt (bool m_bShowPrompt;) fixedData.m_bShowPrompt = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowPrompt: {fixedData.m_bShowPrompt}\n\n"; // Key task (bool m_bKeyTask;) fixedData.m_bKeyTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bKeyTask: {fixedData.m_bKeyTask}\n\n"; // Delivery NPC (uint m_ulDelvNPC;) fixedData.m_ulDelvNPC = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulDelvNPC: {fixedData.m_ulDelvNPC}\n\n"; // Award NPC (uint m_ulAwardNPC;) fixedData.m_ulAwardNPC = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulAwardNPC: {fixedData.m_ulAwardNPC}\n\n"; // Skill task (bool m_bSkillTask;) fixedData.m_bSkillTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bSkillTask: {fixedData.m_bSkillTask}\n\n"; // Can seek out (bool m_bCanSeekOut;) fixedData.m_bCanSeekOut = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bCanSeekOut: {fixedData.m_bCanSeekOut}\n\n"; // Show direction (bool m_bShowDirection;) fixedData.m_bShowDirection = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowDirection: {fixedData.m_bShowDirection}\n\n"; // Marriage (bool m_bMarriage;) fixedData.m_bMarriage = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bMarriage: {fixedData.m_bMarriage}\n\n"; // Change global key/value count (uint m_ulChangeKeyCnt;) fixedData.m_ulChangeKeyCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulChangeKeyCnt: {fixedData.m_ulChangeKeyCnt}\n\n"; // Pointers to basic types (int* m_plChangeKey; int* m_plChangeKeyValue; bool* m_pbChangeType;) // Skip sizeof(int), sizeof(int), sizeof(bool) respectively per conversion rule fp.Seek(4, SeekOrigin.Current); logContent += $"m_plChangeKey: int[] pointer, skip 4 bytes (sizeof(int))\n\n"; fp.Seek(4, SeekOrigin.Current); logContent += $"m_plChangeKeyValue: int[] pointer, skip 4 bytes (sizeof(int))\n\n"; fp.Seek(4, SeekOrigin.Current); logContent += $"m_pbChangeType: bool[] pointer, skip 4 byte (sizeof(bool))\n\n"; // Switch scene fail (bool m_bSwitchSceneFail;) fixedData.m_bSwitchSceneFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bSwitchSceneFail: {fixedData.m_bSwitchSceneFail}\n\n"; // Hidden (bool m_bHidden;) fixedData.m_bHidden = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bHidden: {fixedData.m_bHidden}\n\n"; // Delivery skill (bool m_bDeliverySkill;) fixedData.m_bDeliverySkill = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bDeliverySkill: {fixedData.m_bDeliverySkill}\n\n"; // Delivered skill ID/Level (int m_iDeliveredSkillID; int m_iDeliveredSkillLevel;) fixedData.m_iDeliveredSkillID = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iDeliveredSkillID: {fixedData.m_iDeliveredSkillID}\n\n"; fixedData.m_iDeliveredSkillLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iDeliveredSkillLevel: {fixedData.m_iDeliveredSkillLevel}\n\n"; // Show GFX finished (bool m_bShowGfxFinished;) fixedData.m_bShowGfxFinished = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowGfxFinished: {fixedData.m_bShowGfxFinished}\n\n"; // Change PQ ranking (bool m_bChangePQRanking;) fixedData.m_bChangePQRanking = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bChangePQRanking: {fixedData.m_bChangePQRanking}\n\n"; // Compare items and inventory (bool m_bCompareItemAndInventory;) fixedData.m_bCompareItemAndInventory = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bCompareItemAndInventory: {fixedData.m_bCompareItemAndInventory}\n\n"; // Inventory slots (uint m_ulInventorySlotNum;) fixedData.m_ulInventorySlotNum = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulInventorySlotNum: {fixedData.m_ulInventorySlotNum}\n\n"; // PQ task (bool m_bPQTask;) fixedData.m_bPQTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPQTask: {fixedData.m_bPQTask}\n\n"; // PQ expression count (uint m_ulPQExpCnt;) fixedData.m_ulPQExpCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPQExpCnt: {fixedData.m_ulPQExpCnt}\n\n"; // PQ expressions pointer (byte[,] m_pszPQExp;) // Only the pointer address is stored in the binary (skip 1 bytes) fp.Seek(4, SeekOrigin.Current); logContent += $"m_pszPQExp: byte[,] pointer, skip 4 bytes \n\n"; // PQ expression array pointer (TASK_EXPRESSION[,] m_pPQExpArr;) // Only the pointer address is stored in the binary (skip 4 bytes) fp.Seek(4, SeekOrigin.Current); logContent += $"m_pPQExpArr: TASK_EXPRESSION[,] pointer, skip 4 bytes \n\n"; // Is PQ subtask (bool m_bPQSubTask;) fixedData.m_bPQSubTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPQSubTask: {fixedData.m_bPQSubTask}\n\n"; // Clear contribution on start (bool m_bClearContrib;) fixedData.m_bClearContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bClearContrib: {fixedData.m_bClearContrib}\n\n"; // Monster contribution count (uint m_ulMonsterContribCnt;) fixedData.m_ulMonsterContribCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulMonsterContribCnt: {fixedData.m_ulMonsterContribCnt}\n\n"; // Monster contribution pointer (MONSTERS_CONTRIB[] m_MonstersContrib;) // Only the pointer address is stored in the binary (skip 4 bytes) fp.Seek(4, SeekOrigin.Current); logContent += $"m_MonstersContrib: MONSTERS_CONTRIB[] pointer, skip 4 bytes \n\n"; // Account Task related fixedData.m_iPremNeedRecordTasksNum = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremNeedRecordTasksNum: {fixedData.m_iPremNeedRecordTasksNum}\n\n"; fixedData.m_bShowByNeedRecordTasksNum = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByNeedRecordTasksNum: {fixedData.m_bShowByNeedRecordTasksNum}\n\n"; fixedData.m_iPremiseFactionContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremiseFactionContrib: {fixedData.m_iPremiseFactionContrib}\n\n"; fixedData.m_bShowByFactionContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByFactionContrib: {fixedData.m_bShowByFactionContrib}\n\n"; fixedData.m_bAccountTaskLimit = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bAccountTaskLimit: {fixedData.m_bAccountTaskLimit}\n\n"; fixedData.m_bRoleTaskLimit = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bRoleTaskLimit: {fixedData.m_bRoleTaskLimit}\n\n"; fixedData.m_ulAccountTaskLimitCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulAccountTaskLimitCnt: {fixedData.m_ulAccountTaskLimitCnt}\n\n"; fixedData.m_bLeaveFactionFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bLeaveFactionFail: {fixedData.m_bLeaveFactionFail}\n\n"; fixedData.m_bNotIncCntWhenFailed = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bNotIncCntWhenFailed: {fixedData.m_bNotIncCntWhenFailed}\n\n"; fixedData.m_bNotClearItemWhenFailed = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bNotClearItemWhenFailed: {fixedData.m_bNotClearItemWhenFailed}\n\n"; fixedData.m_bDisplayInTitleTaskUI = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bDisplayInTitleTaskUI: {fixedData.m_bDisplayInTitleTaskUI}\n\n"; // Opening conditions fixedData.m_ucPremiseTransformedForm = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ucPremiseTransformedForm: {fixedData.m_ucPremiseTransformedForm}\n\n"; fixedData.m_bShowByTransformed = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByTransformed: {fixedData.m_bShowByTransformed}\n\n"; fixedData.m_ulPremise_Lev_Min = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremise_Lev_Min: {fixedData.m_ulPremise_Lev_Min}\n\n"; fixedData.m_ulPremise_Lev_Max = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremise_Lev_Max: {fixedData.m_ulPremise_Lev_Max}\n\n"; fixedData.m_bPremCheckMaxHistoryLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_bPremCheckMaxHistoryLevel: {fixedData.m_bPremCheckMaxHistoryLevel}\n\n"; fixedData.m_bShowByLev = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByLev: {fixedData.m_bShowByLev}\n\n"; fixedData.m_bPremCheckReincarnation = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPremCheckReincarnation: {fixedData.m_bPremCheckReincarnation}\n\n"; fixedData.m_ulPremReincarnationMin = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremReincarnationMin: {fixedData.m_ulPremReincarnationMin}\n\n"; fixedData.m_ulPremReincarnationMax = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremReincarnationMax: {fixedData.m_ulPremReincarnationMax}\n\n"; fixedData.m_bShowByReincarnation = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByReincarnation: {fixedData.m_bShowByReincarnation}\n\n"; fixedData.m_bPremCheckRealmLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPremCheckRealmLevel: {fixedData.m_bPremCheckRealmLevel}\n\n"; fixedData.m_ulPremRealmLevelMin = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremRealmLevelMin: {fixedData.m_ulPremRealmLevelMin}\n\n"; fixedData.m_ulPremRealmLevelMax = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremRealmLevelMax: {fixedData.m_ulPremRealmLevelMax}\n\n"; fixedData.m_bPremCheckRealmExpFull = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPremCheckRealmExpFull: {fixedData.m_bPremCheckRealmExpFull}\n\n"; fixedData.m_bShowByRealmLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByRealmLevel: {fixedData.m_bShowByRealmLevel}\n\n"; fixedData.m_ulPremItems = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremItems: {fixedData.m_ulPremItems}\n\n"; // PremItems pointer (ITEM_WANTED[] m_PremItems;) fp.Seek(4, SeekOrigin.Current); logContent += $"m_PremItems: ITEM_WANTED[] pointer, skip 4 bytes \n\n"; fixedData.m_bShowByItems = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByItems: {fixedData.m_bShowByItems}\n\n"; fixedData.m_bPremItemsAnyOne = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPremItemsAnyOne: {fixedData.m_bPremItemsAnyOne}\n\n"; fixedData.m_ulGivenItems = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulGivenItems: {fixedData.m_ulGivenItems}\n\n"; fixedData.m_ulGivenCmnCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulGivenCmnCount: {fixedData.m_ulGivenCmnCount}\n\n"; fixedData.m_ulGivenTskCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulGivenTskCount: {fixedData.m_ulGivenTskCount}\n\n"; // GivenItems pointer (ITEM_WANTED[] m_GivenItems;) fp.Seek(4, SeekOrigin.Current); logContent += $"m_GivenItems: ITEM_WANTED[] pointer, skip 4 bytes \n\n"; fixedData.m_ulPremise_Deposit = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremise_Deposit: {fixedData.m_ulPremise_Deposit}\n\n"; fixedData.m_bShowByDeposit = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByDeposit: {fixedData.m_bShowByDeposit}\n\n"; fixedData.m_lPremise_Reputation = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_lPremise_Reputation: {fixedData.m_lPremise_Reputation}\n\n"; fixedData.m_lPremise_RepuMax = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_lPremise_RepuMax: {fixedData.m_lPremise_RepuMax}\n\n"; fixedData.m_bShowByRepu = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByRepu: {fixedData.m_bShowByRepu}\n\n"; fixedData.m_ulPremise_Task_Count = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremise_Task_Count: {fixedData.m_ulPremise_Task_Count}\n\n"; fixedData.m_ulPremise_Tasks = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_PREM_TASK_COUNT, ref readBytes); logContent += $"m_ulPremise_Tasks[0..{TaskTemplConstants.MAX_PREM_TASK_COUNT - 1}] loaded\n\n"; fixedData.m_bShowByPreTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByPreTask: {fixedData.m_bShowByPreTask}\n\n"; fixedData.m_ulPremise_Task_Least_Num = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremise_Task_Least_Num: {fixedData.m_ulPremise_Task_Least_Num}\n\n"; fixedData.m_ulPremise_Period = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremise_Period: {fixedData.m_ulPremise_Period}\n\n"; fixedData.m_bShowByPeriod = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByPeriod: {fixedData.m_bShowByPeriod}\n\n"; fixedData.m_ulPremise_Faction = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremise_Faction: {fixedData.m_ulPremise_Faction}\n\n"; fixedData.m_iPremise_FactionRole = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremise_FactionRole: {fixedData.m_iPremise_FactionRole}\n\n"; fixedData.m_bShowByFaction = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByFaction: {fixedData.m_bShowByFaction}\n\n"; // Gender and occupation restrictions fixedData.m_ulGender = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulGender: {fixedData.m_ulGender}\n\n"; fixedData.m_bShowByGender = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByGender: {fixedData.m_bShowByGender}\n\n"; fixedData.m_ulOccupations = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulOccupations: {fixedData.m_ulOccupations}\n\n"; fixedData.m_Occupations = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_OCCUPATIONS, ref readBytes); logContent += $"m_Occupations[0..{TaskTemplConstants.MAX_OCCUPATIONS - 1}] loaded\n\n"; fixedData.m_bShowByOccup = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByOccup: {fixedData.m_bShowByOccup}\n\n"; // Spouse related fixedData.m_bPremise_Spouse = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPremise_Spouse: {fixedData.m_bPremise_Spouse}\n\n"; fixedData.m_bShowBySpouse = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowBySpouse: {fixedData.m_bShowBySpouse}\n\n"; fixedData.m_bPremiseWeddingOwner = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPremiseWeddingOwner: {fixedData.m_bPremiseWeddingOwner}\n\n"; fixedData.m_bShowByWeddingOwner = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByWeddingOwner: {fixedData.m_bShowByWeddingOwner}\n\n"; // GM and shield user fixedData.m_bGM = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bGM: {fixedData.m_bGM}\n\n"; fixedData.m_bShieldUser = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShieldUser: {fixedData.m_bShieldUser}\n\n"; // RMB limits fixedData.m_bShowByRMB = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByRMB: {fixedData.m_bShowByRMB}\n\n"; fixedData.m_ulPremRMBMin = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremRMBMin: {fixedData.m_ulPremRMBMin}\n\n"; fixedData.m_ulPremRMBMax = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremRMBMax: {fixedData.m_ulPremRMBMax}\n\n"; // Character time fixedData.m_bCharTime = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bCharTime: {fixedData.m_bCharTime}\n\n"; fixedData.m_bShowByCharTime = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByCharTime: {fixedData.m_bShowByCharTime}\n\n"; fixedData.m_iCharStartTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iCharStartTime: {fixedData.m_iCharStartTime}\n\n"; fixedData.m_iCharEndTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iCharEndTime: {fixedData.m_iCharEndTime}\n\n"; fixedData.m_tmCharEndTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_tmCharEndTime.day: {fixedData.m_tmCharEndTime.day}\n\n"; fixedData.m_ulCharTimeGreaterThan = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulCharTimeGreaterThan: {fixedData.m_ulCharTimeGreaterThan}\n\n"; // Related and mutex tasks fixedData.m_ulPremise_Cotask = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremise_Cotask: {fixedData.m_ulPremise_Cotask}\n\n"; fixedData.m_ulCoTaskCond = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulCoTaskCond: {fixedData.m_ulCoTaskCond}\n\n"; fixedData.m_ulMutexTaskCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulMutexTaskCount: {fixedData.m_ulMutexTaskCount}\n\n"; fixedData.m_ulMutexTasks = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_MUTEX_TASK_COUNT, ref readBytes); logContent += $"m_ulMutexTasks[0..{TaskTemplConstants.MAX_MUTEX_TASK_COUNT - 1}] loaded\n\n"; // Living skills levels (C++ long . 4 bytes). Read as int and widen to long var skillLevelsInt = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_LIVING_SKILLS, ref readBytes); fixedData.m_lSkillLev = Array.ConvertAll(skillLevelsInt, v => (long)v); logContent += $"m_lSkillLev[0..{TaskTemplConstants.MAX_LIVING_SKILLS - 1}] loaded\n\n"; // Dynamic task type and special award fixedData.m_DynTaskType = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_DynTaskType: {fixedData.m_DynTaskType}\n\n"; fixedData.m_ulSpecialAward = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulSpecialAward: {fixedData.m_ulSpecialAward}\n\n"; // Team information fixedData.m_bTeamwork = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bTeamwork: {fixedData.m_bTeamwork}\n\n"; fixedData.m_bRcvByTeam = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bRcvByTeam: {fixedData.m_bRcvByTeam}\n\n"; fixedData.m_bSharedTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bSharedTask: {fixedData.m_bSharedTask}\n\n"; fixedData.m_bSharedAchieved = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bSharedAchieved: {fixedData.m_bSharedAchieved}\n\n"; fixedData.m_bCheckTeammate = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bCheckTeammate: {fixedData.m_bCheckTeammate}\n\n"; fixedData.m_fTeammateDist = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_fTeammateDist: {fixedData.m_fTeammateDist}\n\n"; fixedData.m_bAllFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bAllFail: {fixedData.m_bAllFail}\n\n"; fixedData.m_bCapFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bCapFail: {fixedData.m_bCapFail}\n\n"; fixedData.m_bCapSucc = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bCapSucc: {fixedData.m_bCapSucc}\n\n"; fixedData.m_fSuccDist = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_fSuccDist: {fixedData.m_fSuccDist}\n\n"; fixedData.m_bDismAsSelfFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bDismAsSelfFail: {fixedData.m_bDismAsSelfFail}\n\n"; fixedData.m_bRcvChckMem = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bRcvChckMem: {fixedData.m_bRcvChckMem}\n\n"; fixedData.m_fRcvMemDist = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_fRcvMemDist: {fixedData.m_fRcvMemDist}\n\n"; fixedData.m_bCntByMemPos = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bCntByMemPos: {fixedData.m_bCntByMemPos}\n\n"; fixedData.m_fCntMemDist = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_fCntMemDist: {fixedData.m_fCntMemDist}\n\n"; fixedData.m_bAllSucc = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bAllSucc: {fixedData.m_bAllSucc}\n\n"; fixedData.m_bCoupleOnly = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bCoupleOnly: {fixedData.m_bCoupleOnly}\n\n"; fixedData.m_bDistinguishedOcc = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bDistinguishedOcc: {fixedData.m_bDistinguishedOcc}\n\n"; fixedData.m_ulTeamMemsWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulTeamMemsWanted: {fixedData.m_ulTeamMemsWanted}\n\n"; // TEAM_MEM_WANTED pointer array fp.Seek(4, SeekOrigin.Current); logContent += $"m_TeamMemsWanted: TEAM_MEM_WANTED[] pointer, skip 4 bytes \n\n"; fixedData.m_bShowByTeam = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByTeam: {fixedData.m_bShowByTeam}\n\n"; // Premise global key/value fixedData.m_bPremNeedComp = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPremNeedComp: {fixedData.m_bPremNeedComp}\n\n"; fixedData.m_nPremExp1AndOrExp2 = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_nPremExp1AndOrExp2: {fixedData.m_nPremExp1AndOrExp2}\n\n"; fixedData.m_Prem1KeyValue = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_Prem1KeyValue loaded\n\n"; fixedData.m_Prem2KeyValue = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_Prem2KeyValue loaded\n\n"; // Force related fixedData.m_bPremCheckForce = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPremCheckForce: {fixedData.m_bPremCheckForce}\n\n"; fixedData.m_iPremForce = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremForce: {fixedData.m_iPremForce}\n\n"; fixedData.m_bShowByForce = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByForce: {fixedData.m_bShowByForce}\n\n"; fixedData.m_iPremForceReputation = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremForceReputation: {fixedData.m_iPremForceReputation}\n\n"; fixedData.m_bShowByForceReputation = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByForceReputation: {fixedData.m_bShowByForceReputation}\n\n"; fixedData.m_iPremForceContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremForceContribution: {fixedData.m_iPremForceContribution}\n\n"; fixedData.m_bShowByForceContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByForceContribution: {fixedData.m_bShowByForceContribution}\n\n"; fixedData.m_iPremForceExp = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremForceExp: {fixedData.m_iPremForceExp}\n\n"; fixedData.m_bShowByForceExp = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByForceExp: {fixedData.m_bShowByForceExp}\n\n"; fixedData.m_iPremForceSP = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremForceSP: {fixedData.m_iPremForceSP}\n\n"; fixedData.m_bShowByForceSP = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByForceSP: {fixedData.m_bShowByForceSP}\n\n"; fixedData.m_iPremForceActivityLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremForceActivityLevel: {fixedData.m_iPremForceActivityLevel}\n\n"; fixedData.m_bShowByForceActivityLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByForceActivityLevel: {fixedData.m_bShowByForceActivityLevel}\n\n"; // King / Not in team / Titles fixedData.m_bPremIsKing = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPremIsKing: {fixedData.m_bPremIsKing}\n\n"; fixedData.m_bShowByKing = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByKing: {fixedData.m_bShowByKing}\n\n"; fixedData.m_bPremNotInTeam = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bPremNotInTeam: {fixedData.m_bPremNotInTeam}\n\n"; fixedData.m_bShowByNotInTeam = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByNotInTeam: {fixedData.m_bShowByNotInTeam}\n\n"; fixedData.m_iPremTitleNumTotal = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremTitleNumTotal: {fixedData.m_iPremTitleNumTotal}\n\n"; fixedData.m_iPremTitleNumRequired = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremTitleNumRequired: {fixedData.m_iPremTitleNumRequired}\n\n"; // PremTitles pointer (int[]) fp.Seek(4, SeekOrigin.Current); logContent += $"m_PremTitles: int[] pointer, skip 4 bytes \n\n"; fixedData.m_bShowByTitle = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByTitle: {fixedData.m_bShowByTitle}\n\n"; var premHistoryIdx = AAssit.ReadArrayFromBinary(fp, 2, ref readBytes); fixedData.m_iPremHistoryStageIndex = premHistoryIdx; logContent += $"m_iPremHistoryStageIndex[0..1] loaded\n\n"; fixedData.m_bShowByHistoryStage = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByHistoryStage: {fixedData.m_bShowByHistoryStage}\n\n"; fixedData.m_ulPremGeneralCardCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremGeneralCardCount: {fixedData.m_ulPremGeneralCardCount}\n\n"; fixedData.m_bShowByGeneralCard = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByGeneralCard: {fixedData.m_bShowByGeneralCard}\n\n"; fixedData.m_iPremGeneralCardRank = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iPremGeneralCardRank: {fixedData.m_iPremGeneralCardRank}\n\n"; fixedData.m_ulPremGeneralCardRankCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPremGeneralCardRankCount: {fixedData.m_ulPremGeneralCardRankCount}\n\n"; fixedData.m_bShowByGeneralCardRank = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bShowByGeneralCardRank: {fixedData.m_bShowByGeneralCardRank}\n\n"; // Completion methods and conditions fixedData.m_enumMethod = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_enumMethod: {fixedData.m_enumMethod}\n\n"; fixedData.m_enumFinishType = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_enumFinishType: {fixedData.m_enumFinishType}\n\n"; // Task methods fixedData.m_ulPlayerWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPlayerWanted: {fixedData.m_ulPlayerWanted}\n\n"; // PLAYER_WANTED pointer fp.Seek(4, SeekOrigin.Current); logContent += $"m_PlayerWanted: PLAYER_WANTED[] pointer, skip 4 bytes \n\n"; fixedData.m_ulMonsterWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulMonsterWanted: {fixedData.m_ulMonsterWanted}\n\n"; // MONSTER_WANTED pointer fp.Seek(4, SeekOrigin.Current); logContent += $"m_MonsterWanted: MONSTER_WANTED[] pointer, skip 4 bytes \n\n"; fixedData.m_ulItemsWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulItemsWanted: {fixedData.m_ulItemsWanted}\n\n"; // ITEM_WANTED pointer fp.Seek(4, SeekOrigin.Current); logContent += $"m_ItemsWanted: ITEM_WANTED[] pointer, skip 4 bytes \n\n"; fixedData.m_ulGoldWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulGoldWanted: {fixedData.m_ulGoldWanted}\n\n"; fixedData.m_iFactionContribWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iFactionContribWanted: {fixedData.m_iFactionContribWanted}\n\n"; fixedData.m_iFactionExpContribWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iFactionExpContribWanted: {fixedData.m_iFactionExpContribWanted}\n\n"; fixedData.m_ulNPCToProtect = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulNPCToProtect: {fixedData.m_ulNPCToProtect}\n\n"; fixedData.m_ulProtectTimeLen = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulProtectTimeLen: {fixedData.m_ulProtectTimeLen}\n\n"; fixedData.m_ulNPCMoving = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulNPCMoving: {fixedData.m_ulNPCMoving}\n\n"; fixedData.m_ulNPCDestSite = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulNPCDestSite: {fixedData.m_ulNPCDestSite}\n\n"; // Reach site pointer and counts fp.Seek(4, SeekOrigin.Current); logContent += $"m_pReachSite: Task_Region[] pointer, skip 4 bytes \n\n"; fixedData.m_ulReachSiteCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulReachSiteCnt: {fixedData.m_ulReachSiteCnt}\n\n"; fixedData.m_ulReachSiteId = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulReachSiteId: {fixedData.m_ulReachSiteId}\n\n"; fixedData.m_ulWaitTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulWaitTime: {fixedData.m_ulWaitTime}\n\n"; // Treasure map (TREA) fixedData.m_TreasureStartZone = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_TreasureStartZone: ({fixedData.m_TreasureStartZone.x}, {fixedData.m_TreasureStartZone.y}, {fixedData.m_TreasureStartZone.z})\n\n"; fixedData.m_ucZonesNumX = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ucZonesNumX: {fixedData.m_ucZonesNumX}\n\n"; fixedData.m_ucZonesNumZ = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ucZonesNumZ: {fixedData.m_ucZonesNumZ}\n\n"; fixedData.m_ucZoneSide = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ucZoneSide: {fixedData.m_ucZoneSide}\n\n"; // Leave site pointer and counts fp.Seek(4, SeekOrigin.Current); logContent += $"m_pLeaveSite: Task_Region[] pointer, skip 4 bytes \n\n"; fixedData.m_ulLeaveSiteCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulLeaveSiteCnt: {fixedData.m_ulLeaveSiteCnt}\n\n"; fixedData.m_ulLeaveSiteId = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulLeaveSiteId: {fixedData.m_ulLeaveSiteId}\n\n"; // Finish global key/value fixedData.m_bFinNeedComp = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bFinNeedComp: {fixedData.m_bFinNeedComp}\n\n"; fixedData.m_nFinExp1AndOrExp2 = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_nFinExp1AndOrExp2: {fixedData.m_nFinExp1AndOrExp2}\n\n"; fixedData.m_Fin1KeyValue = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_Fin1KeyValue loaded\n\n"; fixedData.m_Fin2KeyValue = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_Fin2KeyValue loaded\n\n"; // Expressions to display fixedData.m_ulExpCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulExpCnt: {fixedData.m_ulExpCnt}\n\n"; // Pointers for expression storage fp.Seek(4, SeekOrigin.Current); logContent += $"m_pszExp: byte[,] pointer, skip 4 bytes \n\n"; fp.Seek(4, SeekOrigin.Current); logContent += $"m_pExpArr: TASK_EXPRESSION[,] pointer, skip 4 bytes \n\n"; // Task char prompts fixedData.m_ulTaskCharCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulTaskCharCnt: {fixedData.m_ulTaskCharCnt}\n\n"; fp.Seek(4, SeekOrigin.Current); logContent += $"m_pTaskChar: ushort[,] pointer, skip 4 bytes \n\n"; // Transformation state fixedData.m_ucTransformedForm = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ucTransformedForm: {fixedData.m_ucTransformedForm}\n\n"; // Level/Reincarnation/Realm fixedData.m_ulReachLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulReachLevel: {fixedData.m_ulReachLevel}\n\n"; fixedData.m_ulReachReincarnationCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulReachReincarnationCount: {fixedData.m_ulReachReincarnationCount}\n\n"; fixedData.m_ulReachRealmLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulReachRealmLevel: {fixedData.m_ulReachRealmLevel}\n\n"; fixedData.m_uiEmotion = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_uiEmotion: {fixedData.m_uiEmotion}\n\n"; // Award types and pointers fixedData.m_ulAwardType_S = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulAwardType_S: {fixedData.m_ulAwardType_S}\n\n"; fixedData.m_ulAwardType_F = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulAwardType_F: {fixedData.m_ulAwardType_F}\n\n"; // AWARD_DATA pointers fp.Seek(4, SeekOrigin.Current); logContent += $"m_Award_S_ptr: AWARD_DATA* pointer, skip 4 bytes \n\n"; fp.Seek(4, SeekOrigin.Current); logContent += $"m_Award_F_ptr: AWARD_DATA* pointer, skip 4 bytes \n\n"; // Ratio and items scale pointers fp.Seek(4, SeekOrigin.Current); logContent += $"m_AwByRatio_S_ptr: AWARD_RATIO_SCALE* pointer, skip 4 bytes \n\n"; fp.Seek(4, SeekOrigin.Current); logContent += $"m_AwByRatio_F_ptr: AWARD_RATIO_SCALE* pointer, skip 4 bytes \n\n"; fp.Seek(4, SeekOrigin.Current); logContent += $"m_AwByItems_S_ptr: AWARD_ITEMS_SCALE* pointer, skip 4 bytes \n\n"; fp.Seek(4, SeekOrigin.Current); logContent += $"m_AwByItems_F_ptr: AWARD_ITEMS_SCALE* pointer, skip 4 bytes \n\n"; // Hierarchy fixedData.m_ulParent = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulParent: {fixedData.m_ulParent}\n\n"; fixedData.m_ulPrevSibling = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPrevSibling: {fixedData.m_ulPrevSibling}\n\n"; fixedData.m_ulNextSibling = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulNextSibling: {fixedData.m_ulNextSibling}\n\n"; fixedData.m_ulFirstChild = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulFirstChild: {fixedData.m_ulFirstChild}\n\n"; // Library tasks fixedData.m_bIsLibraryTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bIsLibraryTask: {fixedData.m_bIsLibraryTask}\n\n"; fixedData.m_fLibraryTasksProbability = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_fLibraryTasksProbability: {fixedData.m_fLibraryTasksProbability}\n\n"; fixedData.m_bIsUniqueStorageTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bIsUniqueStorageTask: {fixedData.m_bIsUniqueStorageTask}\n\n"; fixedData.m_iWorldContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iWorldContribution: {fixedData.m_iWorldContribution}\n\n"; pointerLog += $" After read Raw of FixedData: {fp.Position} \n"; // BMLogger.LogError($" === Task Data {fixedData.m_ID} loaded === \n {logContent} "); ConvertPointersOfFixedData(fp, ref fixedData, ref readBytes); //fp.Seek(originalPos, SeekOrigin.Begin); m_FixedData = fixedData; return; } private void ConvertPointersOfFixedData(Stream fp, ref ATaskTemplFixedData fixedData, ref long readBytes) { string logContent = ""; // C++ pointer: task_char* m_pszSignature; /*if (m_bHasSign) { m_pszSignature = new task_char[MAX_TASK_NAME_LEN]; g_ulNewCount++; fread(m_pszSignature, sizeof(task_char), MAX_TASK_NAME_LEN, fp); convert_txt(m_pszSignature, MAX_TASK_NAME_LEN, (namechar)m_ID); }*/ if (fixedData.m_bHasSign) { fixedData.m_pszSignature = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TASK_NAME_LEN, ref readBytes); //64 convert_txt(fixedData.m_pszSignature, TaskTemplConstants.MAX_TASK_NAME_LEN, (char)(fixedData.m_ID)); logContent += $"m_pszSignature: {ByteToStringUtils.UshortArrayToUnicodeString(fixedData.m_pszSignature)}\n"; //68 } else { logContent += $"m_pszSignature: {fixedData.m_pszSignature}\n"; } // C++ struct: task_tm* m_tmStart; task_tm* m_tmEnd; /*if (m_ulTimetable) { m_tmStart = new task_tm[m_ulTimetable]; g_ulNewCount++; m_tmEnd = new task_tm[m_ulTimetable]; g_ulNewCount++; } for (i = 0; i < m_ulTimetable; i++) { fread(&m_tmStart[i], sizeof(task_tm), 1, fp); fread(&m_tmEnd[i], sizeof(task_tm), 1, fp); }*/ if (fixedData.m_ulTimetable > 0) { fixedData.m_tmStart = new task_tm[fixedData.m_ulTimetable]; fixedData.m_tmEnd = new task_tm[fixedData.m_ulTimetable]; string tmStartLog = ""; string tmEndLog = ""; for (int i=0; i < fixedData.m_ulTimetable; i++) { fixedData.m_tmStart[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); fixedData.m_tmEnd[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); tmStartLog += $"{i} = {fixedData.m_tmStart[i].GetLog()} || "; tmEndLog += $"{i} = {fixedData.m_tmEnd[i].GetLog()} || "; } logContent += $"m_tmStart: {tmStartLog} \n"; logContent += $"m_tmEnd: {tmEndLog} \n"; } // C++ pointer arrays: long* m_plChangeKey; long* m_plChangeKeyValue; bool* m_pbChangeType; /*if (m_ulChangeKeyCnt) { m_plChangeKey = new long[m_ulChangeKeyCnt]; m_plChangeKeyValue = new long[m_ulChangeKeyCnt]; m_pbChangeType = new bool[m_ulChangeKeyCnt]; } for (i=0; i 0) { fixedData.m_plChangeKey = new int[fixedData.m_ulChangeKeyCnt]; fixedData.m_plChangeKeyValue = new int[fixedData.m_ulChangeKeyCnt]; fixedData.m_pbChangeType = new bool[fixedData.m_ulChangeKeyCnt]; string changeKeyLog = ""; string changeKeyValueLog = ""; string changeTypeLog = ""; for (int i=0; i < fixedData.m_ulChangeKeyCnt; i++) { fixedData.m_plChangeKey[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); fixedData.m_plChangeKeyValue[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); fixedData.m_pbChangeType[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; changeKeyLog += $"{i} = {fixedData.m_plChangeKey[i]} || "; changeKeyValueLog += $"{i} = {fixedData.m_plChangeKeyValue[i]} || "; changeTypeLog += $"{i} = {fixedData.m_pbChangeType[i]} || "; } logContent += $"m_plChangeKey: {changeKeyLog} \n"; logContent += $"m_plChangeKeyValue: {changeKeyValueLog} \n"; logContent += $"m_pbChangeType: {changeTypeLog} \n"; } else { logContent += $"m_plChangeKey: {fixedData.m_plChangeKey}\n"; logContent += $"m_plChangeKeyValue: {fixedData.m_plChangeKeyValue}\n"; logContent += $"m_pbChangeType: {fixedData.m_pbChangeType}\n"; } /*if (m_ulPQExpCnt) { m_pszPQExp = new char[m_ulPQExpCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN]; memset(m_pszPQExp, 0, m_ulPQExpCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN); m_pPQExpArr = new TASK_EXPRESSION[m_ulPQExpCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN]; memset(m_pPQExpArr, 0, sizeof(TASK_EXPRESSION)*m_ulPQExpCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN); for (i=0; i 0) { int rowCount = (int)fixedData.m_ulPQExpCnt; int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; fixedData.m_pszPQExp = new byte[rowCount, colCount]; fixedData.m_pPQExpArr = new TASK_EXPRESSION[rowCount, colCount]; // serialize m_pszPQExp and m_pPQExpArr fixedData.m_pszPQExp_Seri = new byte[rowCount * colCount]; fixedData.m_pPQExpArr_Seri = new TASK_EXPRESSION[rowCount * colCount]; for (int i = 0; i < rowCount; i++) { // Read PQ expression display bytes (length TASK_AWARD_MAX_DISPLAY_CHAR_LEN) byte[] expBytes = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); for (int j = 0; j < colCount; j++) { fixedData.m_pszPQExp[i, j] = expBytes[j]; fixedData.m_pszPQExp_Seri[i * colCount + j] = expBytes[j]; } // Read TASK_EXPRESSION array (length TASK_AWARD_MAX_DISPLAY_CHAR_LEN) for (int j = 0; j < colCount; j++) { fixedData.m_pPQExpArr[i, j] = AAssit.ReadFromBinaryOf(fp, ref readBytes); fixedData.m_pPQExpArr_Seri[i * colCount + j] = fixedData.m_pPQExpArr[i, j]; } } logContent += $"m_pszPQExp and m_pPQExpArr loaded, count: {fixedData.m_ulPQExpCnt} (each {TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN})\n"; } else { logContent += $"m_pszPQExp: {fixedData.m_pszPQExp}\n"; logContent += $"m_pPQExpArr: {fixedData.m_pPQExpArr}\n"; } // Convert C++ lines 3866-3896 if (fixedData.m_ulMonsterContribCnt > 0) { fixedData.m_MonstersContrib = new MONSTERS_CONTRIB[fixedData.m_ulMonsterContribCnt]; string mcLog = ""; for (int i = 0; i < fixedData.m_ulMonsterContribCnt; i++) { fixedData.m_MonstersContrib[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); mcLog += $"{i} = (MonsterId:{fixedData.m_MonstersContrib[i].m_ulMonsterTemplId}) || "; } logContent += $"m_MonstersContrib: {mcLog}\n"; } else { logContent += $"m_MonstersContrib: {fixedData.m_MonstersContrib}\n"; } // C++ lines 3879 - 3890 if (fixedData.m_ulDelvRegionCnt > 0) { fixedData.m_pDelvRegion = new Task_Region[fixedData.m_ulDelvRegionCnt]; string dLog = ""; for (int i = 0; i < fixedData.m_ulDelvRegionCnt; i++) { fixedData.m_pDelvRegion[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); dLog += $" {i} = (RegionId:{fixedData.m_pDelvRegion[i].GetLog()}) || "; } logContent += $"m_pDelvRegion: {dLog}\n"; } else { fixedData.m_pDelvRegion = null; logContent += $"m_pDelvRegion: {fixedData.m_pDelvRegion}\n"; } // C++ lines 3891-3902: enter regions if (fixedData.m_ulEnterRegionCnt > 0) { fixedData.m_pEnterRegion = new Task_Region[fixedData.m_ulEnterRegionCnt]; string eLog = ""; for (int i = 0; i < fixedData.m_ulEnterRegionCnt; i++) { fixedData.m_pEnterRegion[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); eLog += $" {i} = (RegionId:{fixedData.m_pEnterRegion[i].GetLog()}) || "; } logContent += $"m_pEnterRegion: {eLog}\n"; } else { fixedData.m_pEnterRegion = null; logContent += $"m_pEnterRegion: {fixedData.m_pEnterRegion}\n"; } // C++ lines 3903-3914: leave regions if (fixedData.m_ulLeaveRegionCnt > 0) { fixedData.m_pLeaveRegion = new Task_Region[fixedData.m_ulLeaveRegionCnt]; string lLog = ""; for (int i = 0; i < fixedData.m_ulLeaveRegionCnt; i++) { fixedData.m_pLeaveRegion[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); lLog += $" {i} = (RegionId:{fixedData.m_pLeaveRegion[i].GetLog()}) || "; } logContent += $"m_pLeaveRegion: {lLog}\n"; } else { fixedData.m_pLeaveRegion = null; logContent += $"m_pLeaveRegion: {fixedData.m_pLeaveRegion}\n"; } // C++ lines 3916-3927: premise items if (fixedData.m_ulPremItems > 0) { fixedData.m_PremItems = new ITEM_WANTED[fixedData.m_ulPremItems]; string premLog = ""; for (int i = 0; i < fixedData.m_ulPremItems; i++) { fixedData.m_PremItems[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); premLog += $" {i} = (Item:{fixedData.m_PremItems[i].m_ulItemTemplId}, Cmn:{fixedData.m_PremItems[i].m_bCommonItem}, Num:{fixedData.m_PremItems[i].m_ulItemNum}) || "; } logContent += $"m_PremItems: {premLog}\n"; } else { fixedData.m_PremItems = null; logContent += $"m_PremItems: {fixedData.m_PremItems}\n"; } // C++ lines 3929-3945: given items and counts fixedData.m_ulGivenCmnCount = 0; fixedData.m_ulGivenTskCount = 0; if (fixedData.m_ulGivenItems > 0) { fixedData.m_GivenItems = new ITEM_WANTED[fixedData.m_ulGivenItems]; string givenLog = ""; for (int i = 0; i < fixedData.m_ulGivenItems; i++) { fixedData.m_GivenItems[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); if (fixedData.m_GivenItems[i].m_bCommonItem) fixedData.m_ulGivenCmnCount++; else fixedData.m_ulGivenTskCount++; givenLog += $" {i} = (Item:{fixedData.m_GivenItems[i].m_ulItemTemplId}, Cmn:{fixedData.m_GivenItems[i].m_bCommonItem}, Num:{fixedData.m_GivenItems[i].m_ulItemNum}) || "; } logContent += $"m_GivenItems: {givenLog}\n"; logContent += $"m_ulGivenCmnCount: {fixedData.m_ulGivenCmnCount}, m_ulGivenTskCount: {fixedData.m_ulGivenTskCount}\n"; } else { fixedData.m_GivenItems = null; logContent += $"m_GivenItems: {fixedData.m_GivenItems}\n"; } // C++ lines 3947-3960: team members wanted if (fixedData.m_bTeamwork) { if (fixedData.m_ulTeamMemsWanted > 0) { fixedData.m_TeamMemsWanted = new TEAM_MEM_WANTED[fixedData.m_ulTeamMemsWanted]; string tmwLog = ""; for (int i = 0; i < fixedData.m_ulTeamMemsWanted; i++) { fixedData.m_TeamMemsWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); var v = fixedData.m_TeamMemsWanted[i]; tmwLog += $" {i} = (Lvl:{v.m_ulLevelMin}-{v.m_ulLevelMax}, Race:{v.m_ulRace}, Occup:{v.m_ulOccupation}, Gender:{v.m_ulGender}, Cnt:{v.m_ulMinCount}-{v.m_ulMaxCount}, Task:{v.m_ulTask}, Force:{v.m_iForce}) || "; } logContent += $"m_TeamMemsWanted: {tmwLog}\n"; } else { fixedData.m_TeamMemsWanted = null; logContent += $"m_TeamMemsWanted: {fixedData.m_TeamMemsWanted}\n"; } } // C++ lines 3961-3969: premise titles if (fixedData.m_iPremTitleNumTotal > 0) { fixedData.m_PremTitles = new int[fixedData.m_iPremTitleNumTotal]; string ptLog = ""; for (int i = 0; i < fixedData.m_iPremTitleNumTotal; i++) { fixedData.m_PremTitles[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); ptLog += $" {i} = {fixedData.m_PremTitles[i]} || "; } logContent += $"m_PremTitles: {ptLog}\n"; } else { fixedData.m_PremTitles = null; logContent += $"m_PremTitles: {fixedData.m_PremTitles}\n"; } // C++ lines 3973-3983: monster wanted if (fixedData.m_ulMonsterWanted > 0) { fixedData.m_MonsterWanted = new MONSTER_WANTED[fixedData.m_ulMonsterWanted]; string mwLog = ""; for (int i = 0; i < fixedData.m_ulMonsterWanted; i++) { fixedData.m_MonsterWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); mwLog += $" {i} = (Monster:{fixedData.m_MonsterWanted[i].m_ulMonsterTemplId}, Num:{fixedData.m_MonsterWanted[i].m_ulMonsterNum}) || "; } logContent += $"m_MonsterWanted: {mwLog}\n"; } else { fixedData.m_MonsterWanted = null; logContent += $"m_MonsterWanted: {fixedData.m_MonsterWanted}\n"; } // C++ lines 3985-3994: player wanted if (fixedData.m_ulPlayerWanted > 0) { fixedData.m_PlayerWanted = new PLAYER_WANTED[fixedData.m_ulPlayerWanted]; string pwLog = ""; for (int i = 0; i < fixedData.m_ulPlayerWanted; i++) { fixedData.m_PlayerWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); //pwLog += $" {i} = (Tpl:{fixedData.m_PlayerWanted[i].m_ulTemplID}, Cnt:{fixedData.m_PlayerWanted[i].m_ulCount}, Lev:{fixedData.m_PlayerWanted[i].m_ulLevel}) || "; pwLog += $" {i} = {fixedData.m_PlayerWanted[i].GetLog() }|| "; } logContent += $"m_PlayerWanted: {pwLog}\n"; } else { fixedData.m_PlayerWanted = null; logContent += $"m_PlayerWanted: {fixedData.m_PlayerWanted}\n"; } // C++ lines 3996-4006: items wanted if (fixedData.m_ulItemsWanted > 0) { fixedData.m_ItemsWanted = new ITEM_WANTED[fixedData.m_ulItemsWanted]; string iwLog = ""; for (int i = 0; i < fixedData.m_ulItemsWanted; i++) { fixedData.m_ItemsWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); iwLog += $" {i} = (Item:{fixedData.m_ItemsWanted[i].m_ulItemTemplId}, Cmn:{fixedData.m_ItemsWanted[i].m_bCommonItem}, Num:{fixedData.m_ItemsWanted[i].m_ulItemNum}) || "; } logContent += $"m_ItemsWanted: {iwLog}\n"; } else { fixedData.m_ItemsWanted = null; logContent += $"m_ItemsWanted: {fixedData.m_ItemsWanted}\n"; } // C++ lines 4008-4021: expressions to display if (fixedData.m_ulExpCnt > 0) { int rowCount = (int)fixedData.m_ulExpCnt; int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; fixedData.m_pszExp = new byte[rowCount, colCount]; fixedData.m_pExpArr = new TASK_EXPRESSION[rowCount, colCount]; fixedData.m_pszExp_Seri = new byte[rowCount * colCount]; fixedData.m_pExpArr_Seri = new TASK_EXPRESSION[rowCount * colCount]; for (int i = 0; i < rowCount; i++) { byte[] expBytes = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); for (int j = 0; j < colCount; j++) { fixedData.m_pszExp[i, j] = expBytes[j]; fixedData.m_pszExp_Seri[i * colCount + j] = expBytes[j]; fixedData.m_pExpArr[i, j] = AAssit.ReadFromBinaryOf(fp, ref readBytes); fixedData.m_pExpArr_Seri[i * colCount + j] = fixedData.m_pExpArr[i, j]; } } logContent += $"m_pszExp and m_pExpArr loaded, count: {fixedData.m_ulExpCnt} (each {TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN})\n"; } else { logContent += $"m_pszExp: {fixedData.m_pszExp}\n"; logContent += $"m_pExpArr: {fixedData.m_pExpArr}\n"; } // C++ lines 4023-4032: task char prompts if (fixedData.m_ulTaskCharCnt > 0) { int rowCount = (int)fixedData.m_ulTaskCharCnt; int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; fixedData.m_pTaskChar = new ushort[rowCount, colCount]; fixedData.m_pTaskChar_Seri = new ushort[rowCount * colCount]; string tcLog = ""; for (int i = 0; i < rowCount; i++) { ushort[] row = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); for (int j = 0; j < colCount; j++) { fixedData.m_pTaskChar[i, j] = row[j]; fixedData.m_pTaskChar_Seri[i * colCount + j] = row[j]; } tcLog += $" {i} = (...{colCount} chars) || "; } logContent += $"m_pTaskChar: {tcLog}\n"; } else { logContent += $"m_pTaskChar: {fixedData.m_pTaskChar}\n"; } // C++ lines 4035-4058: reach and leave sites if (fixedData.m_ulReachSiteCnt > 0) { fixedData.m_pReachSite = new Task_Region[fixedData.m_ulReachSiteCnt]; string rsLog = ""; for (int i = 0; i < fixedData.m_ulReachSiteCnt; i++) { fixedData.m_pReachSite[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); rsLog += $" {i} = (RegionId:{fixedData.m_pReachSite[i].GetLog()}) || "; } logContent += $"m_pReachSite: {rsLog}\n"; } else { fixedData.m_pReachSite = null; logContent += $"m_pReachSite: {fixedData.m_pReachSite}\n"; } if (fixedData.m_ulLeaveSiteCnt > 0) { fixedData.m_pLeaveSite = new Task_Region[fixedData.m_ulLeaveSiteCnt]; string lsLog = ""; for (int i = 0; i < fixedData.m_ulLeaveSiteCnt; i++) { fixedData.m_pLeaveSite[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); lsLog += $" {i} = (RegionId:{fixedData.m_pLeaveSite[i].GetLog()}) || "; } logContent += $"m_pLeaveSite: {lsLog}\n"; } else { fixedData.m_pLeaveSite = null; logContent += $"m_pLeaveSite: {fixedData.m_pLeaveSite}\n"; } // BMLogger.LogError($" === Task Pointer Datas {fixedData.m_ID} loaded === \n {logContent} "); pointerLog += $" Start read m_Award_S , pointer at : {fp.Position} \n"; // BMLogger.Log($"---- Pointer Log {fixedData.m_ID} ---- \n {pointerLog} "); LoadAwardDataBin(fp, ref fixedData.m_Award_S, TaskTemplConstants._task_templ_cur_version, ref readBytes); pointerLog += $" Start read m_Award_F complete : {fp.Position} \n"; LoadAwardDataBin(fp, ref fixedData.m_Award_F, TaskTemplConstants._task_templ_cur_version, ref readBytes); pointerLog += $" After Award_S and Award_F complete : {fp.Position} \n"; LoadAwardDataRatioScale(fp, ref fixedData.m_AwByRatio_S, TaskTemplConstants._task_templ_cur_version, ref readBytes); LoadAwardDataRatioScale(fp, ref fixedData.m_AwByRatio_F, TaskTemplConstants._task_templ_cur_version, ref readBytes); pointerLog += $" After AwByRatio_S and AwByRatio_F complete : {fp.Position} \n"; LoadAwardDataItemsScale(fp, ref fixedData.m_AwByItems_S, TaskTemplConstants._task_templ_cur_version, ref readBytes); LoadAwardDataItemsScale(fp, ref fixedData.m_AwByItems_F, TaskTemplConstants._task_templ_cur_version, ref readBytes); pointerLog += $" After FixedData complete : {fp.Position} \n"; } private bool LoadAwardDataItemsScale(Stream fp, ref AWARD_ITEMS_SCALE ad, uint ulVersion, ref long readBytes) { // fread(&ad.m_ulScales, sizeof(ad.m_ulScales), 1, fp); ad.m_ulScales = AAssit.ReadFromBinaryOf(fp, ref readBytes); // fread(&ad.m_ulItemId, sizeof(ad.m_ulItemId), 1, fp); ad.m_ulItemId = AAssit.ReadFromBinaryOf(fp, ref readBytes); // fread(ad.m_Counts, sizeof(ad.m_Counts), 1, fp); ad.m_Counts = new uint[TaskTemplConstants.MAX_AWARD_SCALES]; // ad.m_Counts = AAssit.ReadArrayFromBinary(fp, ref readBytes); for (int i=0; i < TaskTemplConstants.MAX_AWARD_SCALES; i++) { ad.m_Counts[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); } // LOG_DELETE_ARR(ad.m_Awards); // ad.m_Awards = NULL; if (ad.m_ulScales > 0) { ad.m_Awards = new AWARD_DATA[ad.m_ulScales]; for (int i = 0; i < ad.m_ulScales; i++) { LoadAwardDataBin(fp, ref ad.m_Awards[i], ulVersion, ref readBytes); } } return true; } private bool LoadAwardDataRatioScale(Stream fp, ref AWARD_RATIO_SCALE ad, uint ulVersion, ref long readBytes) { //fread(&ad.m_ulScales, sizeof(ad.m_ulScales), 1, fp); ad.m_ulScales = AAssit.ReadFromBinaryOf(fp, ref readBytes); pointerLog += $" After read ad.m_ulScales: {fp.Position} / m_ulScales = {ad.m_ulScales} \n"; //fread(ad.m_Ratios, sizeof(ad.m_Ratios), 1, fp); ad.m_Ratios = AAssit.ReadArrayFromBinary(fp,TaskTemplConstants.MAX_AWARD_SCALES, ref readBytes); // pointerLog += $" After read ad.m_Ratios: {fp.Position} +x: {x} \n"; // LOG_DELETE_ARR(ad.m_Awards); // ad.m_Awards = NULL; if (ad.m_ulScales > 0) { ad.m_Awards = new AWARD_DATA[ad.m_ulScales]; for (int i = 0; i < ad.m_ulScales; i++) { LoadAwardDataBin(fp, ref ad.m_Awards[i], ulVersion, ref readBytes); } //g_ulNewCount++; } return true; } private bool LoadAwardDataBin(Stream fp, ref AWARD_DATA ad, uint ulVersion, ref long readBytes) { string logContent = ""; // Inline scalars ad.m_ulGoldNum = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulGoldNum: {ad.m_ulGoldNum} \n"; ad.m_ulExp = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulExp: {ad.m_ulExp} \n"; ad.m_ulRealmExp = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 境界经验 // Realm experience logContent += $"m_ulRealmExp: {ad.m_ulRealmExp} \n"; ad.m_bExpandRealmLevelMax = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 境界等级10整级时提升境界等级上限 // Increase realm level upper limit logContent += $"m_bExpandRealmLevelMax: {ad.m_bExpandRealmLevelMax} \n"; ad.m_ulNewTask = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulNewTask: {ad.m_ulNewTask} \n"; ad.m_ulSP = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulSP: {ad.m_ulSP} \n"; ad.m_lReputation = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_lReputation: {ad.m_lReputation} \n"; ad.m_ulNewPeriod = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulNewPeriod: {ad.m_ulNewPeriod} \n"; ad.m_ulNewRelayStation = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulNewRelayStation: {ad.m_ulNewRelayStation} \n"; ad.m_ulStorehouseSize = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulStorehouseSize: {ad.m_ulStorehouseSize} \n"; ad.m_ulStorehouseSize2 = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulStorehouseSize2: {ad.m_ulStorehouseSize2} \n"; ad.m_ulStorehouseSize3 = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulStorehouseSize3: {ad.m_ulStorehouseSize3} \n"; ad.m_ulStorehouseSize4 = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 账号仓库 // Account warehouse logContent += $"m_ulStorehouseSize4: {ad.m_ulStorehouseSize4} \n"; ad.m_lInventorySize = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_lInventorySize: {ad.m_lInventorySize} \n"; ad.m_ulPetInventorySize = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPetInventorySize: {ad.m_ulPetInventorySize} \n"; ad.m_ulFuryULimit = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulFuryULimit: {ad.m_ulFuryULimit} \n"; ad.m_ulTransWldId = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulTransWldId: {ad.m_ulTransWldId} \n"; ad.m_TransPt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_TransPt: ({ad.m_TransPt.x}, {ad.m_TransPt.y}, {ad.m_TransPt.z}) \n"; ad.m_lMonsCtrl = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_lMonsCtrl: {ad.m_lMonsCtrl} \n"; ad.m_bTrigCtrl = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bTrigCtrl: {ad.m_bTrigCtrl} \n"; ad.m_bUseLevCo = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bUseLevCo: {ad.m_bUseLevCo} \n"; ad.m_bDivorce = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bDivorce: {ad.m_bDivorce} \n"; ad.m_bSendMsg = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bSendMsg: {ad.m_bSendMsg} \n"; ad.m_nMsgChannel = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_nMsgChannel: {ad.m_nMsgChannel} \n"; // Candidates and summoned monsters (pointers skipped; content read later by counts if needed) ad.m_ulCandItems = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulCandItems: {ad.m_ulCandItems} \n"; fp.Seek(4, SeekOrigin.Current); // C++: AWARD_ITEMS_CAND* m_CandItems; skip pointer address logContent += $"skip 4 bytes . AWARD_ITEMS_CAND* m_CandItems \n"; ad.m_ulSummonedMonsters = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulSummonedMonsters: {ad.m_ulSummonedMonsters} \n"; fp.Seek(4, SeekOrigin.Current); // C++: AWARD_MONSTERS_SUMMONED* m_SummonedMonsters; skip pointer address logContent += $"skip 4 bytes . AWARD_MONSTERS_SUMMONED* m_SummonedMonsters \n"; ad.m_bAwardDeath = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bAwardDeath: {ad.m_bAwardDeath} \n"; ad.m_bAwardDeathWithLoss = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bAwardDeathWithLoss: {ad.m_bAwardDeathWithLoss} \n"; ad.m_ulDividend = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 鸿利值 // Dividend value logContent += $"m_ulDividend: {ad.m_ulDividend} \n"; ad.m_bAwardSkill = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 是否奖励技能 // Whether to reward skill logContent += $"m_bAwardSkill: {ad.m_bAwardSkill} \n"; ad.m_iAwardSkillID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 技能ID // Skill ID logContent += $"m_iAwardSkillID: {ad.m_iAwardSkillID} \n"; ad.m_iAwardSkillLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 技能等级 // Skill level logContent += $"m_iAwardSkillLevel: {ad.m_iAwardSkillLevel} \n"; // PQ task reward ad.m_ulSpecifyContribTaskID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 指定任务贡献度的任务id // Task ID for specified contribution logContent += $"m_ulSpecifyContribTaskID: {ad.m_ulSpecifyContribTaskID} \n"; ad.m_ulSpecifyContribSubTaskID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 指定任务贡献度的子任务ID // Subtask ID for specified contribution logContent += $"m_ulSpecifyContribSubTaskID: {ad.m_ulSpecifyContribSubTaskID} \n"; ad.m_ulSpecifyContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 指定任务贡献度 // Specified task contribution logContent += $"m_ulSpecifyContrib: {ad.m_ulSpecifyContrib} \n"; ad.m_ulContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 贡献度 // Contribution logContent += $"m_ulContrib: {ad.m_ulContrib} \n"; ad.m_ulRandContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 随机贡献度 // Random contribution logContent += $"m_ulRandContrib: {ad.m_ulRandContrib} \n"; ad.m_ulLowestcontrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 最低贡献度 // Minimum contribution logContent += $"m_ulLowestcontrib: {ad.m_ulLowestcontrib} \n"; ad.m_iFactionContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 帮派贡献度 // Faction contribution logContent += $"m_iFactionContrib: {ad.m_iFactionContrib} \n"; ad.m_iFactionExpContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iFactionExpContrib: {ad.m_iFactionExpContrib} \n"; ad.m_ulPQRankingAwardCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulPQRankingAwardCnt: {ad.m_ulPQRankingAwardCnt} \n"; fp.Seek(4, SeekOrigin.Current); // C++: AWARD_PQ_RANKING* m_PQRankingAward; skip pointer address logContent += $"skip 4 bytes . AWARD_PQ_RANKING* m_PQRankingAward \n"; // Change global key/value arrays (pointers to basic types) ad.m_ulChangeKeyCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulChangeKeyCnt: {ad.m_ulChangeKeyCnt} \n"; fp.Seek(4, SeekOrigin.Current); // C++: long* m_plChangeKey; skip sizeof(long) fp.Seek(4, SeekOrigin.Current); // C++: long* m_plChangeKeyValue; skip sizeof(long) fp.Seek(4, SeekOrigin.Current); // C++: bool* m_pbChangeType; skip sizeof(bool) logContent += $"skip 4 pointers . m_plChangeKey(4) \n m_plChangeKeyValue(4) \n m_pbChangeType(4) \n"; // Modify historical progress ad.m_ulHistoryChangeCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulHistoryChangeCnt: {ad.m_ulHistoryChangeCnt} \n"; fp.Seek(4, SeekOrigin.Current); // C++: long* m_plHistoryChangeKey fp.Seek(4, SeekOrigin.Current); // C++: long* m_plHistoryChangeKeyValue fp.Seek(4, SeekOrigin.Current); // C++: bool* m_pbHistoryChangeType logContent += $"skip pointers . m_plHistoryChangeKey(4) \n m_plHistoryChangeKeyValue(4) \n m_pbHistoryChangeType(4) \n"; // Multiplier ad.m_bMulti = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; logContent += $"m_bMulti: {ad.m_bMulti} \n"; ad.m_nNumType = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_nNumType: {ad.m_nNumType} \n"; ad.m_lNum = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_lNum: {ad.m_lNum} \n"; // Display global key/value ad.m_ulDisplayKeyCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulDisplayKeyCnt: {ad.m_ulDisplayKeyCnt} \n"; fp.Seek(4, SeekOrigin.Current); // C++: long* m_plDisplayKey logContent += $"skip 4 bytes . long* m_plDisplayKey \n"; // Display global variable expressions ad.m_ulExpCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulExpCnt: {ad.m_ulExpCnt} \n"; fp.Seek(4, SeekOrigin.Current); // C++: char (*m_pszExp)[TASK_AWARD_MAX_DISPLAY_CHAR_LEN] fp.Seek(4, SeekOrigin.Current); // C++: TASK_EXPRESSION (*m_pExpArr)[TASK_AWARD_MAX_DISPLAY_CHAR_LEN] logContent += $"skip 4 bytes . m_pszExp(row ptr) \n"; logContent += $"skip 4 bytes . m_pExpArr(row ptr) \n"; // Display global variable expression prompt strings ad.m_ulTaskCharCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulTaskCharCnt: {ad.m_ulTaskCharCnt} \n"; fp.Seek(4, SeekOrigin.Current); // C++: task_char (*m_pTaskChar)[TASK_AWARD_MAX_DISPLAY_CHAR_LEN] logContent += $"skip 4 bytes . task_char (*m_pTaskChar)[LEN] \n"; // Force-related ad.m_iForceContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iForceContribution: {ad.m_iForceContribution} \n"; ad.m_iForceReputation = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iForceReputation: {ad.m_iForceReputation} \n"; ad.m_iForceActivity = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iForceActivity: {ad.m_iForceActivity} \n"; ad.m_iForceSetRepu = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iForceSetRepu: {ad.m_iForceSetRepu} \n"; ad.m_iTaskLimit = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iTaskLimit: {ad.m_iTaskLimit} \n"; ad.m_ulTitleNum = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_ulTitleNum: {ad.m_ulTitleNum} \n"; fp.Seek(4, SeekOrigin.Current); // C++: TITLE_AWARD* m_pTitleAward logContent += $"skip 4 bytes . TITLE_AWARD* m_pTitleAward \n"; ad.m_iLeaderShip = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iLeaderShip: {ad.m_iLeaderShip} \n"; ad.m_iWorldContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 世界贡献度 // World contribution logContent += $"m_iWorldContribution: {ad.m_iWorldContribution} \n"; logContent += "------ Start Pointer datas of AWARD_DATA ------ \n"; pointerLog += $"After Raw Data of AWARD_DATA, pointer : {fp.Position}\n"; // Start convert Pointer Data of AWARD_DATA //Debug.Log($"ad.m_ulCandItems : {ad.m_ulCandItems}"); if (ad.m_ulCandItems > 0) { ad.m_CandItems = new AWARD_ITEMS_CAND[ad.m_ulCandItems]; for (int i=0; i < ad.m_ulCandItems; i++) { LoadAwardCandBin(fp, ref ad.m_CandItems[i], ulVersion, ref readBytes); } } else ad.m_CandItems = null; logContent += $" m_CandItems : {ad.m_ulCandItems} elements / Pointer : {fp.Position} \n"; // [10:36:42.230] [MH] Pointer Pos after read AWARD_DATA.m_ulCandItems =58302 //pointerLog += $" After Read AWARD_DATA.m_ulCandItems : {fp.Position}\n"; if (ad.m_ulSummonedMonsters > 0) { //C++: ad.m_SummonedMonsters.m_ulMonsterNum = ad.m_ulSummonedMonsters; ad.m_SummonedMonsters.m_ulMonsterNum = ad.m_ulSummonedMonsters; LoadAwardMonstersBin(fp, ref ad.m_SummonedMonsters, ulVersion, ref readBytes); } logContent += $"m_SummonedMonsters : {ad.m_ulSummonedMonsters} elements / Pointer : {fp.Position} \n"; pointerLog += $" After LoadAwardMonstersBin, pointer : {fp.Position}\n"; if (ad.m_ulPQRankingAwardCnt > 0) { // C++: ad.m_PQRankingAward.m_ulRankingAwardNum = ad.m_ulPQRankingAwardCnt; ad.m_PQRankingAward.m_ulRankingAwardNum = ad.m_ulPQRankingAwardCnt; LoadAwardPQRankingBin(fp, ref ad.m_PQRankingAward, ulVersion, ref readBytes); } logContent += $" AWARD_DATA.m_PQRankingAward : {ad.m_ulPQRankingAwardCnt} elements / {fp.Position} \n"; pointerLog += $" After LoadAwardPQRankingBin, pointer : {fp.Position}\n"; ad.m_pTitleAward = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulTitleNum,ref readBytes); logContent += $" AWARD_DATA.m_pTitleAward : {ad.m_ulTitleNum} elements / {fp.Position} \n"; if (ad.m_ulChangeKeyCnt > 0) { ad.m_plChangeKey = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulChangeKeyCnt,ref readBytes); ad.m_plChangeKeyValue = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulChangeKeyCnt,ref readBytes); ad.m_pbChangeType = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulChangeKeyCnt,ref readBytes); } logContent += $" AWARD_DATA.m_plChangeKey : {ad.m_ulChangeKeyCnt} elements / {fp.Position} \n"; logContent += $" AWARD_DATA.m_plChangeKeyValue : {ad.m_ulChangeKeyCnt} elements / {fp.Position} \n"; logContent += $" AWARD_DATA.m_pbChangeType : {ad.m_ulChangeKeyCnt} elements / {fp.Position} \n"; pointerLog += $" After ad.m_pbChangeType, pointer : {fp.Position}\n"; if (ad.m_ulHistoryChangeCnt > 0) { //fread(&ad.m_plHistoryChangeKey[i], sizeof(long), 1, fp); ad.m_plHistoryChangeKey = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulHistoryChangeCnt, ref readBytes); //fread(&ad.m_plHistoryChangeKeyValue[i], sizeof(long), 1, fp); ad.m_plHistoryChangeKeyValue = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulHistoryChangeCnt, ref readBytes); //fread(&ad.m_pbHistoryChangeType[i], sizeof(bool), 1, fp); ad.m_pbHistoryChangeType = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulHistoryChangeCnt,ref readBytes); } logContent += $" AWARD_DATA.m_plHistoryChangeKey : {ad.m_ulHistoryChangeCnt} elements / {fp.Position} \n"; logContent += $" AWARD_DATA.m_plHistoryChangeKeyValue : {ad.m_ulHistoryChangeCnt} elements / {fp.Position} \n"; logContent += $" AWARD_DATA.m_pbHistoryChangeType : {ad.m_ulHistoryChangeCnt} elements / {fp.Position} \n"; ad.m_plDisplayKey = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulDisplayKeyCnt, ref readBytes); logContent += $" AWARD_DATA.m_plDisplayKey : {ad.m_ulDisplayKeyCnt} elements / {fp.Position} \n"; if (ad.m_ulExpCnt > 0) { int rowCount = (int)ad.m_ulExpCnt; int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; // 显示全局变量表达式显示字节 // Display bytes for global variable expressions ad.m_pszExp = new byte[rowCount * colCount]; ad.m_pExpArr = new TASK_EXPRESSION[rowCount * colCount]; for (int row = 0; row < rowCount; row++) { byte[] expBytesRow = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); Buffer.BlockCopy(expBytesRow, 0, ad.m_pszExp, row * colCount, colCount); for (int col = 0; col < colCount; col++) { ad.m_pExpArr[row * colCount + col] = AAssit.ReadFromBinaryOf(fp, ref readBytes); } } } logContent += $" AWARD_DATA.m_pszExp and m_pExpArr : {ad.m_ulExpCnt} rows / {fp.Position} \n"; pointerLog += $" After ad.m_pExpArr, pointer : {fp.Position}\n"; if (ad.m_ulTaskCharCnt > 0) { int rowCount = (int)ad.m_ulTaskCharCnt; int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; ad.m_pTaskChar = new ushort[rowCount * colCount]; for (int row = 0; row < rowCount; row++) { ushort[] rowChars = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); Buffer.BlockCopy(rowChars, 0, ad.m_pTaskChar, row * colCount * 2, colCount * 2); } } logContent += $" AWARD_DATA.m_pTaskChar : {ad.m_ulTaskCharCnt} rows / {fp.Position} \n"; pointerLog += $" After ad.m_pTaskChar, pointer : {fp.Position}\n"; // BMLogger.LogError( $" ---- Data of AWARD_DATA ---- \n {logContent} " ); return true; } private bool LoadAwardCandBin(Stream fp, ref AWARD_ITEMS_CAND ic, uint ulVersion, ref long readBytes) { string valueLog = ""; pointerLog += $" Before Read AWARD_ITEMS_CAND.m_bRandChoose : {fp.Position}\n"; //ic.m_bRandChoose = AAssit.ReadFromBinaryOf(fp, ref readBytes); ic.m_bRandChoose = AAssit.ReadFromBinaryOf(fp, ref readBytes); pointerLog += $" After Read AWARD_ITEMS_CAND.m_bRandChoose : {fp.Position}\n"; ic.m_ulAwardItems = AAssit.ReadFromBinaryOf(fp, ref readBytes); pointerLog += $" After Read AWARD_ITEMS_CAND.m_ulAwardItems : {fp.Position}\n"; // Debug.Log( $"ic.m_bRandChoose : {ic.m_bRandChoose} ic.m_ulAwardItems : {ic.m_ulAwardItems}"); // return true; if (ic.m_ulAwardItems > 0) { ic.m_AwardItems = new ITEM_WANTED[ic.m_ulAwardItems]; for (int i = 0; i < ic.m_ulAwardItems; i++) { ic.m_AwardItems[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); ITEM_WANTED iw = ic.m_AwardItems[i]; if (iw.m_bCommonItem) ic.m_ulAwardCmnItems++; else ic.m_ulAwardTskItems++; valueLog += $" {i} = (Item:{iw.m_ulItemTemplId}, Cmn:{iw.m_bCommonItem}, Num:{iw.m_ulItemNum}) || "; } } else ic.m_AwardItems = null; pointerLog += $" After Read m_ulAwardItems : {fp.Position}\n"; //BMLogger.Log($"AWARD_ITEMS_CAND.m_AwardItems[] : {valueLog}" ); return true; } private bool LoadAwardMonstersBin(Stream fp, ref AWARD_MONSTERS_SUMMONED ms, uint ulVersion, ref long readBytes) { // fread(&ms.m_bRandChoose, sizeof(ms.m_bRandChoose), 1, fp); // fread(&ms.m_ulSummonRadius, sizeof(ms.m_ulSummonRadius), 1, fp); // fread(&ms.m_bDeathDisappear, sizeof(ms.m_bDeathDisappear), 1, fp); ms.m_bRandChoose = AAssit.ReadFromBinaryOf(fp, ref readBytes); ms.m_ulSummonRadius = AAssit.ReadFromBinaryOf(fp, ref readBytes); ms.m_bDeathDisappear = AAssit.ReadFromBinaryOf(fp, ref readBytes); // for (i=0; i < ms.m_ulMonsterNum; i++) // { // MONSTERS_SUMMONED& monster = ms.m_Monsters[i]; // fread(&monster, sizeof(monster), 1, fp); // } ms.m_Monsters = AAssit.ReadArrayFromBinary(fp, (int)ms.m_ulMonsterNum, ref readBytes); return true; } private bool LoadAwardPQRankingBin(Stream fp, ref AWARD_PQ_RANKING pr, uint ulVersion, ref long readBytes) { //fread(&pr.m_bAwardByProf, sizeof(pr.m_bAwardByProf), 1, fp); pr.m_bAwardByProf = AAssit.ReadFromBinaryOf(fp, ref readBytes); // for (i=0; i < pr.m_ulRankingAwardNum; i++) // { // RANKING_AWARD& rAward = pr.m_RankingAward[i]; // fread(&rAward, sizeof(rAward), 1, fp); // } pr.m_RankingAward = AAssit.ReadArrayFromBinary(fp, (int)pr.m_ulRankingAwardNum, ref readBytes); return true; } #endregion // 加载任务描述与确认/拒绝文本 // Load task description and OK/No texts private bool LoadDescriptionBin(Stream fp) { long readBytes = 0; string valueLog = ""; // Debug.Log($"Id= {m_FixedData.m_ID}"); // 读取长度(C++: size_t) // Read length (C++: size_t) uint len = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 描述文本(task_char*) // Description text (task_char*) m_pwstrDescript = new ushort[len + 1]; m_pwstrDescript[len] = 0; if (len > 0) { // ushort[] tmp = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); // System.Buffer.BlockCopy(tmp, 0, m_pwstrDescript, 0, (int)len * 2); m_pwstrDescript = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); convert_txt(m_pwstrDescript, (int)len, (char)m_FixedData.m_ID); } valueLog += $" m_pwstrDescript : len = {len} / " + $"{ ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrDescript) } / " + $" Pointer = {fp.Position} \n"; // OK 文本 // OK text len = AAssit.ReadFromBinaryOf(fp, ref readBytes); m_pwstrOkText = new ushort[len + 1]; m_pwstrOkText[len] = 0; if (len > 0) { // ushort[] tmp = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); // System.Buffer.BlockCopy(tmp, 0, m_pwstrOkText, 0, (int)len * 2); m_pwstrOkText = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); convert_txt(m_pwstrOkText, (int)len, (char)m_FixedData.m_ID); } valueLog += $" m_pwstrOkText : { ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrOkText) } \n"; // NO 文本 // No text len = AAssit.ReadFromBinaryOf(fp, ref readBytes); m_pwstrNoText = new ushort[len + 1]; m_pwstrNoText[len] = 0; if (len > 0) { // ushort[] tmp = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); // System.Buffer.BlockCopy(tmp, 0, m_pwstrNoText, 0, (int)len * 2); m_pwstrNoText = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); convert_txt(m_pwstrNoText, (int)len, (char)m_FixedData.m_ID); } valueLog += $" m_pwstrNoText : { ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrNoText) } \n"; // BMLogger.LogError( $" ---- Data of Task Description ---- \n {valueLog} " ); return true; } private bool LoadTributeBin(Stream fp) { long readBytes = 0; // size_t len; // len = 0; // fread(&len, sizeof(len), 1, fp); uint len = AAssit.ReadFromBinaryOf(fp, ref readBytes); // m_FixedData.m_pwstrTribute = new task_char[len+1]; // m_pwstrTribute[len] = L'\0'; m_pwstrTribute = new ushort[len + 1]; m_pwstrTribute[len] = 0; if (len > 0) { // fread(m_pwstrTribute, sizeof(task_char), len, fp); // convert_txt(m_pwstrTribute, len, (namechar)m_ID); m_pwstrTribute = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); convert_txt(m_pwstrTribute, (int)len, (char)m_FixedData.m_ID); } // BMLogger.Log($" --- m_pwstrTribute ---- \n " + // $" Len : {len} \n " + // $" content: {ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrTribute)}"); return true; } #region convert from c++ to cs // private bool LoadFixedDataFromBinFile(FileStream fp) // { // long readBytes = 0; // BMLogger.Log($"LoadFixedDataFromBinFile: {fp.Length}"); // ATaskTemplFixedData fixedData; // // * Important Note: // // + In C++: "unsigned long" → corresponds to "uint" in C# // // + "bool" in C++ is 1 byte (while C# bool is also 1 byte in struct layout, but not in file IO) // // + wchar_t on Windows = 2 bytes // // + When reading binary data, we must match the original C++ memory layout exactly. // // ------------------------------------------------------------ // // Case 1: "Normal" value type variable // // ------------------------------------------------------------ // // These are directly stored scalar values (no arrays, no pointers, no user-defined struct). // // Example: bool m_bHasSign; unsigned long m_ID; // // Originally in C++: unsigned long m_ID; // // → Read value and asign value to the field // fixedData.m_ID = AAssist.ReadFromBinaryOf(fp, ref readBytes); // // ------------------------------------------------------------ // // Case 2: Fixed-size array (memory already allocated inline) // // ------------------------------------------------------------ // // These have a known constant size in C++, usually defined by a macro. // // Example: task_char m_szName[MAX_TASK_NAME_LEN]; // // char m_tmType[MAX_TIMETABLE_SIZE]; // // → request write here // // Example usage: // //read array from binary to assign value to the field // fixedData.m_tmStart = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes); // fixedData.m_tmEnd = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes); // // ------------------------------------------------------------ // // Case 3: Pointer to user-defined type or string // // ------------------------------------------------------------ // // These fields in C++ store only the pointer address, not the actual object. // // Example: task_char* m_pszSignature; // // originally in C++: task_char* m_pszSignature; // // → Skip pointer size, since the content is not inlined. // // fp.Seek(IntPtr.Size, SeekOrigin.Current); // fp.Seek(4, SeekOrigin.Current); // // ------------------------------------------------------------ // // Case 4: User-defined struct (not pointer) // // ------------------------------------------------------------ // // Skip the full size of the struct in the binary stream. // // **Important:** check the struct's internal members and padding // // to calculate the correct size, do not rely on hardcoded numbers. // // // // Example: // // task_tm m_tmAbsFailTime; // inline struct // // → Skip sizeof(task_tm) bytes. // fp.Seek(24, SeekOrigin.Current); // Example for Windows/MSVC // //case pointer không được define kích thước trước và là kiểu dữ liệu cơ bản => skip tùy theo kích thước của kiểu dữ liệu cơ bản // // ví dụ: ushort* m_pszSignature => skip 2 bytes // //request: hoàn thiện rule // // ------------------------------------------------------------ // // Case 5: Pointer to basic type (size not predefined) // // ------------------------------------------------------------ // // If a field is a pointer to a basic type (e.g., ushort*, int*, float*), // // the pointer itself is stored inline, but the pointed-to data is not. // // When reading binary, skip the size of the basic type (not the pointer address). // // // // Example: // // ushort* m_pszSignature; // skip 2 bytes (size of ushort) // fp.Seek(2, SeekOrigin.Current); // skip 1 element of the basic type // return true; // } // this convert from c++ to cs //*important note: // + in c++: unsigned long => will be uint in cs; // // Case 1: convert from "normal" variable => asign value to the field // Excample: bool *m_pbChangeType; unsigned long m_ID; // originally this line in c++: unsigned long m_ID; // fixedData.m_ID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // Case 2: convert from variable what already defined size of memories => skip the size of the variable // Excample: task_char m_szName[MAX_TASK_NAME_LEN]; char m_tmType[MAX_TIMETABLE_SIZE]; => in this example, MAX_TASK_NAME_LEN and MAX_TIMETABLE_SIZE are already defined size of memories. // originally this line in c++: task_char m_szName[MAX_TASK_NAME_LEN]; // fp.Seek(TaskTemplConstants.MAX_TASK_NAME_LEN, SeekOrigin.Current); // Case 3: convert from variable what is user defination and it is pointer => skip 2 bytes // Excample: task_char* m_pszSignature; (task_char is defined by user) // originally this line in c++: task_char* m_pszSignature; // fp.Seek(2, SeekOrigin.Current); // Case 4: convert from variable what is user defination and it is pointer => skip 4 bytes // Excample: task_char* m_pszSignature; (task_char is defined by user) // originally this line in c++: task_char* m_pszSignature; // fp.Seek(4, SeekOrigin.Current); // fixedData.m_ID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // fixedData.m_szName = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TASK_NAME_LEN, ref readBytes); // TaskTemplUtils.convert_txt(ref fixedData.m_szName, TaskTemplConstants.MAX_TASK_NAME_LEN, TaskTemplUtils.uint_to_ushort(fixedData.m_ID)); // BMLogger.Log($"LoadFixedDataFromBinFile: ID {fixedData.m_ID} Name {ByteToStringUtils.UshortArrayToCP936String(fixedData.m_szName)}"); // fixedData.m_bHasSign = AAssit.ReadFromBinaryOf(fp, ref readBytes); // ATaskTemplFixedData fixedData = AAssit.ReadFromBinaryOf(fp, ref readBytes); //convert_txt(m_szName, MAX_TASK_NAME_LEN, (namechar)m_ID); // m_Award_S = new AWARD_DATA; // g_ulNewCount++; // m_Award_F = new AWARD_DATA; // g_ulNewCount++; // m_AwByRatio_S = new AWARD_RATIO_SCALE; // g_ulNewCount++; // m_AwByRatio_F = new AWARD_RATIO_SCALE; // g_ulNewCount++; // m_AwByItems_S = new AWARD_ITEMS_SCALE; // g_ulNewCount++; // m_AwByItems_F = new AWARD_ITEMS_SCALE; // g_ulNewCount++; // m_tmStart = NULL; // m_tmEnd = NULL; // m_plChangeKey = NULL; // m_plChangeKeyValue = NULL; // m_pbChangeType = NULL; // m_PremItems = NULL; // m_GivenItems = NULL; // m_TeamMemsWanted= NULL; // m_ItemsWanted = NULL; // m_PlayerWanted = NULL; // m_MonsterWanted = NULL; // m_pszSignature = NULL; // m_pszExp = NULL; // m_pExpArr = NULL; // m_pTaskChar = NULL; // m_pszPQExp = NULL; // m_pPQExpArr = NULL; // m_MonstersContrib = NULL; // m_PremTitles = NULL; // if (m_bHasSign) // { // m_pszSignature = new task_char[MAX_TASK_NAME_LEN]; // g_ulNewCount++; // fread(m_pszSignature, sizeof(task_char), MAX_TASK_NAME_LEN, fp); // convert_txt(m_pszSignature, MAX_TASK_NAME_LEN, (namechar)m_ID); // } // if (m_ulTimetable) // { // m_tmStart = new task_tm[m_ulTimetable]; // g_ulNewCount++; // m_tmEnd = new task_tm[m_ulTimetable]; // g_ulNewCount++; // } // for (i = 0; i < m_ulTimetable; i++) // { // fread(&m_tmStart[i], sizeof(task_tm), 1, fp); // fread(&m_tmEnd[i], sizeof(task_tm), 1, fp); // } // if (m_ulChangeKeyCnt) // { // m_plChangeKey = new long[m_ulChangeKeyCnt]; // m_plChangeKeyValue = new long[m_ulChangeKeyCnt]; // m_pbChangeType = new bool[m_ulChangeKeyCnt]; // } // for (i=0; i0) // { // m_pDelvRegion = new Task_Region[m_ulDelvRegionCnt]; // g_ulNewCount++; // } // else m_pDelvRegion = NULL; // for (i=0;i0) // { // m_pEnterRegion = new Task_Region[m_ulEnterRegionCnt]; // g_ulNewCount++; // } // else m_pEnterRegion = NULL; // for (i=0;i0) // { // m_pLeaveRegion = new Task_Region[m_ulLeaveRegionCnt]; // g_ulNewCount++; // } // else m_pLeaveRegion = NULL; // for (i=0;i0) // { // m_pReachSite = new Task_Region[m_ulReachSiteCnt]; // g_ulNewCount++; // } // else m_pReachSite = NULL; // for (i=0;i0) // { // m_pLeaveSite = new Task_Region[m_ulLeaveSiteCnt]; // g_ulNewCount++; // } // else m_pLeaveSite = NULL; // for (i=0;i ushort[64] if (talk.text != null) { convert_txt(talk.text, talk.text.Length, code); } if (talk.windows == null) return; for (int i = 0; i < talk.num_window && i < talk.windows.Length; i++) { var win = talk.windows[i]; if (win.talk_text != null && win.talk_text_len > 0) { int len = Math.Min(win.talk_text_len, win.talk_text.Length); convert_txt(win.talk_text, len, code); } if (win.options == null) continue; for (int j = 0; j < win.num_option && j < win.options.Length; j++) { var o = win.options[j]; if (o.text != null) { convert_txt(o.text, o.text.Length, code); } } } } private void CheckMask() { // 根据完成方式设置掩码 // Set mask according to completion method uint method = m_FixedData.m_enumMethod; if (method == (uint)TaskCompletionMethod.enumTMKillNumMonster) m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_KILL_MONSTER; else if (method == (uint)TaskCompletionMethod.enumTMCollectNumArticle) m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_COLLECT_ITEM; else if (method == (uint)TaskCompletionMethod.enumTMTalkToNPC) m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_TALK_TO_NPC; else if (method == (uint)TaskCompletionMethod.enumTMKillPlayer) m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_KILL_PLAYER; // PQ子任务使用对应掩码 // PQ subtask uses corresponding mask if (m_FixedData.m_bPQSubTask) m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_KILL_PQ_MONSTER; } // 同步任务类型 // Sync task type public ATaskTempl GetTopTask() { ATaskTempl pTop = this; while (pTop.m_pParent != null) { pTop = pTop.m_pParent; } return pTop; } // 同步任务类型 // Sync task type private void SyncTaskType() { ATaskTempl pTop = GetTopTask(); if (pTop != null && !ReferenceEquals(pTop, this)) { m_FixedData.m_ulType = pTop.m_FixedData.m_ulType; } } // 同步层级ID // Synchronize hierarchy IDs private void SynchID() { m_FixedData.m_ulParent = (m_pParent != null) ? m_pParent.m_FixedData.m_ID : 0u; m_FixedData.m_ulNextSibling = (m_pNextSibling != null) ? m_pNextSibling.m_FixedData.m_ID : 0u; m_FixedData.m_ulPrevSibling = (m_pPrevSibling != null) ? m_pPrevSibling.m_FixedData.m_ID : 0u; m_FixedData.m_ulFirstChild = (m_pFirstChild != null) ? m_pFirstChild.m_FixedData.m_ID : 0u; if (m_pFirstChild != null) m_FixedData.m_enumMethod = (uint)TaskCompletionMethod.enumTMNone; } // 添加子任务到层级结构 // Add sub task to hierarchy private void AddSubTaskTempl(ATaskTempl pSub) { if (pSub == null) return; pSub.m_pParent = this; if (m_pFirstChild == null) { m_pFirstChild = pSub; return; } // 追加到兄弟链表末尾 // Append to end of sibling list var last = m_pFirstChild; while (last.m_pNextSibling != null) { last = last.m_pNextSibling; } last.m_pNextSibling = pSub; pSub.m_pPrevSibling = last; } // 检查并累加深度 // Check and accumulate depth private void CheckDepth() { ATaskTempl pChild = m_pFirstChild; byte uDepthLocal = 0; bool bMaxChildDepth = m_FixedData.m_bExeChildInOrder || m_FixedData.m_bChooseOne || m_FixedData.m_bRandOne; while (pChild != null) { pChild.CheckDepth(); if (bMaxChildDepth) { if (uDepthLocal < pChild.m_uDepth) uDepthLocal = pChild.m_uDepth; } else { unchecked { uDepthLocal += pChild.m_uDepth; } } pChild = pChild.m_pNextSibling; } unchecked { m_uDepth += uDepthLocal; } } public void CalcAwardData( TaskInterface pTask, ref AWARD_DATA pAward, ActiveTaskEntry pEntry, uint ulTaskTime, uint ulCurTime) { var ulType = (pEntry.IsSuccess() ? m_FixedData.m_ulAwardType_S : m_FixedData.m_ulAwardType_F); switch (ulType) { case (uint)TaskAwardType.enumTATNormal: case (uint)TaskAwardType.enumTATEach: pAward = (pEntry.IsSuccess() ? m_Award_S : m_Award_F); break; case (uint)TaskAwardType.enumTATRatio: CalcAwardDataByRatio(ref pAward, pEntry, ulTaskTime, ulCurTime); break; case (uint)TaskAwardType.enumTATItemCount: CalcAwardDataByItems(pTask, ref pAward, pEntry); break; default: break; } } public void CalcAwardDataByRatio( ref AWARD_DATA pAward, ActiveTaskEntry pEntry, uint ulTaskTime, uint ulCurTime) { if (m_ulTimeLimit == 0) return; AWARD_RATIO_SCALE p = (pEntry.IsSuccess() ? m_AwByRatio_S : m_AwByRatio_F); float ratio = (float)(ulCurTime - ulTaskTime) / m_ulTimeLimit; uint i; for (i = 0; i= p.m_Counts[i]) { pAward = p.m_Awards[i]; return; } } } public bool CanShowTask(TaskInterface pTask) { uint ulCurTime = pTask.GetCurTime(); if (m_pParent != null || (pTask.GetActiveTaskList() as ActiveTaskList).GetEntry(GetID()) != null || CheckTimetable(ulCurTime) > 0 || CheckDeliverTime(pTask, ulCurTime) > 0 || CheckFnshLst(pTask, ulCurTime) > 0 || CheckMutexTask(pTask, ulCurTime) > 0 || CheckLivingSkill(pTask) > 0 || CheckSpecialAward(pTask) > 0 || CheckGlobalKeyValue(pTask, false) > 0) return false; uint ulRet; if (m_FixedData.m_bShowByDeposit && CheckDeposit(pTask) > 0) return false; if (m_FixedData.m_bShowByGender && CheckGender(pTask) > 0) return false; if (m_FixedData.m_bShowByItems && CheckItems(pTask) > 0) return false; ulRet = CheckLevel(pTask); if (ulRet == TaskInterfaceConstants.TASK_PREREQU_FAIL_ABOVE_LEVEL || (m_FixedData.m_bShowByLev && ulRet > 0)) return false; if (m_FixedData.m_bShowByTransformed && CheckTransform(pTask) > 0) return false; if (m_FixedData.m_bShowByForce && CheckForce(pTask) > 0) return false; if (m_FixedData.m_bShowByForceActivityLevel && CheckForceActivityLevel(pTask) > 0) return false; if (m_FixedData.m_bShowByForceExp && CheckExp(pTask) > 0) return false; if (m_FixedData.m_bShowByForceSP && CheckSP(pTask) > 0) return false; if (m_FixedData.m_bShowByForceContribution && CheckForceContribution(pTask) > 0) return false; if (m_FixedData.m_bShowByForceReputation && CheckForceReputation(pTask) > 0) return false; if (m_FixedData.m_bShowByNeedRecordTasksNum && CheckRecordTasksNum(pTask) > 0) return false; if (m_FixedData.m_bShowByFactionContrib && CheckFactionContrib(pTask) > 0) return false; if (m_FixedData.m_bShowByOccup && CheckOccupation(pTask) > 0) return false; if (m_FixedData.m_bShowByPreTask && CheckPreTask(pTask) > 0) return false; if (m_FixedData.m_bShowByRepu && CheckRepu(pTask) > 0) return false; if (m_FixedData.m_bShowByTeam && CheckTeamTask(pTask) > 0) return false; if (m_FixedData.m_bShowByFaction && CheckFaction(pTask) > 0) return false; if (m_FixedData.m_bShowByPeriod && CheckPeriod(pTask) > 0) return false; if (m_FixedData.m_bShowByCharTime && CheckCharTime(pTask) > 0) return false; if (m_FixedData.m_bShowByRMB && CheckAccountRMB(pTask) > 0) return false; if (m_FixedData.m_bShowByWeddingOwner && CheckWeddingOwner(pTask) > 0) return false; if (m_FixedData.m_bShowByKing && CheckKing(pTask) > 0) return false; if (m_FixedData.m_bShowByNotInTeam && CheckNotInTeam(pTask) > 0) return false; if (m_FixedData.m_bShowByReincarnation && CheckReincarnation(pTask) > 0) return false; if (m_FixedData.m_bShowByRealmLevel && (CheckRealmLevel(pTask) > 0 || CheckRealmExpFull(pTask) > 0)) return false; if (m_FixedData.m_bShowByGeneralCard && CheckCardCollection(pTask) > 0) return false; if (m_FixedData.m_bShowByGeneralCardRank && CheckCardRankCount(pTask) > 0) return false; if (m_FixedData.m_bShowByHistoryStage && CheckHistoryStage(pTask) > 0) return false; return true; } public new uint GetType() { return m_FixedData.m_ulType; } void Init() { m_FixedData.m_bCanRedo = true; m_FixedData.m_bParentAlsoFail = true; m_FixedData.m_bCanGiveUp = true; m_FixedData.m_bCanRedoAfterFailure = true; m_FixedData.m_bClearAcquired = true; m_FixedData.m_enumMethod = (uint)TaskCompletionMethod.enumTMNone; m_FixedData.m_enumFinishType = (uint)TaskFinishType.enumTFTDirect; m_FixedData.m_bShowByDeposit = true; m_FixedData.m_bShowByGender = true; m_FixedData.m_bShowByItems = true; m_FixedData.m_bShowByFactionContrib = true; m_FixedData.m_bShowByNeedRecordTasksNum = true; m_FixedData.m_bShowByLev = true; m_FixedData.m_bShowByOccup = true; m_FixedData.m_bShowByPreTask = true; m_FixedData.m_bShowByRepu = true; m_FixedData.m_bShowByTeam = true; m_FixedData.m_bShowByFaction = true; m_FixedData.m_bShowByPeriod = true; m_FixedData.m_bShowPrompt = true; m_FixedData.m_bShowByCharTime = true; m_FixedData.m_bShowByRMB = true; m_FixedData.m_bShowBySpouse = true; m_FixedData.m_bShowByWeddingOwner = true; m_FixedData.m_bShowByKing = true; m_FixedData.m_bShowByNotInTeam = true; m_FixedData.m_bShowByGeneralCard = true; m_FixedData.m_ulDelvWorld = 1; m_FixedData.m_ulTransWldId = 1; m_FixedData.m_ulReachSiteId = 1; m_FixedData.m_lPeriodLimit = 1; m_FixedData.m_bCanSeekOut = false; m_FixedData.m_bShowDirection = true; m_FixedData.m_bDeliverySkill = false; // verison 77 m_FixedData.m_iDeliveredSkillID = 0; m_FixedData.m_iDeliveredSkillLevel = 0; m_FixedData.m_bShowGfxFinished = false; // version 78 m_FixedData.m_bChangePQRanking = false; // version 79. Ĭ�� PQ �ı���������� m_FixedData.m_bDisplayInExclusiveUI = false; m_FixedData.m_bReadyToNotifyServer = false; m_FixedData.m_bDistinguishedOcc = false; m_FixedData.m_bUsedInTokenShop = false; m_FixedData.m_iPremise_FactionRole = 6; m_FixedData.m_TreasureStartZone.x = 0; m_FixedData.m_TreasureStartZone.y = 0; m_FixedData.m_TreasureStartZone.z = 0; m_FixedData.m_ucZonesNumX = 1; m_FixedData.m_ucZonesNumZ = 1; m_FixedData.m_ucZoneSide = 10; m_FixedData.m_ucPremiseTransformedForm = 0xFF; m_FixedData.m_bShowByForce = true; m_FixedData.m_bShowByForceContribution = true; m_FixedData.m_bShowByForceReputation = true; m_FixedData.m_bShowByForceExp = true; m_FixedData.m_bShowByForceSP = true; m_FixedData.m_bShowByForceActivityLevel = true; m_FixedData.m_bShowByReincarnation = true; m_FixedData.m_bShowByRealmLevel = true; m_FixedData.m_bShowByGeneralCardRank = true; m_FixedData.m_bShowByHistoryStage = true; m_FixedData.m_iPremForceActivityLevel = -1; m_FixedData.m_iPremGeneralCardRank = -1; } void UnmarshalSpecialAwardData(byte[] data, ref long p) { // const char* p = pData; // m_ulSpecialAward = *(long*)p; // p += sizeof(long); m_FixedData.m_ulSpecialAward = GPDataTypeHelper.FromBytes(data, ref p); // return p - pData; } void UnmarshalKillMonster(byte[] data, ref long p) // int ATaskTempl::UnmarshalKillMonster(const char* pData) { // const char* p = pData; m_FixedData.m_ulMonsterWanted = GPDataTypeHelper.FromBytes(data, ref p); #if !TASK_TEMPL_EDITOR if (m_FixedData.m_ulMonsterWanted != 0) { m_FixedData.m_MonsterWanted = new MONSTER_WANTED[m_FixedData.m_ulMonsterWanted]; g_ulNewCount++; } #endif int sz = (int)(m_FixedData.m_ulMonsterWanted * Marshal.SizeOf()); if (sz != 0) { // memcpy(m_FixedData.m_MonsterWanted, p, sz); for( int i = 0; i < m_FixedData.m_MonsterWanted.Length; i++) { m_FixedData.m_MonsterWanted[i] = GPDataTypeHelper.FromBytes(data, ref p); } } // return p - pData; } void UnmarshalCollectItems(byte[] data, ref long p) // int ATaskTempl::UnmarshalCollectItems(const char* pData) { // const char* p = pData; m_FixedData.m_ulItemsWanted = GPDataTypeHelper.FromBytes(data, ref p); if (m_FixedData.m_ulItemsWanted != 0) { #if !TASK_TEMPL_EDITOR m_FixedData.m_ItemsWanted = new ITEM_WANTED[m_FixedData.m_ulItemsWanted]; g_ulNewCount++; #endif int sz = (int)(m_FixedData.m_ulItemsWanted * Marshal.SizeOf()); // memcpy(m_FixedData.m_ItemsWanted, p, sz); // p += sz; for( int i = 0; i < m_FixedData.m_ItemsWanted.Length; i++) { m_FixedData.m_ItemsWanted[i] = GPDataTypeHelper.FromBytes(data, ref p); } } m_FixedData.m_ulGoldWanted = GPDataTypeHelper.FromBytes(data, ref p); m_FixedData.m_iFactionContribWanted = GPDataTypeHelper.FromBytes(data, ref p); m_FixedData.m_iFactionExpContribWanted = GPDataTypeHelper.FromBytes(data, ref p); // return p - pData; } void unmarshal_str(byte[] data, ushort[] s, ref long p) // inline int unmarshal_str(const char* data, task_char*& s) { // const char* p = data; int len = GPDataTypeHelper.FromBytes( data, ref p); s = new ushort[len + 1]; g_ulNewCount++; s[len] = 0; if (len != 0) { // len *= sizeof(task_char); // memcpy(s, p, len); // p += len; for (int i = 0; i < len; i++) { s[i] = GPDataTypeHelper.FromBytes(data, ref p); } } // return p - data; } void unmarshal_option(ref talk_proc.option opt, byte[] data, ref long p) // int unmarshal_option(talk_proc::option* opt, const char* data) { // const char* p = data; opt.id = GPDataTypeHelper.FromBytes( data, ref p); opt.param = GPDataTypeHelper.FromBytes(data, ref p); uint sz = GPDataTypeHelper.FromBytes(data, ref p); if (sz != 0) { // memcpy(opt->text, p, sz); // p += sz; opt.text = new ushort[sz / sizeof(ushort)]; for (int i = 0; i < opt.text.Length; i++) { opt.text[i] = GPDataTypeHelper.FromBytes(data, ref p); } } // return p - data; } void unmarshal_window(ref talk_proc.window win, byte[] data, ref long p) // int unmarshal_window(talk_proc::window* win, const char* data) { // const char* p = data; win.id = GPDataTypeHelper.FromBytes(data, ref p); win.id_parent = GPDataTypeHelper.FromBytes(data, ref p); win.talk_text_len = GPDataTypeHelper.FromBytes(data, ref p); if (win.talk_text_len != 0) { // C++ // win->talk_text = new namechar[win->talk_text_len]; // size_t sz = sizeof(namechar) * win->talk_text_len; // memcpy(win->talk_text, p, sz); // p += sz; // g_ulNewCount++; win.talk_text = new ushort[win.talk_text_len]; for (int i = 0; i < win.talk_text_len; i++) { win.talk_text[i] = GPDataTypeHelper.FromBytes(data, ref p); } g_ulNewCount++; } win.num_option = GPDataTypeHelper.FromBytes( data, ref p); if (win.num_option != 0) { // C++ // win->options = new talk_proc::option[win->num_option]; // memset(win->options, 0, sizeof(talk_proc::option) * win->num_option); // g_ulNewCount++; // // for (int i = 0; i < win->num_option; i++) // p += unmarshal_option(&win->options[i], p); win.options = new talk_proc.option[win.num_option]; g_ulNewCount++; for (int i = 0; i < win.num_option; i++) { win.options[i] = new talk_proc.option(); unmarshal_option(ref win.options[i], data, ref p); } } // return p - data; } void unmarshal_talk_proc(ref talk_proc talk, byte[] data, ref long p) // int unmarshal_talk_proc(talk_proc* talk, const char* data) { // const char* p = data; int sz = GPDataTypeHelper.FromBytes(data, ref p); if (sz != 0) { // memcpy(talk->text, p, sz); // p += sz; for( int i = 0; i < talk.text.Length; i++) { talk.text[i] = GPDataTypeHelper.FromBytes(data, ref p); } } talk.num_window = GPDataTypeHelper.FromBytes(data, ref p); if (talk.num_window != 0) { // C++ // talk->windows = new talk_proc::window[talk->num_window]; // memset(talk->windows, 0, sizeof(talk_proc::window) * talk->num_window); // g_ulNewCount++; // // for (int i = 0; i < talk->num_window; i++) // p += unmarshal_window(&talk->windows[i], p); talk.windows = new talk_proc.window[talk.num_window]; g_ulNewCount++; for (int i = 0; i < talk.num_window; i++) { talk.windows[i] = new talk_proc.window(); unmarshal_window(ref talk.windows[i], data, ref p); } } // return p - data; } public void UnmarshalDynTask(byte[] pData, ref long p) { Init(); // const char* p = pData; // int p = 0; uint token_mask1, token_mask2; token_mask1 = GPDataTypeHelper.FromBytes(pData, ref p); token_mask2 = GPDataTypeHelper.FromBytes(pData, ref p); int token_count = 0; // dyn type m_FixedData.m_DynTaskType = GPDataTypeHelper.FromBytes(pData, ref p); // top task if (m_pParent == null) { switch (m_FixedData.m_DynTaskType) { case (byte)DynTaskType.enumDTTSpecialAward: case (byte)DynTaskType.enumDTTGiftCard: UnmarshalSpecialAwardData(pData, ref p); break; default: break; } } // id m_FixedData.m_ID = GPDataTypeHelper.FromBytes(pData, ref p); // name // char len = *p; p++; // len *= sizeof(task_char); // memcpy(m_szName, p, len); // p += len; byte nameLen = pData[p++]; // int nameByteLen = nameLen * sizeof(ushort); m_FixedData.m_szName = new ushort[nameLen]; for (int i = 0; i < nameLen; i++) { m_FixedData.m_szName[i] = GPDataTypeHelper.FromBytes(pData, ref p); } // choose one m_FixedData.m_bChooseOne = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // rand one m_FixedData.m_bRandOne = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // in order m_FixedData.m_bExeChildInOrder = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // parent fail m_FixedData.m_bParentAlsoFail = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // parent succ m_FixedData.m_bParentAlsoSucc = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // give up m_FixedData.m_bCanGiveUp = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // redo m_FixedData.m_bCanRedo = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // redo after fail m_FixedData.m_bCanRedoAfterFailure = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // clear as give up m_FixedData.m_bClearAsGiveUp = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // record m_FixedData.m_bNeedRecord = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // die m_FixedData.m_bFailAsPlayerDie = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // auto deliver m_FixedData.m_bAutoDeliver = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // death trig m_FixedData.m_bDeathTrig = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // clear acquired m_FixedData.m_bClearAcquired = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // spouse m_FixedData.m_bPremise_Spouse = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // teamwork m_FixedData.m_bTeamwork = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // direction m_FixedData.m_bShowDirection = GPDataTypeHelper.FromBytes(pData, ref p) != 0; // level m_FixedData.m_ulPremise_Lev_Min = GPDataTypeHelper.FromBytes(pData, ref p); m_FixedData.m_ulPremise_Lev_Max = GPDataTypeHelper.FromBytes(pData, ref p); // 0: time limit if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_ulTimeLimit = GPDataTypeHelper.FromBytes(pData, ref p); } // 1: reputation if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_lPremise_Reputation = GPDataTypeHelper.FromBytes(pData, ref p); } // 2: period if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_ulPremise_Period = GPDataTypeHelper.FromBytes(pData, ref p); } // 3: prem items if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_ulPremItems = GPDataTypeHelper.FromBytes(pData, ref p); #if !TASK_TEMPL_EDITOR m_FixedData.m_PremItems = new ITEM_WANTED[m_FixedData.m_ulPremItems]; g_ulNewCount++; #endif int sz = (int)(m_FixedData.m_ulPremItems * Marshal.SizeOf()); // memcpy(m_PremItems, p, sz); Array.Copy( pData, p, m_FixedData.m_PremItems, 0, sz ); p += sz; } // 4: delv in zone if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_bDelvInZone = GPDataTypeHelper.FromBytes(pData, ref p) != 0; m_FixedData.m_ulDelvWorld = GPDataTypeHelper.FromBytes(pData, ref p); m_FixedData.m_ulDelvRegionCnt = GPDataTypeHelper.FromBytes(pData, ref p); for (int i=0; i< m_FixedData.m_ulDelvRegionCnt; i++) { m_FixedData.m_pDelvRegion[i] = GPDataTypeHelper.FromBytes(pData, ref p); } /* m_DelvMinVert = *(ZONE_VERT*)p; p += sizeof(ZONE_VERT); m_DelvMaxVert = *(ZONE_VERT*)p; p += sizeof(ZONE_VERT);*/ } // 5: trans to if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_bTransTo = GPDataTypeHelper.FromBytes(pData, ref p) != 0; m_FixedData.m_ulTransWldId = GPDataTypeHelper.FromBytes(pData, ref p); m_FixedData.m_TransPt = GPDataTypeHelper.FromBytes(pData, ref p); } // 6: given items if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_ulGivenItems =GPDataTypeHelper.FromBytes(pData, ref p); m_FixedData.m_ulGivenCmnCount = GPDataTypeHelper.FromBytes(pData, ref p); m_FixedData.m_ulGivenTskCount = GPDataTypeHelper.FromBytes(pData, ref p); #if !TASK_TEMPL_EDITOR m_FixedData.m_GivenItems = new ITEM_WANTED[m_FixedData.m_ulGivenItems]; g_ulNewCount++; #endif int sz = (int)(m_FixedData.m_ulGivenItems * Marshal.SizeOf()); // memcpy(m_GivenItems, p, sz); Array.Copy( pData, p, m_FixedData.m_GivenItems, 0, sz ); p += sz; } // 7: deposit if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_ulPremise_Deposit = GPDataTypeHelper.FromBytes(pData, ref p); } // 8: pre task if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_ulPremise_Task_Count = GPDataTypeHelper.FromBytes(pData, ref p); m_FixedData.m_ulPremise_Task_Least_Num = GPDataTypeHelper.FromBytes(pData, ref p); // size_t sz = sizeof(long) * m_ulPremise_Task_Count; // memcpy(m_ulPremise_Tasks, p, sz); for (int i = 0; i < m_FixedData.m_ulPremise_Task_Count; i++) { m_FixedData.m_ulPremise_Tasks[i] = GPDataTypeHelper.FromBytes(pData, ref p); } } // 9: gender if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_ulGender = GPDataTypeHelper.FromBytes(pData, ref p); } // 10: occupation if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_ulOccupations = GPDataTypeHelper.FromBytes(pData, ref p); // size_t sz = sizeof(long) * m_ulOccupations; // memcpy(m_Occupations, p, sz); for (int i = 0; i < m_FixedData.m_ulOccupations; i++) { m_FixedData.m_Occupations[i] = GPDataTypeHelper.FromBytes(pData, ref p); } } // 11: mutex task if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_ulMutexTaskCount = GPDataTypeHelper.FromBytes(pData, ref p); // size_t sz = sizeof(long) * m_ulMutexTaskCount; // memcpy(m_ulMutexTasks, p, sz); for( int i = 0; i < m_FixedData.m_ulMutexTaskCount; i++ ) { m_FixedData.m_ulMutexTasks[i] = GPDataTypeHelper.FromBytes(pData, ref p); } } // 12: time table if (((1 << token_count++) & token_mask1) != 0) { m_FixedData.m_ulTimetable = GPDataTypeHelper.FromBytes(pData, ref p); #if !TASK_TEMPL_EDITOR m_FixedData.m_tmStart = new task_tm[m_FixedData.m_ulTimetable]; g_ulNewCount++; m_FixedData.m_tmEnd = new task_tm[m_FixedData.m_ulTimetable]; g_ulNewCount++; #endif int sz=0; sz = (int)(sizeof(byte) * m_FixedData.m_ulTimetable); // memcpy(m_tmType, p, sz); Array.Copy( pData, p, m_FixedData.m_tmType, 0, sz ); p += sz; sz = (int)(Marshal.SizeOf() * m_FixedData.m_ulTimetable); // memcpy(m_tmStart, p, sz); // p += sz; for (int i = 0; i < m_FixedData.m_ulTimetable; i++) { m_FixedData.m_tmStart[i] = GPDataTypeHelper.FromBytes(pData, ref p); } // memcpy(m_tmEnd, p, sz); // p += sz; for (int i = 0; i < m_FixedData.m_ulTimetable; i++) { m_FixedData.m_tmEnd[i] = GPDataTypeHelper.FromBytes(pData, ref p); } } // method m_FixedData.m_enumMethod = GPDataTypeHelper.FromBytes(pData, ref p); switch (m_FixedData.m_enumMethod) { case (uint)TaskCompletionMethod.enumTMKillNumMonster: // p += UnmarshalKillMonster(p); UnmarshalKillMonster( pData, ref p); break; case (uint)TaskCompletionMethod.enumTMCollectNumArticle: // p += UnmarshalCollectItems(p); UnmarshalCollectItems(data:pData, ref p); break; case (uint)TaskCompletionMethod.enumTMReachSite: m_FixedData.m_ulReachSiteId = GPDataTypeHelper.FromBytes(pData, ref p); // C++ // memcpy(m_pReachSite, p, sizeof(Task_Region)*m_ulReachSiteCnt); // p += sizeof(Task_Region)*m_ulReachSiteCnt; // Use m_ulReachSiteCnt instead of m_ulReachSiteId for count // Default to 1 if not set (matching C++ behavior) uint reachSiteCnt = m_FixedData.m_ulReachSiteCnt; if (reachSiteCnt == 0) reachSiteCnt = 1; // Allocate array if needed if (m_FixedData.m_pReachSite == null || m_FixedData.m_pReachSite.Length < reachSiteCnt) { m_FixedData.m_pReachSite = new Task_Region[reachSiteCnt]; } for (int i = 0; i < reachSiteCnt; i++) { m_FixedData.m_pReachSite[i] = GPDataTypeHelper.FromBytes(pData, ref p); } // memcpy(&m_ReachSiteMax, p, sizeof(ZONE_VERT)); // p += sizeof(ZONE_VERT); break; case (uint)TaskCompletionMethod.enumTMLeaveSite: m_FixedData.m_ulLeaveSiteId = GPDataTypeHelper.FromBytes(pData, ref p); // memcpy(m_pLeaveSite, p, sizeof(Task_Region)*m_ulLeaveSiteCnt); // p += sizeof(ZONE_VERT); // Use m_ulLeaveSiteCnt instead of m_ulLeaveSiteId for count // Default to 1 if not set (matching C++ behavior) uint leaveSiteCnt = m_FixedData.m_ulLeaveSiteCnt; if (leaveSiteCnt == 0) leaveSiteCnt = 1; // Allocate array if needed if (m_FixedData.m_pLeaveSite == null || m_FixedData.m_pLeaveSite.Length < leaveSiteCnt) { m_FixedData.m_pLeaveSite = new Task_Region[leaveSiteCnt]; } // Read the items long pBefore = p; for (int i = 0; i < leaveSiteCnt; i++) { m_FixedData.m_pLeaveSite[i] = GPDataTypeHelper.FromBytes(pData, ref p); } // C++ bug: advance by sizeof(ZONE_VERT) instead of sizeof(Task_Region)*m_ulLeaveSiteCnt // So we need to adjust p to match the C++ behavior long bytesShouldAdvance = Marshal.SizeOf(); p = pBefore + bytesShouldAdvance; // memcpy(&m_LeaveSiteMax, p, sizeof(ZONE_VERT)); // p += sizeof(ZONE_VERT); break; case (uint)TaskCompletionMethod.enumTMWaitTime: m_FixedData.m_ulWaitTime = GPDataTypeHelper.FromBytes(pData, ref p); break; } // finish type m_FixedData.m_enumFinishType = GPDataTypeHelper.FromBytes(pData, ref p); // award // C++: p += m_Award_S->UnmarshalBasicData(p); // Need to pass array starting from current position p byte[] awardData = new byte[pData.Length - (int)p]; Array.Copy(pData, (int)p, awardData, 0, awardData.Length); p += m_Award_S.UnmarshalBasicData(awardData); // talks unmarshal_str(pData, m_pwstrDescript, ref p); unmarshal_str(pData, m_pwstrOkText, ref p); unmarshal_str(pData, m_pwstrNoText, ref p); unmarshal_talk_proc(ref m_DelvTaskTalk, pData, ref p); unmarshal_talk_proc(ref m_UnqualifiedTalk, pData, ref p); unmarshal_talk_proc(ref m_DelvItemTalk, pData, ref p); unmarshal_talk_proc(ref m_ExeTalk, pData, ref p); unmarshal_talk_proc(ref m_AwardTalk, pData, ref p); #if !_TASK_CLIENT CheckMask(); #else SyncTaskType(); #endif m_nSubCount = GPDataTypeHelper.FromBytes( pData, ref p); for (int i = 0; i < m_nSubCount; i++) { // ATaskTempl* pSub = new ATaskTempl; // g_ulNewCount++; // AddSubTaskTempl(pSub); // p += pSub->UnmarshalDynTask(p); ATaskTempl pSub = new ATaskTempl(); g_ulNewCount++; AddSubTaskTempl( pSub ); pSub.UnmarshalDynTask( pData , ref p); } SynchID(); if (m_pParent == null) CheckDepth(); // return p - pData; } public bool IsAutoDeliver() { return m_FixedData.m_bDeathTrig || m_FixedData.m_bAutoDeliver; } public void FillUnserializableDataWhenPlayGame(TaskTemplContainerSO container) { m_pParent = container.GetTaskTemplate(ParentID); m_pPrevSibling = container.GetTaskTemplate( PrevSiblingID ); m_pNextSibling = container.GetTaskTemplate( NextSiblingID ); m_pFirstChild = container.GetTaskTemplate( FirstChildID ); // Unserialize m_pszPQExp and m_pPQExpArr if (m_FixedData.m_ulPQExpCnt > 0) { int rowCount = (int)m_FixedData.m_ulPQExpCnt; int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; m_FixedData.m_pszPQExp = new byte[rowCount, colCount]; m_FixedData.m_pPQExpArr = new TASK_EXPRESSION[rowCount, colCount]; for (int i = 0; i < rowCount; i++) { for (int j = 0; j < colCount; j++) { m_FixedData.m_pszPQExp[i, j] = m_FixedData.m_pszPQExp_Seri[ i * colCount + j ]; m_FixedData.m_pPQExpArr[i, j] = m_FixedData.m_pPQExpArr_Seri[ i * colCount + j ]; } } } // Unserialize m_pszExp and m_pExpArr if (m_FixedData.m_ulExpCnt > 0) { int rowCount = (int)m_FixedData.m_ulExpCnt; int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; m_FixedData.m_pszExp = new byte[rowCount, colCount]; m_FixedData.m_pExpArr = new TASK_EXPRESSION[rowCount, colCount]; for (int i = 0; i < rowCount; i++) { for (int j = 0; j < colCount; j++) { m_FixedData.m_pszExp[i, j] = m_FixedData.m_pszExp_Seri[ i * colCount + j ]; m_FixedData.m_pExpArr[i, j] = m_FixedData.m_pExpArr_Seri[ i * colCount + j ]; } } } // Unserialize m_pTaskChar if (m_FixedData.m_ulTaskCharCnt > 0) { int rowCount = (int)m_FixedData.m_ulTaskCharCnt; int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; m_FixedData.m_pTaskChar = new ushort[rowCount, colCount]; for (int i = 0; i < rowCount; i++) { for (int j = 0; j < colCount; j++) { m_FixedData.m_pTaskChar[i, j] = m_FixedData.m_pTaskChar_Seri[ i * colCount + j ]; } } } } public void SyncSerializableDataAfterLoaded() { if(m_pParent!=null) ParentID = m_pParent.m_ID; if(m_pPrevSibling!= null) PrevSiblingID = m_pPrevSibling.m_ID; if(m_pNextSibling!= null) NextSiblingID = m_pNextSibling.m_ID; if(m_pFirstChild!= null) FirstChildID = m_pFirstChild.m_ID; } public string GetName() { return ByteToStringUtils.UshortArrayToUnicodeString(m_FixedData.m_szName); } } }