Files
test/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs
T
2025-12-20 11:52:13 +07:00

5445 lines
232 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using 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;
public short x;
public short y;
public short z;
}
// 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
{
/// <summary>
/// 必须定义operator == // Must define operator ==
/// </summary>
/// <typeparam name="T_NAME">The type of the objects to compare</typeparam>
/// <param name="p1">First object to compare</param>
/// <param name="p2">Second object to compare</param>
/// <returns>True if both objects are equal or both are null</returns>
public static bool CompareTwoPointer<T_NAME>(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
};
/// <summary>
/// Completion Method
/// </summary>
// 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;
}*/
/// <summary>
/// 任务模板类 // Task Template Class
/// include
/// </summary>
[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;
uint m_ulAwardType_S => m_FixedData.m_ulAwardType_S;
uint m_ulAwardType_F => m_FixedData.m_ulAwardType_F;
// ʱ¼äÏÞÖÆ
uint m_ulTimeLimit => m_FixedData.m_ulTimeLimit;
/* ÆÕͨºÍ°´Ã¿¸ö·½Ê½ */
AWARD_DATA m_Award_S => m_FixedData.m_Award_S; /* ³É¹¦ */
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(FileStream 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(FileStream 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<int>(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(FileStream 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(FileStream 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<uint>(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<ushort>(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<byte>(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<uint>(fp, ref readBytes);//value 103
logContent += $"Type: {fixedData.m_ulType}\n";
// Time Limit (unsigned long m_ulTimeLimit;)
fixedData.m_ulTimeLimit = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulTimeLimit: {fixedData.m_ulTimeLimit}\n";
// Offline Fail (bool m_bOfflineFail;)
fixedData.m_bOfflineFail = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bOfflineFail: {fixedData.m_bOfflineFail}\n";
// Absolute Fail (bool m_bAbsFail;)
fixedData.m_bAbsFail = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bAbsFail: {fixedData.m_bAbsFail}\n";
// Absolute Fail Time (task_tm m_tmAbsFailTime;)
fixedData.m_tmAbsFailTime = AAssit.ReadFromBinaryOf<task_tm>(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<byte>(fp, ref readBytes) > 0;
logContent += $"m_bItemNotTakeOff: {fixedData.m_bItemNotTakeOff}\n";
// Absolute Time (bool m_bAbsTime;)
fixedData.m_bAbsTime = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bAbsTime: {fixedData.m_bAbsTime}\n";
// Timetable count (unsigned long m_ulTimetable;)
fixedData.m_ulTimetable = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulTimetable: {fixedData.m_ulTimetable}\n";
// Timetable type (char m_tmType[MAX_TIMETABLE_SIZE];)
fixedData.m_tmType = AAssit.ReadArrayFromBinary<byte>(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<int>(fp, ref readBytes);
logContent += $"m_lAvailFrequency: {fixedData.m_lAvailFrequency}\n";
// Period limit (long m_lPeriodLimit;)
fixedData.m_lPeriodLimit = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_lPeriodLimit: {fixedData.m_lPeriodLimit}\n";
// Choose one subtask (bool m_bChooseOne;)
fixedData.m_bChooseOne = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bChooseOne: {fixedData.m_bChooseOne}\n";
// Random one subtask (bool m_bRandOne;)
fixedData.m_bRandOne = AAssit.ReadFromBinaryOf<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<uint>(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<byte>(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<uint>(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<uint>(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<byte>(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<uint>(fp, ref readBytes);
logContent += $"m_ulEnterRegionWorld: {fixedData.m_ulEnterRegionWorld}\n\n";
// Enter region count (unsigned long m_ulEnterRegionCnt;)
fixedData.m_ulEnterRegionCnt = AAssit.ReadFromBinaryOf<uint>(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<byte>(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<uint>(fp, ref readBytes);
logContent += $"m_ulLeaveRegionWorld: {fixedData.m_ulLeaveRegionWorld}\n\n";
// Leave region count (unsigned long m_ulLeaveRegionCnt;)
fixedData.m_ulLeaveRegionCnt = AAssit.ReadFromBinaryOf<uint>(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<byte>(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<byte>(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<uint>(fp, ref readBytes);
logContent += $"m_ulTransWldId: {fixedData.m_ulTransWldId}\n\n";
// Teleport position (ZONE_VERT m_TransPt;)
fixedData.m_TransPt = AAssit.ReadFromBinaryOf<ZONE_VERT>(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<int>(fp, ref readBytes);
logContent += $"m_lMonsCtrl: {fixedData.m_lMonsCtrl}\n\n";
// Trigger controller (bool m_bTrigCtrl;)
fixedData.m_bTrigCtrl = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bTrigCtrl: {fixedData.m_bTrigCtrl}\n\n";
// Auto deliver (bool m_bAutoDeliver;)
fixedData.m_bAutoDeliver = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bAutoDeliver: {fixedData.m_bAutoDeliver}\n\n";
// Display in exclusive UI (bool m_bDisplayInExclusiveUI;)
fixedData.m_bDisplayInExclusiveUI = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bDisplayInExclusiveUI: {fixedData.m_bDisplayInExclusiveUI}\n\n";
// Ready to notify server (bool m_bReadyToNotifyServer;)
fixedData.m_bReadyToNotifyServer = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bReadyToNotifyServer: {fixedData.m_bReadyToNotifyServer}\n\n";
// Used in token shop (bool m_bUsedInTokenShop;)
fixedData.m_bUsedInTokenShop = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bUsedInTokenShop: {fixedData.m_bUsedInTokenShop}\n\n";
// Death trigger (bool m_bDeathTrig;)
fixedData.m_bDeathTrig = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bDeathTrig: {fixedData.m_bDeathTrig}\n\n";
// Clear acquired (bool m_bClearAcquired;)
fixedData.m_bClearAcquired = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bClearAcquired: {fixedData.m_bClearAcquired}\n\n";
// Suitable level (uint m_ulSuitableLevel;)
fixedData.m_ulSuitableLevel = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulSuitableLevel: {fixedData.m_ulSuitableLevel}\n\n";
// Show prompt (bool m_bShowPrompt;)
fixedData.m_bShowPrompt = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowPrompt: {fixedData.m_bShowPrompt}\n\n";
// Key task (bool m_bKeyTask;)
fixedData.m_bKeyTask = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bKeyTask: {fixedData.m_bKeyTask}\n\n";
// Delivery NPC (uint m_ulDelvNPC;)
fixedData.m_ulDelvNPC = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulDelvNPC: {fixedData.m_ulDelvNPC}\n\n";
// Award NPC (uint m_ulAwardNPC;)
fixedData.m_ulAwardNPC = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulAwardNPC: {fixedData.m_ulAwardNPC}\n\n";
// Skill task (bool m_bSkillTask;)
fixedData.m_bSkillTask = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bSkillTask: {fixedData.m_bSkillTask}\n\n";
// Can seek out (bool m_bCanSeekOut;)
fixedData.m_bCanSeekOut = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bCanSeekOut: {fixedData.m_bCanSeekOut}\n\n";
// Show direction (bool m_bShowDirection;)
fixedData.m_bShowDirection = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowDirection: {fixedData.m_bShowDirection}\n\n";
// Marriage (bool m_bMarriage;)
fixedData.m_bMarriage = AAssit.ReadFromBinaryOf<byte>(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<uint>(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<byte>(fp, ref readBytes) > 0;
logContent += $"m_bSwitchSceneFail: {fixedData.m_bSwitchSceneFail}\n\n";
// Hidden (bool m_bHidden;)
fixedData.m_bHidden = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bHidden: {fixedData.m_bHidden}\n\n";
// Delivery skill (bool m_bDeliverySkill;)
fixedData.m_bDeliverySkill = AAssit.ReadFromBinaryOf<byte>(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<int>(fp, ref readBytes);
logContent += $"m_iDeliveredSkillID: {fixedData.m_iDeliveredSkillID}\n\n";
fixedData.m_iDeliveredSkillLevel = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iDeliveredSkillLevel: {fixedData.m_iDeliveredSkillLevel}\n\n";
// Show GFX finished (bool m_bShowGfxFinished;)
fixedData.m_bShowGfxFinished = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowGfxFinished: {fixedData.m_bShowGfxFinished}\n\n";
// Change PQ ranking (bool m_bChangePQRanking;)
fixedData.m_bChangePQRanking = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bChangePQRanking: {fixedData.m_bChangePQRanking}\n\n";
// Compare items and inventory (bool m_bCompareItemAndInventory;)
fixedData.m_bCompareItemAndInventory = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bCompareItemAndInventory: {fixedData.m_bCompareItemAndInventory}\n\n";
// Inventory slots (uint m_ulInventorySlotNum;)
fixedData.m_ulInventorySlotNum = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulInventorySlotNum: {fixedData.m_ulInventorySlotNum}\n\n";
// PQ task (bool m_bPQTask;)
fixedData.m_bPQTask = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPQTask: {fixedData.m_bPQTask}\n\n";
// PQ expression count (uint m_ulPQExpCnt;)
fixedData.m_ulPQExpCnt = AAssit.ReadFromBinaryOf<uint>(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<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPQSubTask: {fixedData.m_bPQSubTask}\n\n";
// Clear contribution on start (bool m_bClearContrib;)
fixedData.m_bClearContrib = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bClearContrib: {fixedData.m_bClearContrib}\n\n";
// Monster contribution count (uint m_ulMonsterContribCnt;)
fixedData.m_ulMonsterContribCnt = AAssit.ReadFromBinaryOf<uint>(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<int>(fp, ref readBytes);
logContent += $"m_iPremNeedRecordTasksNum: {fixedData.m_iPremNeedRecordTasksNum}\n\n";
fixedData.m_bShowByNeedRecordTasksNum = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByNeedRecordTasksNum: {fixedData.m_bShowByNeedRecordTasksNum}\n\n";
fixedData.m_iPremiseFactionContrib = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iPremiseFactionContrib: {fixedData.m_iPremiseFactionContrib}\n\n";
fixedData.m_bShowByFactionContrib = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByFactionContrib: {fixedData.m_bShowByFactionContrib}\n\n";
fixedData.m_bAccountTaskLimit = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bAccountTaskLimit: {fixedData.m_bAccountTaskLimit}\n\n";
fixedData.m_bRoleTaskLimit = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bRoleTaskLimit: {fixedData.m_bRoleTaskLimit}\n\n";
fixedData.m_ulAccountTaskLimitCnt = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulAccountTaskLimitCnt: {fixedData.m_ulAccountTaskLimitCnt}\n\n";
fixedData.m_bLeaveFactionFail = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bLeaveFactionFail: {fixedData.m_bLeaveFactionFail}\n\n";
fixedData.m_bNotIncCntWhenFailed = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bNotIncCntWhenFailed: {fixedData.m_bNotIncCntWhenFailed}\n\n";
fixedData.m_bNotClearItemWhenFailed = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bNotClearItemWhenFailed: {fixedData.m_bNotClearItemWhenFailed}\n\n";
fixedData.m_bDisplayInTitleTaskUI = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bDisplayInTitleTaskUI: {fixedData.m_bDisplayInTitleTaskUI}\n\n";
// Opening conditions
fixedData.m_ucPremiseTransformedForm = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes);
logContent += $"m_ucPremiseTransformedForm: {fixedData.m_ucPremiseTransformedForm}\n\n";
fixedData.m_bShowByTransformed = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByTransformed: {fixedData.m_bShowByTransformed}\n\n";
fixedData.m_ulPremise_Lev_Min = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremise_Lev_Min: {fixedData.m_ulPremise_Lev_Min}\n\n";
fixedData.m_ulPremise_Lev_Max = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremise_Lev_Max: {fixedData.m_ulPremise_Lev_Max}\n\n";
fixedData.m_bPremCheckMaxHistoryLevel = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_bPremCheckMaxHistoryLevel: {fixedData.m_bPremCheckMaxHistoryLevel}\n\n";
fixedData.m_bShowByLev = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByLev: {fixedData.m_bShowByLev}\n\n";
fixedData.m_bPremCheckReincarnation = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPremCheckReincarnation: {fixedData.m_bPremCheckReincarnation}\n\n";
fixedData.m_ulPremReincarnationMin = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremReincarnationMin: {fixedData.m_ulPremReincarnationMin}\n\n";
fixedData.m_ulPremReincarnationMax = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremReincarnationMax: {fixedData.m_ulPremReincarnationMax}\n\n";
fixedData.m_bShowByReincarnation = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByReincarnation: {fixedData.m_bShowByReincarnation}\n\n";
fixedData.m_bPremCheckRealmLevel = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPremCheckRealmLevel: {fixedData.m_bPremCheckRealmLevel}\n\n";
fixedData.m_ulPremRealmLevelMin = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremRealmLevelMin: {fixedData.m_ulPremRealmLevelMin}\n\n";
fixedData.m_ulPremRealmLevelMax = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremRealmLevelMax: {fixedData.m_ulPremRealmLevelMax}\n\n";
fixedData.m_bPremCheckRealmExpFull = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPremCheckRealmExpFull: {fixedData.m_bPremCheckRealmExpFull}\n\n";
fixedData.m_bShowByRealmLevel = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByRealmLevel: {fixedData.m_bShowByRealmLevel}\n\n";
fixedData.m_ulPremItems = AAssit.ReadFromBinaryOf<uint>(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<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByItems: {fixedData.m_bShowByItems}\n\n";
fixedData.m_bPremItemsAnyOne = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPremItemsAnyOne: {fixedData.m_bPremItemsAnyOne}\n\n";
fixedData.m_ulGivenItems = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulGivenItems: {fixedData.m_ulGivenItems}\n\n";
fixedData.m_ulGivenCmnCount = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulGivenCmnCount: {fixedData.m_ulGivenCmnCount}\n\n";
fixedData.m_ulGivenTskCount = AAssit.ReadFromBinaryOf<uint>(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<uint>(fp, ref readBytes);
logContent += $"m_ulPremise_Deposit: {fixedData.m_ulPremise_Deposit}\n\n";
fixedData.m_bShowByDeposit = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByDeposit: {fixedData.m_bShowByDeposit}\n\n";
fixedData.m_lPremise_Reputation = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_lPremise_Reputation: {fixedData.m_lPremise_Reputation}\n\n";
fixedData.m_lPremise_RepuMax = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_lPremise_RepuMax: {fixedData.m_lPremise_RepuMax}\n\n";
fixedData.m_bShowByRepu = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByRepu: {fixedData.m_bShowByRepu}\n\n";
fixedData.m_ulPremise_Task_Count = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremise_Task_Count: {fixedData.m_ulPremise_Task_Count}\n\n";
fixedData.m_ulPremise_Tasks = AAssit.ReadArrayFromBinary<uint>(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<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByPreTask: {fixedData.m_bShowByPreTask}\n\n";
fixedData.m_ulPremise_Task_Least_Num = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremise_Task_Least_Num: {fixedData.m_ulPremise_Task_Least_Num}\n\n";
fixedData.m_ulPremise_Period = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremise_Period: {fixedData.m_ulPremise_Period}\n\n";
fixedData.m_bShowByPeriod = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByPeriod: {fixedData.m_bShowByPeriod}\n\n";
fixedData.m_ulPremise_Faction = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremise_Faction: {fixedData.m_ulPremise_Faction}\n\n";
fixedData.m_iPremise_FactionRole = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iPremise_FactionRole: {fixedData.m_iPremise_FactionRole}\n\n";
fixedData.m_bShowByFaction = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByFaction: {fixedData.m_bShowByFaction}\n\n";
// Gender and occupation restrictions
fixedData.m_ulGender = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulGender: {fixedData.m_ulGender}\n\n";
fixedData.m_bShowByGender = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByGender: {fixedData.m_bShowByGender}\n\n";
fixedData.m_ulOccupations = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulOccupations: {fixedData.m_ulOccupations}\n\n";
fixedData.m_Occupations = AAssit.ReadArrayFromBinary<uint>(fp, TaskTemplConstants.MAX_OCCUPATIONS, ref readBytes);
logContent += $"m_Occupations[0..{TaskTemplConstants.MAX_OCCUPATIONS - 1}] loaded\n\n";
fixedData.m_bShowByOccup = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByOccup: {fixedData.m_bShowByOccup}\n\n";
// Spouse related
fixedData.m_bPremise_Spouse = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPremise_Spouse: {fixedData.m_bPremise_Spouse}\n\n";
fixedData.m_bShowBySpouse = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowBySpouse: {fixedData.m_bShowBySpouse}\n\n";
fixedData.m_bPremiseWeddingOwner = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPremiseWeddingOwner: {fixedData.m_bPremiseWeddingOwner}\n\n";
fixedData.m_bShowByWeddingOwner = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByWeddingOwner: {fixedData.m_bShowByWeddingOwner}\n\n";
// GM and shield user
fixedData.m_bGM = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bGM: {fixedData.m_bGM}\n\n";
fixedData.m_bShieldUser = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShieldUser: {fixedData.m_bShieldUser}\n\n";
// RMB limits
fixedData.m_bShowByRMB = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByRMB: {fixedData.m_bShowByRMB}\n\n";
fixedData.m_ulPremRMBMin = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremRMBMin: {fixedData.m_ulPremRMBMin}\n\n";
fixedData.m_ulPremRMBMax = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremRMBMax: {fixedData.m_ulPremRMBMax}\n\n";
// Character time
fixedData.m_bCharTime = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bCharTime: {fixedData.m_bCharTime}\n\n";
fixedData.m_bShowByCharTime = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByCharTime: {fixedData.m_bShowByCharTime}\n\n";
fixedData.m_iCharStartTime = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iCharStartTime: {fixedData.m_iCharStartTime}\n\n";
fixedData.m_iCharEndTime = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iCharEndTime: {fixedData.m_iCharEndTime}\n\n";
fixedData.m_tmCharEndTime = AAssit.ReadFromBinaryOf<task_tm>(fp, ref readBytes);
logContent += $"m_tmCharEndTime.day: {fixedData.m_tmCharEndTime.day}\n\n";
fixedData.m_ulCharTimeGreaterThan = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulCharTimeGreaterThan: {fixedData.m_ulCharTimeGreaterThan}\n\n";
// Related and mutex tasks
fixedData.m_ulPremise_Cotask = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremise_Cotask: {fixedData.m_ulPremise_Cotask}\n\n";
fixedData.m_ulCoTaskCond = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulCoTaskCond: {fixedData.m_ulCoTaskCond}\n\n";
fixedData.m_ulMutexTaskCount = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulMutexTaskCount: {fixedData.m_ulMutexTaskCount}\n\n";
fixedData.m_ulMutexTasks = AAssit.ReadArrayFromBinary<uint>(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<int>(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<byte>(fp, ref readBytes);
logContent += $"m_DynTaskType: {fixedData.m_DynTaskType}\n\n";
fixedData.m_ulSpecialAward = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulSpecialAward: {fixedData.m_ulSpecialAward}\n\n";
// Team information
fixedData.m_bTeamwork = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bTeamwork: {fixedData.m_bTeamwork}\n\n";
fixedData.m_bRcvByTeam = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bRcvByTeam: {fixedData.m_bRcvByTeam}\n\n";
fixedData.m_bSharedTask = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bSharedTask: {fixedData.m_bSharedTask}\n\n";
fixedData.m_bSharedAchieved = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bSharedAchieved: {fixedData.m_bSharedAchieved}\n\n";
fixedData.m_bCheckTeammate = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bCheckTeammate: {fixedData.m_bCheckTeammate}\n\n";
fixedData.m_fTeammateDist = AAssit.ReadFromBinaryOf<float>(fp, ref readBytes);
logContent += $"m_fTeammateDist: {fixedData.m_fTeammateDist}\n\n";
fixedData.m_bAllFail = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bAllFail: {fixedData.m_bAllFail}\n\n";
fixedData.m_bCapFail = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bCapFail: {fixedData.m_bCapFail}\n\n";
fixedData.m_bCapSucc = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bCapSucc: {fixedData.m_bCapSucc}\n\n";
fixedData.m_fSuccDist = AAssit.ReadFromBinaryOf<float>(fp, ref readBytes);
logContent += $"m_fSuccDist: {fixedData.m_fSuccDist}\n\n";
fixedData.m_bDismAsSelfFail = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bDismAsSelfFail: {fixedData.m_bDismAsSelfFail}\n\n";
fixedData.m_bRcvChckMem = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bRcvChckMem: {fixedData.m_bRcvChckMem}\n\n";
fixedData.m_fRcvMemDist = AAssit.ReadFromBinaryOf<float>(fp, ref readBytes);
logContent += $"m_fRcvMemDist: {fixedData.m_fRcvMemDist}\n\n";
fixedData.m_bCntByMemPos = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bCntByMemPos: {fixedData.m_bCntByMemPos}\n\n";
fixedData.m_fCntMemDist = AAssit.ReadFromBinaryOf<float>(fp, ref readBytes);
logContent += $"m_fCntMemDist: {fixedData.m_fCntMemDist}\n\n";
fixedData.m_bAllSucc = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bAllSucc: {fixedData.m_bAllSucc}\n\n";
fixedData.m_bCoupleOnly = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bCoupleOnly: {fixedData.m_bCoupleOnly}\n\n";
fixedData.m_bDistinguishedOcc = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bDistinguishedOcc: {fixedData.m_bDistinguishedOcc}\n\n";
fixedData.m_ulTeamMemsWanted = AAssit.ReadFromBinaryOf<uint>(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<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByTeam: {fixedData.m_bShowByTeam}\n\n";
// Premise global key/value
fixedData.m_bPremNeedComp = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPremNeedComp: {fixedData.m_bPremNeedComp}\n\n";
fixedData.m_nPremExp1AndOrExp2 = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_nPremExp1AndOrExp2: {fixedData.m_nPremExp1AndOrExp2}\n\n";
fixedData.m_Prem1KeyValue = AAssit.ReadFromBinaryOf<COMPARE_KEY_VALUE>(fp, ref readBytes);
logContent += $"m_Prem1KeyValue loaded\n\n";
fixedData.m_Prem2KeyValue = AAssit.ReadFromBinaryOf<COMPARE_KEY_VALUE>(fp, ref readBytes);
logContent += $"m_Prem2KeyValue loaded\n\n";
// Force related
fixedData.m_bPremCheckForce = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPremCheckForce: {fixedData.m_bPremCheckForce}\n\n";
fixedData.m_iPremForce = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iPremForce: {fixedData.m_iPremForce}\n\n";
fixedData.m_bShowByForce = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByForce: {fixedData.m_bShowByForce}\n\n";
fixedData.m_iPremForceReputation = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iPremForceReputation: {fixedData.m_iPremForceReputation}\n\n";
fixedData.m_bShowByForceReputation = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByForceReputation: {fixedData.m_bShowByForceReputation}\n\n";
fixedData.m_iPremForceContribution = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iPremForceContribution: {fixedData.m_iPremForceContribution}\n\n";
fixedData.m_bShowByForceContribution = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByForceContribution: {fixedData.m_bShowByForceContribution}\n\n";
fixedData.m_iPremForceExp = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iPremForceExp: {fixedData.m_iPremForceExp}\n\n";
fixedData.m_bShowByForceExp = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByForceExp: {fixedData.m_bShowByForceExp}\n\n";
fixedData.m_iPremForceSP = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iPremForceSP: {fixedData.m_iPremForceSP}\n\n";
fixedData.m_bShowByForceSP = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByForceSP: {fixedData.m_bShowByForceSP}\n\n";
fixedData.m_iPremForceActivityLevel = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iPremForceActivityLevel: {fixedData.m_iPremForceActivityLevel}\n\n";
fixedData.m_bShowByForceActivityLevel = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByForceActivityLevel: {fixedData.m_bShowByForceActivityLevel}\n\n";
// King / Not in team / Titles
fixedData.m_bPremIsKing = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPremIsKing: {fixedData.m_bPremIsKing}\n\n";
fixedData.m_bShowByKing = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByKing: {fixedData.m_bShowByKing}\n\n";
fixedData.m_bPremNotInTeam = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bPremNotInTeam: {fixedData.m_bPremNotInTeam}\n\n";
fixedData.m_bShowByNotInTeam = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByNotInTeam: {fixedData.m_bShowByNotInTeam}\n\n";
fixedData.m_iPremTitleNumTotal = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_iPremTitleNumTotal: {fixedData.m_iPremTitleNumTotal}\n\n";
fixedData.m_iPremTitleNumRequired = AAssit.ReadFromBinaryOf<uint>(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<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByTitle: {fixedData.m_bShowByTitle}\n\n";
var premHistoryIdx = AAssit.ReadArrayFromBinary<int>(fp, 2, ref readBytes);
fixedData.m_iPremHistoryStageIndex = premHistoryIdx;
logContent += $"m_iPremHistoryStageIndex[0..1] loaded\n\n";
fixedData.m_bShowByHistoryStage = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByHistoryStage: {fixedData.m_bShowByHistoryStage}\n\n";
fixedData.m_ulPremGeneralCardCount = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremGeneralCardCount: {fixedData.m_ulPremGeneralCardCount}\n\n";
fixedData.m_bShowByGeneralCard = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByGeneralCard: {fixedData.m_bShowByGeneralCard}\n\n";
fixedData.m_iPremGeneralCardRank = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iPremGeneralCardRank: {fixedData.m_iPremGeneralCardRank}\n\n";
fixedData.m_ulPremGeneralCardRankCount = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPremGeneralCardRankCount: {fixedData.m_ulPremGeneralCardRankCount}\n\n";
fixedData.m_bShowByGeneralCardRank = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bShowByGeneralCardRank: {fixedData.m_bShowByGeneralCardRank}\n\n";
// Completion methods and conditions
fixedData.m_enumMethod = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_enumMethod: {fixedData.m_enumMethod}\n\n";
fixedData.m_enumFinishType = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_enumFinishType: {fixedData.m_enumFinishType}\n\n";
// Task methods
fixedData.m_ulPlayerWanted = AAssit.ReadFromBinaryOf<uint>(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<uint>(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<uint>(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<uint>(fp, ref readBytes);
logContent += $"m_ulGoldWanted: {fixedData.m_ulGoldWanted}\n\n";
fixedData.m_iFactionContribWanted = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iFactionContribWanted: {fixedData.m_iFactionContribWanted}\n\n";
fixedData.m_iFactionExpContribWanted = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iFactionExpContribWanted: {fixedData.m_iFactionExpContribWanted}\n\n";
fixedData.m_ulNPCToProtect = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulNPCToProtect: {fixedData.m_ulNPCToProtect}\n\n";
fixedData.m_ulProtectTimeLen = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulProtectTimeLen: {fixedData.m_ulProtectTimeLen}\n\n";
fixedData.m_ulNPCMoving = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulNPCMoving: {fixedData.m_ulNPCMoving}\n\n";
fixedData.m_ulNPCDestSite = AAssit.ReadFromBinaryOf<uint>(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<uint>(fp, ref readBytes);
logContent += $"m_ulReachSiteCnt: {fixedData.m_ulReachSiteCnt}\n\n";
fixedData.m_ulReachSiteId = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulReachSiteId: {fixedData.m_ulReachSiteId}\n\n";
fixedData.m_ulWaitTime = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulWaitTime: {fixedData.m_ulWaitTime}\n\n";
// Treasure map (TREA)
fixedData.m_TreasureStartZone = AAssit.ReadFromBinaryOf<ZONE_VERT>(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<byte>(fp, ref readBytes);
logContent += $"m_ucZonesNumX: {fixedData.m_ucZonesNumX}\n\n";
fixedData.m_ucZonesNumZ = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes);
logContent += $"m_ucZonesNumZ: {fixedData.m_ucZonesNumZ}\n\n";
fixedData.m_ucZoneSide = AAssit.ReadFromBinaryOf<byte>(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<uint>(fp, ref readBytes);
logContent += $"m_ulLeaveSiteCnt: {fixedData.m_ulLeaveSiteCnt}\n\n";
fixedData.m_ulLeaveSiteId = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulLeaveSiteId: {fixedData.m_ulLeaveSiteId}\n\n";
// Finish global key/value
fixedData.m_bFinNeedComp = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bFinNeedComp: {fixedData.m_bFinNeedComp}\n\n";
fixedData.m_nFinExp1AndOrExp2 = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_nFinExp1AndOrExp2: {fixedData.m_nFinExp1AndOrExp2}\n\n";
fixedData.m_Fin1KeyValue = AAssit.ReadFromBinaryOf<COMPARE_KEY_VALUE>(fp, ref readBytes);
logContent += $"m_Fin1KeyValue loaded\n\n";
fixedData.m_Fin2KeyValue = AAssit.ReadFromBinaryOf<COMPARE_KEY_VALUE>(fp, ref readBytes);
logContent += $"m_Fin2KeyValue loaded\n\n";
// Expressions to display
fixedData.m_ulExpCnt = AAssit.ReadFromBinaryOf<uint>(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<uint>(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<byte>(fp, ref readBytes);
logContent += $"m_ucTransformedForm: {fixedData.m_ucTransformedForm}\n\n";
// Level/Reincarnation/Realm
fixedData.m_ulReachLevel = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulReachLevel: {fixedData.m_ulReachLevel}\n\n";
fixedData.m_ulReachReincarnationCount = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulReachReincarnationCount: {fixedData.m_ulReachReincarnationCount}\n\n";
fixedData.m_ulReachRealmLevel = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulReachRealmLevel: {fixedData.m_ulReachRealmLevel}\n\n";
fixedData.m_uiEmotion = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_uiEmotion: {fixedData.m_uiEmotion}\n\n";
// Award types and pointers
fixedData.m_ulAwardType_S = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulAwardType_S: {fixedData.m_ulAwardType_S}\n\n";
fixedData.m_ulAwardType_F = AAssit.ReadFromBinaryOf<uint>(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<uint>(fp, ref readBytes);
logContent += $"m_ulParent: {fixedData.m_ulParent}\n\n";
fixedData.m_ulPrevSibling = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPrevSibling: {fixedData.m_ulPrevSibling}\n\n";
fixedData.m_ulNextSibling = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulNextSibling: {fixedData.m_ulNextSibling}\n\n";
fixedData.m_ulFirstChild = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulFirstChild: {fixedData.m_ulFirstChild}\n\n";
// Library tasks
fixedData.m_bIsLibraryTask = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bIsLibraryTask: {fixedData.m_bIsLibraryTask}\n\n";
fixedData.m_fLibraryTasksProbability = AAssit.ReadFromBinaryOf<float>(fp, ref readBytes);
logContent += $"m_fLibraryTasksProbability: {fixedData.m_fLibraryTasksProbability}\n\n";
fixedData.m_bIsUniqueStorageTask = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bIsUniqueStorageTask: {fixedData.m_bIsUniqueStorageTask}\n\n";
fixedData.m_iWorldContribution = AAssit.ReadFromBinaryOf<int>(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(FileStream 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<ushort>(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<task_tm>(fp, ref readBytes);
fixedData.m_tmEnd[i] = AAssit.ReadFromBinaryOf<task_tm>(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<m_ulChangeKeyCnt; i++)
{
fread(&m_plChangeKey[i], sizeof(long), 1, fp);
fread(&m_plChangeKeyValue[i], sizeof(long), 1, fp);
fread(&m_pbChangeType[i], sizeof(bool), 1, fp);
}*/
if (fixedData.m_ulChangeKeyCnt > 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<int>(fp, ref readBytes);
fixedData.m_plChangeKeyValue[i] = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
fixedData.m_pbChangeType[i] = AAssit.ReadFromBinaryOf<byte>(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<m_ulPQExpCnt; i++)
{
fread(m_pszPQExp[i], 1, TASK_AWARD_MAX_DISPLAY_CHAR_LEN, fp);
fread(m_pPQExpArr[i], sizeof(TASK_EXPRESSION), TASK_AWARD_MAX_DISPLAY_CHAR_LEN, fp);
}
}*/
if (fixedData.m_ulPQExpCnt > 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<byte>(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<TASK_EXPRESSION>(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<MONSTERS_CONTRIB>(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<Task_Region>(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<Task_Region>(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<Task_Region>(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<ITEM_WANTED>(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<ITEM_WANTED>(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<TEAM_MEM_WANTED>(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<int>(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<MONSTER_WANTED>(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<PLAYER_WANTED>(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<ITEM_WANTED>(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<byte>(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<TASK_EXPRESSION>(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<ushort>(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<Task_Region>(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<Task_Region>(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(FileStream 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<uint>(fp, ref readBytes);
// fread(&ad.m_ulItemId, sizeof(ad.m_ulItemId), 1, fp);
ad.m_ulItemId = AAssit.ReadFromBinaryOf<uint>(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<uint>(fp, ref readBytes);
for (int i=0; i < TaskTemplConstants.MAX_AWARD_SCALES; i++)
{
ad.m_Counts[i] = AAssit.ReadFromBinaryOf<uint>(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(FileStream 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<uint>(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<float>(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(FileStream fp, ref AWARD_DATA ad, uint ulVersion, ref long readBytes)
{
string logContent = "";
// Inline scalars
ad.m_ulGoldNum = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulGoldNum: {ad.m_ulGoldNum} \n";
ad.m_ulExp = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulExp: {ad.m_ulExp} \n";
ad.m_ulRealmExp = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 境界经验 // Realm experience
logContent += $"m_ulRealmExp: {ad.m_ulRealmExp} \n";
ad.m_bExpandRealmLevelMax = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0; // 境界等级10整级时提升境界等级上限 // Increase realm level upper limit
logContent += $"m_bExpandRealmLevelMax: {ad.m_bExpandRealmLevelMax} \n";
ad.m_ulNewTask = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulNewTask: {ad.m_ulNewTask} \n";
ad.m_ulSP = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulSP: {ad.m_ulSP} \n";
ad.m_lReputation = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_lReputation: {ad.m_lReputation} \n";
ad.m_ulNewPeriod = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulNewPeriod: {ad.m_ulNewPeriod} \n";
ad.m_ulNewRelayStation = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulNewRelayStation: {ad.m_ulNewRelayStation} \n";
ad.m_ulStorehouseSize = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulStorehouseSize: {ad.m_ulStorehouseSize} \n";
ad.m_ulStorehouseSize2 = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulStorehouseSize2: {ad.m_ulStorehouseSize2} \n";
ad.m_ulStorehouseSize3 = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulStorehouseSize3: {ad.m_ulStorehouseSize3} \n";
ad.m_ulStorehouseSize4 = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 账号仓库 // Account warehouse
logContent += $"m_ulStorehouseSize4: {ad.m_ulStorehouseSize4} \n";
ad.m_lInventorySize = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_lInventorySize: {ad.m_lInventorySize} \n";
ad.m_ulPetInventorySize = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPetInventorySize: {ad.m_ulPetInventorySize} \n";
ad.m_ulFuryULimit = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulFuryULimit: {ad.m_ulFuryULimit} \n";
ad.m_ulTransWldId = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulTransWldId: {ad.m_ulTransWldId} \n";
ad.m_TransPt = AAssit.ReadFromBinaryOf<ZONE_VERT>(fp, ref readBytes);
logContent += $"m_TransPt: ({ad.m_TransPt.x}, {ad.m_TransPt.y}, {ad.m_TransPt.z}) \n";
ad.m_lMonsCtrl = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_lMonsCtrl: {ad.m_lMonsCtrl} \n";
ad.m_bTrigCtrl = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bTrigCtrl: {ad.m_bTrigCtrl} \n";
ad.m_bUseLevCo = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bUseLevCo: {ad.m_bUseLevCo} \n";
ad.m_bDivorce = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bDivorce: {ad.m_bDivorce} \n";
ad.m_bSendMsg = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bSendMsg: {ad.m_bSendMsg} \n";
ad.m_nMsgChannel = AAssit.ReadFromBinaryOf<int>(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<uint>(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<uint>(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<byte>(fp, ref readBytes) > 0;
logContent += $"m_bAwardDeath: {ad.m_bAwardDeath} \n";
ad.m_bAwardDeathWithLoss = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bAwardDeathWithLoss: {ad.m_bAwardDeathWithLoss} \n";
ad.m_ulDividend = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 鸿利值 // Dividend value
logContent += $"m_ulDividend: {ad.m_ulDividend} \n";
ad.m_bAwardSkill = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0; // 是否奖励技能 // Whether to reward skill
logContent += $"m_bAwardSkill: {ad.m_bAwardSkill} \n";
ad.m_iAwardSkillID = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes); // 技能ID // Skill ID
logContent += $"m_iAwardSkillID: {ad.m_iAwardSkillID} \n";
ad.m_iAwardSkillLevel = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes); // 技能等级 // Skill level
logContent += $"m_iAwardSkillLevel: {ad.m_iAwardSkillLevel} \n";
// PQ task reward
ad.m_ulSpecifyContribTaskID = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 指定任务贡献度的任务id // Task ID for specified contribution
logContent += $"m_ulSpecifyContribTaskID: {ad.m_ulSpecifyContribTaskID} \n";
ad.m_ulSpecifyContribSubTaskID = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 指定任务贡献度的子任务ID // Subtask ID for specified contribution
logContent += $"m_ulSpecifyContribSubTaskID: {ad.m_ulSpecifyContribSubTaskID} \n";
ad.m_ulSpecifyContrib = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 指定任务贡献度 // Specified task contribution
logContent += $"m_ulSpecifyContrib: {ad.m_ulSpecifyContrib} \n";
ad.m_ulContrib = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 贡献度 // Contribution
logContent += $"m_ulContrib: {ad.m_ulContrib} \n";
ad.m_ulRandContrib = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 随机贡献度 // Random contribution
logContent += $"m_ulRandContrib: {ad.m_ulRandContrib} \n";
ad.m_ulLowestcontrib = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 最低贡献度 // Minimum contribution
logContent += $"m_ulLowestcontrib: {ad.m_ulLowestcontrib} \n";
ad.m_iFactionContrib = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes); // 帮派贡献度 // Faction contribution
logContent += $"m_iFactionContrib: {ad.m_iFactionContrib} \n";
ad.m_iFactionExpContrib = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iFactionExpContrib: {ad.m_iFactionExpContrib} \n";
ad.m_ulPQRankingAwardCnt = AAssit.ReadFromBinaryOf<uint>(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<uint>(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<uint>(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<byte>(fp, ref readBytes) > 0;
logContent += $"m_bMulti: {ad.m_bMulti} \n";
ad.m_nNumType = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_nNumType: {ad.m_nNumType} \n";
ad.m_lNum = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_lNum: {ad.m_lNum} \n";
// Display global key/value
ad.m_ulDisplayKeyCnt = AAssit.ReadFromBinaryOf<uint>(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<uint>(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<uint>(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<int>(fp, ref readBytes);
logContent += $"m_iForceContribution: {ad.m_iForceContribution} \n";
ad.m_iForceReputation = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iForceReputation: {ad.m_iForceReputation} \n";
ad.m_iForceActivity = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iForceActivity: {ad.m_iForceActivity} \n";
ad.m_iForceSetRepu = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iForceSetRepu: {ad.m_iForceSetRepu} \n";
ad.m_iTaskLimit = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iTaskLimit: {ad.m_iTaskLimit} \n";
ad.m_ulTitleNum = AAssit.ReadFromBinaryOf<uint>(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<int>(fp, ref readBytes);
logContent += $"m_iLeaderShip: {ad.m_iLeaderShip} \n";
ad.m_iWorldContribution = AAssit.ReadFromBinaryOf<int>(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<TITLE_AWARD>(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<int>(fp, (int)ad.m_ulChangeKeyCnt,ref readBytes);
ad.m_plChangeKeyValue = AAssit.ReadArrayFromBinary<int>(fp, (int)ad.m_ulChangeKeyCnt,ref readBytes);
ad.m_pbChangeType = AAssit.ReadArrayFromBinary<bool>(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<int>(fp, (int)ad.m_ulHistoryChangeCnt, ref readBytes);
//fread(&ad.m_plHistoryChangeKeyValue[i], sizeof(long), 1, fp);
ad.m_plHistoryChangeKeyValue = AAssit.ReadArrayFromBinary<int>(fp, (int)ad.m_ulHistoryChangeCnt, ref readBytes);
//fread(&ad.m_pbHistoryChangeType[i], sizeof(bool), 1, fp);
ad.m_pbHistoryChangeType = AAssit.ReadArrayFromBinary<bool>(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<int>(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<byte>(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<TASK_EXPRESSION>(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<ushort>(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(FileStream 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<bool>(fp, ref readBytes);
ic.m_bRandChoose = AAssit.ReadFromBinaryOf<bool>(fp, ref readBytes);
pointerLog += $" After Read AWARD_ITEMS_CAND.m_bRandChoose : {fp.Position}\n";
ic.m_ulAwardItems = AAssit.ReadFromBinaryOf<uint>(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<ITEM_WANTED>(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(FileStream 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<bool>(fp, ref readBytes);
ms.m_ulSummonRadius = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
ms.m_bDeathDisappear = AAssit.ReadFromBinaryOf<bool>(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<MONSTERS_SUMMONED>(fp, (int)ms.m_ulMonsterNum, ref readBytes);
return true;
}
private bool LoadAwardPQRankingBin(FileStream 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<bool>(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<RANKING_AWARD>(fp, (int)pr.m_ulRankingAwardNum, ref readBytes);
return true;
}
#endregion
// 加载任务描述与确认/拒绝文本 // Load task description and OK/No texts
private bool LoadDescriptionBin(FileStream 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<uint>(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<ushort>(fp, (int)len, ref readBytes);
// System.Buffer.BlockCopy(tmp, 0, m_pwstrDescript, 0, (int)len * 2);
m_pwstrDescript = AAssit.ReadArrayFromBinary<ushort>(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<uint>(fp, ref readBytes);
m_pwstrOkText = new ushort[len + 1];
m_pwstrOkText[len] = 0;
if (len > 0)
{
// ushort[] tmp = AAssit.ReadArrayFromBinary<ushort>(fp, (int)len, ref readBytes);
// System.Buffer.BlockCopy(tmp, 0, m_pwstrOkText, 0, (int)len * 2);
m_pwstrOkText = AAssit.ReadArrayFromBinary<ushort>(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<uint>(fp, ref readBytes);
m_pwstrNoText = new ushort[len + 1];
m_pwstrNoText[len] = 0;
if (len > 0)
{
// ushort[] tmp = AAssit.ReadArrayFromBinary<ushort>(fp, (int)len, ref readBytes);
// System.Buffer.BlockCopy(tmp, 0, m_pwstrNoText, 0, (int)len * 2);
m_pwstrNoText = AAssit.ReadArrayFromBinary<ushort>(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(FileStream fp)
{
long readBytes = 0;
// size_t len;
// len = 0;
// fread(&len, sizeof(len), 1, fp);
uint len = AAssit.ReadFromBinaryOf<uint>(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<ushort>(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<uint>(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<task_tm>(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes);
// fixedData.m_tmEnd = AAssit.ReadArrayFromBinary<task_tm>(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<uint>(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<uint>(fp, ref readBytes);
// fixedData.m_szName = AAssit.ReadArrayFromBinary<ushort>(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<bool>(fp, ref readBytes);
// ATaskTemplFixedData fixedData = AAssit.ReadFromBinaryOf<ATaskTemplFixedData>(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; i<m_ulChangeKeyCnt; i++)
// {
// fread(&m_plChangeKey[i], sizeof(long), 1, fp);
// fread(&m_plChangeKeyValue[i], sizeof(long), 1, fp);
// fread(&m_pbChangeType[i], sizeof(bool), 1, fp);
// }
// 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<m_ulPQExpCnt; i++)
// {
// fread(m_pszPQExp[i], 1, TASK_AWARD_MAX_DISPLAY_CHAR_LEN, fp);
// fread(m_pPQExpArr[i], sizeof(TASK_EXPRESSION), TASK_AWARD_MAX_DISPLAY_CHAR_LEN, fp);
// }
// }
// if (m_ulMonsterContribCnt)
// {
// m_MonstersContrib = new MONSTERS_CONTRIB[m_ulMonsterContribCnt];
// g_ulNewCount++;
// }
// for (i = 0; i < m_ulMonsterContribCnt; i++)
// {
// MONSTERS_CONTRIB& mc = m_MonstersContrib[i];
// fread(&mc, sizeof(mc), 1, fp);
// }
// // version 80
// if (m_ulDelvRegionCnt>0)
// {
// m_pDelvRegion = new Task_Region[m_ulDelvRegionCnt];
// g_ulNewCount++;
// }
// else m_pDelvRegion = NULL;
// for (i=0;i<m_ulDelvRegionCnt;i++)
// {
// Task_Region& t = m_pDelvRegion[i];
// fread(&t,sizeof(Task_Region),1,fp);
// }
// if (m_ulEnterRegionCnt>0)
// {
// m_pEnterRegion = new Task_Region[m_ulEnterRegionCnt];
// g_ulNewCount++;
// }
// else m_pEnterRegion = NULL;
// for (i=0;i<m_ulEnterRegionCnt;i++)
// {
// Task_Region& t = m_pEnterRegion[i];
// fread(&t,sizeof(Task_Region),1,fp);
// }
// if (m_ulLeaveRegionCnt>0)
// {
// m_pLeaveRegion = new Task_Region[m_ulLeaveRegionCnt];
// g_ulNewCount++;
// }
// else m_pLeaveRegion = NULL;
// for (i=0;i<m_ulLeaveRegionCnt;i++)
// {
// Task_Region& t = m_pLeaveRegion[i];
// fread(&t,sizeof(Task_Region),1,fp);
// }
// // ÈÎÎñ¿ªÆôÌõ¼þ¼°·½Ê½
// if (m_ulPremItems)
// {
// m_PremItems = new ITEM_WANTED[m_ulPremItems];
// g_ulNewCount++;
// }
// for (i = 0; i < m_ulPremItems; i++)
// {
// ITEM_WANTED& iw = m_PremItems[i];
// fread(&iw, sizeof(iw), 1, fp);
// }
// m_ulGivenCmnCount = 0;
// m_ulGivenTskCount = 0;
// if (m_ulGivenItems)
// {
// m_GivenItems = new ITEM_WANTED[m_ulGivenItems];
// g_ulNewCount++;
// }
// for (i = 0; i < m_ulGivenItems; i++)
// {
// ITEM_WANTED& iw = m_GivenItems[i];
// fread(&iw, sizeof(iw), 1, fp);
// if (iw.m_bCommonItem) m_ulGivenCmnCount++;
// else m_ulGivenTskCount++;
// }
// if (m_bTeamwork)
// {
// if (m_ulTeamMemsWanted)
// {
// m_TeamMemsWanted = new TEAM_MEM_WANTED[m_ulTeamMemsWanted];
// g_ulNewCount++;
// }
// for (i = 0; i < m_ulTeamMemsWanted; i++)
// {
// TEAM_MEM_WANTED& tmw = m_TeamMemsWanted[i];
// fread(&tmw, sizeof(tmw), 1, fp);
// }
// }
// if (m_iPremTitleNumTotal)
// {
// m_PremTitles = new int[m_iPremTitleNumTotal];
// g_ulNewCount++;
// for (i = 0; i < m_iPremTitleNumTotal; i++)
// {
// fread(&m_PremTitles[i], sizeof(int), 1, fp);
// }
// }
// /* ÈÎÎñÍê³ÉµÄ·½Ê½¼°Ìõ¼þ */
// if (m_ulMonsterWanted)
// {
// m_MonsterWanted = new MONSTER_WANTED[m_ulMonsterWanted];
// g_ulNewCount++;
// }
// for (i = 0; i < m_ulMonsterWanted; i++)
// {
// MONSTER_WANTED& mw = m_MonsterWanted[i];
// fread(&mw, sizeof(mw), 1, fp);
// }
// if (m_ulPlayerWanted)
// {
// m_PlayerWanted = new PLAYER_WANTED[m_ulPlayerWanted];
// g_ulNewCount++;
// }
// for (i = 0; i < m_ulPlayerWanted; ++i)
// {
// PLAYER_WANTED& pw = m_PlayerWanted[i];
// fread(&pw, sizeof(pw), 1, fp);
// }
// if (m_ulItemsWanted)
// {
// m_ItemsWanted = new ITEM_WANTED[m_ulItemsWanted];
// g_ulNewCount++;
// }
// for (i = 0; i < m_ulItemsWanted; i++)
// {
// ITEM_WANTED& iw = m_ItemsWanted[i];
// fread(&iw, sizeof(iw), 1, fp);
// }
// if (m_ulExpCnt)
// {
// m_pszExp = new char[m_ulExpCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN];
// memset(m_pszExp, 0, m_ulExpCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN);
// m_pExpArr = new TASK_EXPRESSION[m_ulExpCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN];
// memset(m_pExpArr, 0, sizeof(TASK_EXPRESSION)*m_ulExpCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN);
// for (i=0; i<m_ulExpCnt; i++)
// {
// fread(m_pszExp[i], 1, TASK_AWARD_MAX_DISPLAY_CHAR_LEN, fp);
// fread(m_pExpArr[i], sizeof(TASK_EXPRESSION), TASK_AWARD_MAX_DISPLAY_CHAR_LEN, fp);
// }
// }
// if (m_ulTaskCharCnt)
// {
// m_pTaskChar = new task_char[m_ulTaskCharCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN];
// memset(m_pTaskChar, 0, sizeof(task_char)*m_ulTaskCharCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN);
// for (i=0; i<m_ulTaskCharCnt; i++)
// {
// fread(m_pTaskChar[i], sizeof(task_char), TASK_AWARD_MAX_DISPLAY_CHAR_LEN, fp);
// }
// }
// // version 80
// if (m_ulReachSiteCnt>0)
// {
// m_pReachSite = new Task_Region[m_ulReachSiteCnt];
// g_ulNewCount++;
// }
// else m_pReachSite = NULL;
// for (i=0;i<m_ulReachSiteCnt;i++)
// {
// Task_Region& t = m_pReachSite[i];
// fread(&t,sizeof(Task_Region),1,fp);
// }
// if (m_ulLeaveSiteCnt>0)
// {
// m_pLeaveSite = new Task_Region[m_ulLeaveSiteCnt];
// g_ulNewCount++;
// }
// else m_pLeaveSite = NULL;
// for (i=0;i<m_ulLeaveSiteCnt;i++)
// {
// Task_Region& t = m_pLeaveSite[i];
// fread(&t,sizeof(Task_Region),1,fp);
// }
// LoadAwardDataBin(fp, *m_Award_S, _task_templ_cur_version);
// LoadAwardDataBin(fp, *m_Award_F, _task_templ_cur_version);
// LoadAwardDataRatioScale(fp, *m_AwByRatio_S, _task_templ_cur_version);
// LoadAwardDataRatioScale(fp, *m_AwByRatio_F, _task_templ_cur_version);
// LoadAwardDataItemsScale(fp, *m_AwByItems_S, _task_templ_cur_version);
// LoadAwardDataItemsScale(fp, *m_AwByItems_F, _task_templ_cur_version);
#endregion
public void IncValidCount() { m_uValidCount++; }
// 转换对话文本 // Convert talk text
private void convert_talk_text(ref talk_proc talk, char code)
{
// talk.text is task_char[64] => 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_ulAwardType_S : 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_ulScales; i++)
{
if (ratio <= p.m_Ratios[i])
{
pAward = p.m_Awards[i];
return;
}
}
}
public void CalcAwardDataByItems(
TaskInterface pTask,
ref AWARD_DATA pAward,
ActiveTaskEntry pEntry)
{
AWARD_ITEMS_SCALE p = (pEntry.IsSuccess() ? m_AwByItems_S : m_AwByItems_F);
uint ulCount = (uint)pTask.GetTaskItemCount(p.m_ulItemId), i;
for (i = 0; i < p.m_ulScales; i++)
{
if (ulCount >= 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<uint>(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<byte>(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<MONSTER_WANTED>());
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<MONSTER_WANTED>(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<byte>(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<ITEM_WANTED>());
// 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<ITEM_WANTED>(data, ref p);
}
}
m_FixedData.m_ulGoldWanted = GPDataTypeHelper.FromBytes<uint>(data, ref p);
m_FixedData.m_iFactionContribWanted = GPDataTypeHelper.FromBytes<int>(data, ref p);
m_FixedData.m_iFactionExpContribWanted = GPDataTypeHelper.FromBytes<int>(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<int>( 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<ushort>(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<uint>( data, ref p);
opt.param = GPDataTypeHelper.FromBytes<uint>(data, ref p);
uint sz = GPDataTypeHelper.FromBytes<uint>(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<ushort>(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<byte>(data, ref p);
win.id_parent = GPDataTypeHelper.FromBytes<byte>(data, ref p);
win.talk_text_len = GPDataTypeHelper.FromBytes<int>(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<ushort>(data, ref p);
}
g_ulNewCount++;
}
win.num_option = GPDataTypeHelper.FromBytes<byte>( 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<int>(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<ushort>(data, ref p);
}
}
talk.num_window = GPDataTypeHelper.FromBytes<byte>(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<uint>(pData, ref p);
token_mask2 = GPDataTypeHelper.FromBytes<uint>(pData, ref p);
int token_count = 0;
// dyn type
m_FixedData.m_DynTaskType = GPDataTypeHelper.FromBytes<byte>(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<uint>(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<ushort>(pData, ref p);
}
// choose one
m_FixedData.m_bChooseOne = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// rand one
m_FixedData.m_bRandOne = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// in order
m_FixedData.m_bExeChildInOrder = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// parent fail
m_FixedData.m_bParentAlsoFail = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// parent succ
m_FixedData.m_bParentAlsoSucc = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// give up
m_FixedData.m_bCanGiveUp = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// redo
m_FixedData.m_bCanRedo = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// redo after fail
m_FixedData.m_bCanRedoAfterFailure = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// clear as give up
m_FixedData.m_bClearAsGiveUp = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// record
m_FixedData.m_bNeedRecord = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// die
m_FixedData.m_bFailAsPlayerDie = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// auto deliver
m_FixedData.m_bAutoDeliver = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// death trig
m_FixedData.m_bDeathTrig = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// clear acquired
m_FixedData.m_bClearAcquired = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// spouse
m_FixedData.m_bPremise_Spouse = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// teamwork
m_FixedData.m_bTeamwork = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// direction
m_FixedData.m_bShowDirection = GPDataTypeHelper.FromBytes<byte>(pData, ref p) != 0;
// level
m_FixedData.m_ulPremise_Lev_Min = GPDataTypeHelper.FromBytes<byte>(pData, ref p);
m_FixedData.m_ulPremise_Lev_Max = GPDataTypeHelper.FromBytes<byte>(pData, ref p);
// 0: time limit
if (((1 << token_count++) & token_mask1) != 0)
{
m_FixedData.m_ulTimeLimit = GPDataTypeHelper.FromBytes<uint>(pData, ref p);
}
// 1: reputation
if (((1 << token_count++) & token_mask1) != 0)
{
m_FixedData.m_lPremise_Reputation = GPDataTypeHelper.FromBytes<uint>(pData, ref p);
}
// 2: period
if (((1 << token_count++) & token_mask1) != 0)
{
m_FixedData.m_ulPremise_Period = GPDataTypeHelper.FromBytes<ushort>(pData, ref p);
}
// 3: prem items
if (((1 << token_count++) & token_mask1) != 0)
{
m_FixedData.m_ulPremItems = GPDataTypeHelper.FromBytes<byte>(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<ITEM_WANTED>());
// 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<byte>(pData, ref p) != 0;
m_FixedData.m_ulDelvWorld = GPDataTypeHelper.FromBytes<uint>(pData, ref p);
m_FixedData.m_ulDelvRegionCnt = GPDataTypeHelper.FromBytes<uint>(pData, ref p);
for (int i=0; i< m_FixedData.m_ulDelvRegionCnt; i++)
{
m_FixedData.m_pDelvRegion[i] = GPDataTypeHelper.FromBytes<Task_Region>(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<byte>(pData, ref p) != 0;
m_FixedData.m_ulTransWldId = GPDataTypeHelper.FromBytes<uint>(pData, ref p);
m_FixedData.m_TransPt = GPDataTypeHelper.FromBytes<ZONE_VERT>(pData, ref p);
}
// 6: given items
if (((1 << token_count++) & token_mask1) != 0)
{
m_FixedData.m_ulGivenItems =GPDataTypeHelper.FromBytes<byte>(pData, ref p);
m_FixedData.m_ulGivenCmnCount = GPDataTypeHelper.FromBytes<byte>(pData, ref p);
m_FixedData.m_ulGivenTskCount = GPDataTypeHelper.FromBytes<byte>(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<ITEM_WANTED>());
// 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<uint>(pData, ref p);
}
// 8: pre task
if (((1 << token_count++) & token_mask1) != 0)
{
m_FixedData.m_ulPremise_Task_Count = GPDataTypeHelper.FromBytes<byte>(pData, ref p);
m_FixedData.m_ulPremise_Task_Least_Num = GPDataTypeHelper.FromBytes<byte>(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<uint>(pData, ref p);
}
}
// 9: gender
if (((1 << token_count++) & token_mask1) != 0)
{
m_FixedData.m_ulGender = GPDataTypeHelper.FromBytes<byte>(pData, ref p);
}
// 10: occupation
if (((1 << token_count++) & token_mask1) != 0)
{
m_FixedData.m_ulOccupations = GPDataTypeHelper.FromBytes<byte>(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<uint>(pData, ref p);
}
}
// 11: mutex task
if (((1 << token_count++) & token_mask1) != 0)
{
m_FixedData.m_ulMutexTaskCount = GPDataTypeHelper.FromBytes<byte>(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<uint>(pData, ref p);
}
}
// 12: time table
if (((1 << token_count++) & token_mask1) != 0)
{
m_FixedData.m_ulTimetable = GPDataTypeHelper.FromBytes<byte>(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<task_tm>() * 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<task_tm>(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<task_tm>(pData, ref p);
}
}
// method
m_FixedData.m_enumMethod = GPDataTypeHelper.FromBytes<byte>(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<uint>(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<Task_Region>(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<uint>(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<Task_Region>(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<ZONE_VERT>();
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<uint>(pData, ref p);
break;
}
// finish type
m_FixedData.m_enumFinishType = GPDataTypeHelper.FromBytes<byte>(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<int>( 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;
}
}
}