Files
test/Assets/Scripts/Task/TaskTempl.cs
T
2025-10-23 11:02:58 +07:00

3037 lines
112 KiB
C#

using UnityEngine;
using System.IO;
using System.Runtime.InteropServices;
using System;
using BrewMonster;
using ModelRenderer.Scripts.Common;
namespace PerfectWorld.Scripts.Task
{
public class TaskTemplConstants
{
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];
}
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;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ZONE_VERT
{
public float x;
public float y;
public float z;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct PLAYER_WANTED
{
public uint m_ulTemplID; // Player Template ID
public uint m_ulCount; // Count
public uint m_ulLevel; // Level
}
[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
public bool m_bDropCmnItem; // Is common item drop
public float m_fDropProb; // Drop probability
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);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ITEM_WANTED
{
public uint m_ulItemTemplId;
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);
}
}
[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;
}
[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);
}
}
[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);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RANKING_AWARD
{
public uint m_iRankingStart;
public uint m_iRankingEnd;
public bool m_bCommonItem;
public ulong m_ulAwardItemId;
public ulong m_ulAwardItemNum;
public long 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);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AWARD_MONSTERS_SUMMONED
{
public uint m_ulMonsterNum;
public bool m_bRandChoose;
public uint m_ulSummonRadius;
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();
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AWARD_PQ_RANKING
{
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;
}
}
}
[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;
}
// 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;
public bool m_bMale;
}
// Race-occupation mapping array
public static class TaskTemplMapping
{
public static readonly uint[] _race_occ_map = new uint[TaskTemplConstants.MAX_OCCUPATIONS];
}
[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();
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AWARD_ITEMS_CAND
{
public uint m_ulAwardItems;
public uint m_ulAwardCmnItems;
public uint m_ulAwardTskItems;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.MAX_ITEM_AWARD)]
public ITEM_WANTED[] m_AwardItems;
public bool m_bRandChoose;
public int MarshalBasicData(byte[] pData)
{
int offset = 0;
pData[offset] = m_bRandChoose ? (byte)1 : (byte)0;
offset++;
pData[offset] = (byte)m_ulAwardItems;
offset++;
int sz = Marshal.SizeOf(typeof(ITEM_WANTED)) * (int)m_ulAwardItems;
if (sz > 0)
{
// Copy ITEM_WANTED array data
for (int i = 0; i < m_ulAwardItems; i++)
{
// Would need to implement proper marshaling here
// For now, just increase offset by appropriate size
offset += Marshal.SizeOf(typeof(ITEM_WANTED));
}
}
return offset;
}
public int UnmarshalBasicData(byte[] pData)
{
int offset = 0;
m_bRandChoose = pData[offset] != 0;
offset++;
m_ulAwardItems = pData[offset];
offset++;
if (m_ulAwardItems > 0)
{
m_AwardItems = new ITEM_WANTED[m_ulAwardItems];
// Copy ITEM_WANTED array data
for (uint i = 0; i < m_ulAwardItems; i++)
{
// Would need to implement proper unmarshaling here
// For now, just increase offset by appropriate size
offset += Marshal.SizeOf(typeof(ITEM_WANTED));
if (m_AwardItems[i].m_bCommonItem)
m_ulAwardCmnItems++;
else
m_ulAwardTskItems++;
}
}
return offset;
}
public static bool operator ==(AWARD_ITEMS_CAND a, AWARD_ITEMS_CAND b)
{
if (a.m_ulAwardItems != b.m_ulAwardItems)
return false;
for (uint i = 0; i < a.m_ulAwardItems; ++i)
{
if (!(a.m_AwardItems[i].Equals(b.m_AwardItems[i])))
return false;
}
return (a.m_ulAwardCmnItems == b.m_ulAwardCmnItems &&
a.m_ulAwardTskItems == b.m_ulAwardTskItems &&
a.m_bRandChoose == b.m_bRandChoose);
}
public static bool operator !=(AWARD_ITEMS_CAND a, AWARD_ITEMS_CAND b)
{
return !(a == b);
}
public override bool Equals(object obj)
{
if (obj is AWARD_ITEMS_CAND)
return this == (AWARD_ITEMS_CAND)obj;
return false;
}
public override int GetHashCode()
{
return m_ulAwardItems.GetHashCode() ^
m_ulAwardCmnItems.GetHashCode() ^
m_ulAwardTskItems.GetHashCode() ^
m_bRandChoose.GetHashCode();
}
}
[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;
}
}
[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;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AWARD_DATA
{
/*/
public AWARD_DATA(bool initialize = true)
{
m_ulGoldNum = 0;
m_ulExp = 0;
m_ulRealmExp = 0;
m_bExpandRealmLevelMax = false;
m_ulNewTask = 0;
m_ulSP = 0;
m_lReputation = 0;
m_ulNewPeriod = 0;
m_ulNewRelayStation = 0;
m_ulStorehouseSize = 0;
m_ulStorehouseSize2 = 0;
m_ulStorehouseSize3 = 0;
m_ulStorehouseSize4 = 0;
m_lInventorySize = 0;
m_ulPetInventorySize = 0;
m_ulFuryULimit = 0;
m_ulTransWldId = 0;
m_TransPt = new ZONE_VERT();
m_lMonsCtrl = 0;
m_bTrigCtrl = false;
m_bUseLevCo = false;
m_bDivorce = false;
m_bSendMsg = false;
m_nMsgChannel = 0;
m_ulCandItems = 0;
m_CandItems = null;
m_ulSummonedMonsters = 0;
m_SummonedMonsters = new AWARD_MONSTERS_SUMMONED();
m_bAwardDeath = false;
m_bAwardDeathWithLoss = false;
m_ulDividend = 0;
m_bAwardSkill = false;
m_iAwardSkillID = 0;
m_iAwardSkillLevel = 0;
m_ulSpecifyContribTaskID = 0;
m_ulSpecifyContribSubTaskID = 0;
m_ulSpecifyContrib = 0;
m_ulContrib = 0;
m_ulRandContrib = 0;
m_ulLowestcontrib = 0;
m_iFactionContrib = 0;
m_iFactionExpContrib = 0;
m_ulPQRankingAwardCnt = 0;
m_PQRankingAward = new AWARD_PQ_RANKING();
m_bMulti = false;
m_nNumType = 0;
m_lNum = 0;
m_ulChangeKeyCnt = 0;
m_plChangeKey = null;
m_plChangeKeyValue = null;
m_pbChangeType = null;
m_ulHistoryChangeCnt = 0;
m_plHistoryChangeKey = null;
m_plHistoryChangeKeyValue = null;
m_pbHistoryChangeType = null;
m_ulDisplayKeyCnt = 0;
m_plDisplayKey = null;
m_ulExpCnt = 0;
m_pszExp = null;
m_pExpArr = null;
m_ulTaskCharCnt = 0;
m_pTaskChar = null;
m_iForceContribution = 0;
m_iForceReputation = 0;
m_iForceActivity = 0;
m_iForceSetRepu = 0;
m_iTaskLimit = 0;
m_ulTitleNum = 0;
m_pTitleAward = null;
m_iLeaderShip = 0;
m_iWorldContribution = 0;
#if TASK_TEMPL_EDITOR
m_CandItems = new AWARD_ITEMS_CAND[TaskTemplConstants.MAX_AWARD_CANDIDATES];
m_SummonedMonsters = new AWARD_MONSTERS_SUMMONED();
m_PQRankingAward = new AWARD_PQ_RANKING();
m_pTitleAward = new TITLE_AWARD[TaskTemplConstants.MAX_TITLE_NUM];
#endif
}
//*/
public uint m_ulGoldNum;
public uint m_ulExp;
public uint m_ulRealmExp; // 境界经验 // Realm experience
public bool m_bExpandRealmLevelMax; // 境界等级10整级时提升境界等级上限 // Increase realm level upper limit when realm level is at level 10
public uint m_ulNewTask;
public uint m_ulSP;
public int m_lReputation;
public uint m_ulNewPeriod;
public uint m_ulNewRelayStation;
public uint m_ulStorehouseSize;
public uint m_ulStorehouseSize2;
public uint m_ulStorehouseSize3;
public uint m_ulStorehouseSize4; // 账号仓库 // Account warehouse
public int m_lInventorySize;
public uint m_ulPetInventorySize;
public uint m_ulFuryULimit;
public uint m_ulTransWldId;
public ZONE_VERT m_TransPt;
public int m_lMonsCtrl;
public bool m_bTrigCtrl;
public bool m_bUseLevCo;
public bool m_bDivorce;
public bool m_bSendMsg;
public int m_nMsgChannel;
public uint m_ulCandItems;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
public AWARD_ITEMS_CAND[] m_CandItems; //[MAX_AWARD_CANDIDATES];
public uint m_CandItems_ptr;
public uint m_ulSummonedMonsters;
[MarshalAs(UnmanagedType.SysInt)]
public AWARD_MONSTERS_SUMMONED m_SummonedMonsters;
public bool m_bAwardDeath;
public bool m_bAwardDeathWithLoss;
public uint m_ulDividend; // 鸿利值 // Dividend value
public bool m_bAwardSkill; // 是否奖励技能 // Whether to reward skill [Yongdong, 2010-1-6]
public int m_iAwardSkillID; // 技能ID // Skill ID
public int m_iAwardSkillLevel;// 技能等级 // Skill level
//////////////////////////////////////////////////// PQ任务奖励 start // PQ task reward start
public uint m_ulSpecifyContribTaskID; // 指定任务贡献度的任务id // Task ID for specified contribution
public uint m_ulSpecifyContribSubTaskID; // 指定任务贡献度的子任务ID // Subtask ID for specified contribution
public uint m_ulSpecifyContrib; // 指定任务贡献度 // Specified task contribution
// 仅PQ子任务专用 // Only for PQ subtasks
public uint m_ulContrib; // 贡献度 // Contribution
public uint m_ulRandContrib; // 随机贡献度 // Random contribution
public uint m_ulLowestcontrib; // 最低贡献度 // Minimum contribution
// 帮派贡献度 // Faction contribution
public int m_iFactionContrib;
public int m_iFactionExpContrib;
public uint m_ulPQRankingAwardCnt;
[MarshalAs(UnmanagedType.SysInt)]
public AWARD_PQ_RANKING m_PQRankingAward;
//////////////////////////////////////////////////// PQ任务奖励 end // PQ task reward end
// 改变全局key/value // Change global key/value
public uint m_ulChangeKeyCnt;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.TASK_AWARD_MAX_CHANGE_VALUE)]
[NonSerialized]
public int[] m_plChangeKey;
public uint m_plChangeKey_ptr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
// [NonSerialized]
public int[] m_plChangeKeyValue;
public uint m_plChangeKeyValue_ptr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
// [NonSerialized]
public bool[] m_pbChangeType;
public uint m_pbChangeType_ptr;
// 修改历史进度 // Modify historical progress
public uint m_ulHistoryChangeCnt;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public int[] m_plHistoryChangeKey;
public uint m_plHistoryChangeKey_ptr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public int[] m_plHistoryChangeKeyValue;
public uint m_plHistoryChangeKeyValue_ptr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public bool[] m_pbHistoryChangeType;
public uint m_pbHistoryChangeType_ptr;
// 倍率 // Multiplier
public bool m_bMulti;
public int m_nNumType;
public int m_lNum;
// 显示全局key/value // Display global key/value
public uint m_ulDisplayKeyCnt;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public int[] m_plDisplayKey;
public uint m_plDisplayKey_ptr;
// 显示全局变量表达式 // Display global variable expressions
public uint m_ulExpCnt;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public byte[] m_pszExp;
public byte m_pszExp_ptr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
public TASK_EXPRESSION[] m_pExpArr;
public uint m_pExpArr_ptr;
// 显示全局变量表达式提示字符串 // Display global variable expression prompt strings
public uint m_ulTaskCharCnt;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public ushort[] m_pTaskChar;
public ushort m_pTaskChar_ptr;
// 势力相关 // Force-related
public int m_iForceContribution;
public int m_iForceReputation;
public int m_iForceActivity;
public int m_iForceSetRepu;
public int m_iTaskLimit;
public uint m_ulTitleNum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
public TITLE_AWARD[] m_pTitleAward;
public uint m_pTitleAward_ptr;
public int m_iLeaderShip;
public int m_iWorldContribution; // 世界贡献度 // World contribution
public bool HasAward()
{
return m_ulGoldNum != 0
|| m_ulExp != 0
|| m_ulNewTask != 0
|| m_ulSP != 0
|| m_lReputation != 0
|| m_ulNewPeriod != 0
|| m_ulNewRelayStation != 0
|| m_ulStorehouseSize != 0
|| m_ulStorehouseSize2 != 0
|| m_ulStorehouseSize3 != 0
|| m_ulStorehouseSize4 != 0
|| m_lInventorySize != 0
|| m_ulPetInventorySize != 0
|| m_ulFuryULimit != 0
|| m_bDivorce
|| m_bSendMsg
|| m_bAwardDeath
|| m_ulCandItems != 0
|| m_ulSummonedMonsters != 0
|| m_ulSpecifyContrib != 0
|| m_ulSpecifyContribTaskID != 0
|| m_ulContrib != 0
|| m_ulRandContrib != 0
|| m_ulDividend != 0
|| m_ulPQRankingAwardCnt != 0
|| m_ulSpecifyContribSubTaskID != 0
|| m_bAwardSkill
|| m_iFactionContrib != 0
|| m_iFactionExpContrib != 0
|| m_iForceActivity != 0
|| m_iForceContribution != 0
|| m_iForceReputation != 0
|| m_iForceSetRepu != 0
|| m_iTaskLimit != 0
|| m_ulRealmExp != 0
|| m_bExpandRealmLevelMax;
}
public int MarshalBasicData(byte[] pData)
{
int offset = 0;
int mask = 0;
BitConverter.GetBytes(mask).CopyTo(pData, offset);
offset += 4;
if (m_ulGoldNum != 0)
{
mask |= 1;
BitConverter.GetBytes((int)m_ulGoldNum).CopyTo(pData, offset);
offset += sizeof(int);
}
if (m_ulExp != 0)
{
mask |= 1 << 1;
BitConverter.GetBytes((int)m_ulExp).CopyTo(pData, offset);
offset += sizeof(int);
}
if (m_ulSP != 0)
{
mask |= 1 << 2;
BitConverter.GetBytes((int)m_ulSP).CopyTo(pData, offset);
offset += sizeof(int);
}
if (m_lReputation != 0)
{
mask |= 1 << 3;
BitConverter.GetBytes(m_lReputation).CopyTo(pData, offset);
offset += sizeof(int);
}
if (m_ulCandItems != 0)
{
mask |= 1 << 4;
pData[offset] = (byte)m_ulCandItems;
offset++;
for (int i = 0; i < m_ulCandItems; i++)
{
offset += m_CandItems[i].MarshalBasicData(pData.AsSpan(offset).ToArray());
}
}
if (m_ulSummonedMonsters != 0)
{
mask |= 1 << 5;
pData[offset] = (byte)m_ulSummonedMonsters;
offset++;
offset += m_SummonedMonsters.MarshalBasicData(pData.AsSpan(offset).ToArray());
}
if (m_ulPQRankingAwardCnt != 0)
{
mask |= 1 << 6;
pData[offset] = (byte)m_ulPQRankingAwardCnt;
offset++;
offset += m_PQRankingAward.MarshalBasicData(pData.AsSpan(offset).ToArray());
}
// Update the mask
BitConverter.GetBytes(mask).CopyTo(pData, 0);
return offset;
}
public int UnmarshalBasicData(byte[] pData)
{
int offset = 0;
int mask = BitConverter.ToInt32(pData, offset);
offset += sizeof(int);
if ((mask & 1) != 0)
{
m_ulGoldNum = (uint)BitConverter.ToInt32(pData, offset);
offset += 4;
}
if ((mask & (1 << 1)) != 0)
{
m_ulExp = (uint)BitConverter.ToInt32(pData, offset);
offset += 4;
}
if ((mask & (1 << 2)) != 0)
{
m_ulSP = (uint)BitConverter.ToInt32(pData, offset);
offset += 4;
}
if ((mask & (1 << 3)) != 0)
{
m_lReputation = BitConverter.ToInt32(pData, offset);
offset += 4;
}
if ((mask & (1 << 4)) != 0)
{
m_ulCandItems = pData[offset];
offset++;
if (m_ulCandItems != 0)
{
#if !TASK_TEMPL_EDITOR
m_CandItems = new AWARD_ITEMS_CAND[m_ulCandItems];
#endif
for (uint i = 0; i < m_ulCandItems; i++)
{
offset += m_CandItems[i].UnmarshalBasicData(pData.AsSpan(offset).ToArray());
}
}
}
if ((mask & (1 << 5)) != 0)
{
m_ulSummonedMonsters = pData[offset];
offset++;
if (m_ulSummonedMonsters != 0)
{
#if !TASK_TEMPL_EDITOR
m_SummonedMonsters = new AWARD_MONSTERS_SUMMONED();
#endif
offset += m_SummonedMonsters.UnmarshalBasicData(pData.AsSpan(offset).ToArray());
}
}
if ((mask & (1 << 6)) != 0)
{
m_ulPQRankingAwardCnt = pData[offset];
offset++;
if (m_ulPQRankingAwardCnt != 0)
{
#if !TASK_TEMPL_EDITOR
m_PQRankingAward = new AWARD_PQ_RANKING();
#endif
offset += m_PQRankingAward.UnmarshalBasicData(pData.AsSpan(offset).ToArray());
}
}
return offset;
}
public static bool CompareTwoPointer<T>(T p1, T p2) where T : class
{
if (p1 == null && p2 == null)
{
return true;
}
else if (p1 != null && p2 != null)
{
return p1.Equals(p2);
}
else
return false;
}
public static bool operator ==(AWARD_DATA a, AWARD_DATA b)
{
if (a.m_ulCandItems != b.m_ulCandItems || a.m_ulSummonedMonsters != b.m_ulSummonedMonsters ||
a.m_ulChangeKeyCnt != b.m_ulChangeKeyCnt || a.m_ulDisplayKeyCnt != b.m_ulDisplayKeyCnt ||
a.m_ulExpCnt != b.m_ulExpCnt || a.m_ulTaskCharCnt != b.m_ulTaskCharCnt ||
a.m_ulHistoryChangeCnt != b.m_ulHistoryChangeCnt)
{
return false;
}
for (uint i = 0; i < a.m_ulCandItems; ++i)
{
if (!(a.m_CandItems[i] == b.m_CandItems[i]))
{
return false;
}
}
if (!TaskTemplUtils.CompareTwoPointer(a.m_SummonedMonsters, b.m_SummonedMonsters))
{
return false;
}
for (uint i = 0; i < a.m_ulChangeKeyCnt; ++i)
{
if (a.m_plChangeKey[i] != b.m_plChangeKey[i] ||
a.m_plChangeKeyValue[i] != b.m_plChangeKeyValue[i] ||
a.m_pbChangeType[i] != b.m_pbChangeType[i])
{
return false;
}
}
for (uint i = 0; i < a.m_ulHistoryChangeCnt; ++i)
{
if (a.m_plHistoryChangeKey[i] != b.m_plHistoryChangeKey[i] ||
a.m_plHistoryChangeKeyValue[i] != b.m_plHistoryChangeKeyValue[i] ||
a.m_pbHistoryChangeType[i] != b.m_pbHistoryChangeType[i])
{
return false;
}
}
for (uint i = 0; i < a.m_ulDisplayKeyCnt; ++i)
{
if (a.m_plDisplayKey[i] != b.m_plDisplayKey[i])
{
return false;
}
}
if (!TaskTemplUtils.CompareTwoPointer(a.m_PQRankingAward, b.m_PQRankingAward))
{
return false;
}
return (a.m_ulGoldNum == b.m_ulGoldNum &&
a.m_ulExp == b.m_ulExp &&
a.m_ulNewTask == b.m_ulNewTask &&
a.m_ulSP == b.m_ulSP &&
a.m_lReputation == b.m_lReputation &&
a.m_ulNewPeriod == b.m_ulNewPeriod &&
a.m_ulNewRelayStation == b.m_ulNewRelayStation &&
a.m_ulStorehouseSize == b.m_ulStorehouseSize &&
a.m_ulStorehouseSize2 == b.m_ulStorehouseSize2 &&
a.m_ulStorehouseSize3 == b.m_ulStorehouseSize3 &&
a.m_ulStorehouseSize4 == b.m_ulStorehouseSize4 &&
a.m_lInventorySize == b.m_lInventorySize &&
a.m_ulPetInventorySize == b.m_ulPetInventorySize &&
a.m_ulFuryULimit == b.m_ulFuryULimit &&
a.m_ulTransWldId == b.m_ulTransWldId &&
a.m_TransPt.Equals(b.m_TransPt) &&
a.m_lMonsCtrl == b.m_lMonsCtrl &&
a.m_bTrigCtrl == b.m_bTrigCtrl &&
a.m_bUseLevCo == b.m_bUseLevCo &&
a.m_bDivorce == b.m_bDivorce &&
a.m_bSendMsg == b.m_bSendMsg &&
a.m_nMsgChannel == b.m_nMsgChannel &&
a.m_bAwardDeath == b.m_bAwardDeath &&
a.m_bAwardDeathWithLoss == b.m_bAwardDeathWithLoss &&
a.m_ulDividend == b.m_ulDividend &&
a.m_bAwardSkill == b.m_bAwardSkill &&
a.m_iAwardSkillID == b.m_iAwardSkillID &&
a.m_iAwardSkillLevel == b.m_iAwardSkillLevel &&
a.m_ulSpecifyContribTaskID == b.m_ulSpecifyContribTaskID &&
a.m_ulSpecifyContribSubTaskID == b.m_ulSpecifyContribSubTaskID &&
a.m_ulSpecifyContrib == b.m_ulSpecifyContrib &&
a.m_ulContrib == b.m_ulContrib &&
a.m_ulRandContrib == b.m_ulRandContrib &&
a.m_ulLowestcontrib == b.m_ulLowestcontrib &&
a.m_iFactionContrib == b.m_iFactionContrib &&
a.m_iFactionExpContrib == b.m_iFactionExpContrib &&
a.m_ulPQRankingAwardCnt == b.m_ulPQRankingAwardCnt &&
a.m_bMulti == b.m_bMulti &&
a.m_nNumType == b.m_nNumType &&
a.m_lNum == b.m_lNum
);
}
public static bool operator !=(AWARD_DATA a, AWARD_DATA b)
{
return !(a == b);
}
public override bool Equals(object obj)
{
if (obj is AWARD_DATA)
{
return this == (AWARD_DATA)obj;
}
return false;
}
public override int GetHashCode()
{
return m_ulGoldNum.GetHashCode() ^
m_ulExp.GetHashCode() ^
m_lReputation.GetHashCode() ^
m_ulSP.GetHashCode();
}
}
public enum task_tm_type
{
enumTaskTimeDate = 0,
enumTaskTimeMonth,
enumTaskTimeWeek,
enumTaskTimeDay
};
/// <summary>
/// Completion Method
/// </summary>
public enum TaskMethod
{
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
}
[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();
}
}
[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();
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ATaskTemplFixedData
{
// 任务id // Task ID
public uint m_ID;
// 任务名称 // Task name
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_TASK_NAME_LEN)]
public char[] m_szName;
// 任务署名 // Task signature
public bool m_bHasSign;
public ushort[] m_pszSignature;
// 任务类型 // Task type
public uint m_ulType;
// 时间限制 // Time limit
public uint m_ulTimeLimit;
// 下线任务失败 // Task fails when offline
public bool m_bOfflineFail;
// 任务失败时间 // Task failure time
public bool m_bAbsFail;
public task_tm m_tmAbsFailTime;
// 任务开启物品检验不收取 // Don't take items when validating task start
public bool m_bItemNotTakeOff;
// 是否绝对时间 // Whether absolute time
public bool m_bAbsTime;
// 时间段个数 // Number of time periods
public uint m_ulTimetable;
// 时间方式 // Time method
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_TIMETABLE_SIZE)]
public byte[] m_tmType;
// 发放起始时间 // Distribution start time
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public task_tm[] m_tmStart;
// 发放终止时间 // Distribution end time
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public task_tm[] m_tmEnd;
// 发放频率 // Distribution frequency
public int m_lAvailFrequency;
public int m_lPeriodLimit;
// 选择单个子任务执行 // Execute single subtask
public bool m_bChooseOne;
// 随机旋转单个子任务执行 // Randomly rotate single subtask execution
public bool m_bRandOne;
// 子任务是否有顺序 // Whether subtasks have order
public bool m_bExeChildInOrder;
// 失败后是否认为父任务也失败 // Whether parent task fails when subtask fails
public bool m_bParentAlsoFail;
// 子任务成功后父任务成功 // Parent task succeeds when subtask succeeds
public bool m_bParentAlsoSucc;
// 能否放弃此任务 // Whether task can be abandoned
public bool m_bCanGiveUp;
// 是否可重复完成 // Whether task can be repeated
public bool m_bCanRedo;
// 失败后是否可重新完成 // Whether task can be redone after failure
public bool m_bCanRedoAfterFailure;
// 放弃清空任务 // Clear task when abandoned
public bool m_bClearAsGiveUp;
// 是否需要记录 // Whether recording is needed
public bool m_bNeedRecord;
// 玩家被杀死是否认为失败 // Whether task fails when player dies
public bool m_bFailAsPlayerDie;
// 接受者上限 // Maximum number of receivers
public uint m_ulMaxReceiver;
// 发放区域 // Distribution area
public bool m_bDelvInZone;
public uint m_ulDelvWorld;
public uint m_ulDelvRegionCnt;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_TASKREGION)]
// [NonSerialized]
// public Task_Region[] m_pDelvRegion;
public Task_Region[] m_pDelvRegion_ptr;
// 进入区域任务失败 // Task fails when entering region
public bool m_bEnterRegionFail;
public uint m_ulEnterRegionWorld;
public uint m_ulEnterRegionCnt;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_TASKREGION)]
// [NonSerialized]
// public Task_Region[] m_pEnterRegion;
public uint m_pEnterRegion_ptr;
// 离开区域任务失败 // Task fails when leaving region
public bool m_bLeaveRegionFail;
public uint m_ulLeaveRegionWorld;
public uint m_ulLeaveRegionCnt;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_TASKREGION)]
// [NonSerialized]
// public Task_Region[] m_pLeaveRegion;
public uint m_pLeaveRegion_ptr;
// 离开阵营失败 // Fails when leaving force
public bool m_bLeaveForceFail;
// 传送到特定点 // Teleport to specific point
public bool m_bTransTo;
public uint m_ulTransWldId;
public ZONE_VERT m_TransPt;
// Monster controller
public long m_lMonsCtrl;
public bool m_bTrigCtrl;
// Auto trigger when conditions are met
public bool m_bAutoDeliver;
// Whether to display in exclusive UI
public bool m_bDisplayInExclusiveUI;
public bool m_bReadyToNotifyServer;
// Whether used in token shop
public bool m_bUsedInTokenShop;
// Death trigger
public bool m_bDeathTrig;
// Whether clear all acquired items
public bool m_bClearAcquired;
// Recommended level
public uint m_ulSuitableLevel;
// Whether to show prompt
public bool m_bShowPrompt;
// Whether it is a key task
public bool m_bKeyTask;
// Delivery NPC
public uint m_ulDelvNPC;
// Award NPC
public uint m_ulAwardNPC;
// Whether it is a skill task
public bool m_bSkillTask;
// Whether can be searched
public bool m_bCanSeekOut;
// Whether show direction
public bool m_bShowDirection;
// Marriage
public bool m_bMarriage;
// Change global key/value
public uint m_ulChangeKeyCnt;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public int[] m_plChangeKey; // [TASK_AWARD_MAX_CHANGE_VALUE]
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public int[] m_plChangeKeyValue;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public bool[] m_pbChangeType;
// Fail on scene switch
public bool m_bSwitchSceneFail;
// Hidden task
public bool m_bHidden;
// Whether deliver skill
public bool m_bDeliverySkill;
public int m_iDeliveredSkillID;
public int m_iDeliveredSkillLevel;
// Whether show task completion effect
public bool m_bShowGfxFinished;
// Whether change player ranking in PQ
public bool m_bChangePQRanking;
// Compare delivery items with player inventory slots
public bool m_bCompareItemAndInventory;
public uint m_ulInventorySlotNum;
// PQ Task related // PQ任务相关
public bool m_bPQTask; // Whether it is a PQ task // 是否是PQ任务
public uint m_ulPQExpCnt; // PQ task global variable display // PQ任务全局变量显示
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public byte[,] m_pszPQExp; // PQ expressions
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public TASK_EXPRESSION[,] m_pPQExpArr; // PQ expression arrays
public bool m_bPQSubTask; // Whether it is a PQ subtask // 是否PQ子任务
public bool m_bClearContrib; // Clear contribution when task starts // 任务开始时清空贡献度
public uint m_ulMonsterContribCnt; // Number of monster types // 怪物种类数量
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public MONSTERS_CONTRIB[] m_MonstersContrib; // Monster contribution settings // 怪物贡献度设定
// Account Task related // 账号任务相关
public int m_iPremNeedRecordTasksNum; // Number of completed record tasks // 记录完成结果任务完成个数
public bool m_bShowByNeedRecordTasksNum; // Show by number of needed record tasks
public int m_iPremiseFactionContrib; // Faction contribution // 帮派贡献度
public bool m_bShowByFactionContrib; // Show by faction contribution
public bool m_bAccountTaskLimit; // Whether account limits completion times // 是否账号限制完成次数
public bool m_bRoleTaskLimit; // Whether role limits completion times // 是否角色限制完成次数
public uint m_ulAccountTaskLimitCnt; // Account task limit count (deprecated) // 账号限制完成次数,废弃使用了
public bool m_bLeaveFactionFail; // Fail when leaving faction
public bool m_bNotIncCntWhenFailed; // Don't increase count when failed // 是否失败时不增加完成次数
public bool m_bNotClearItemWhenFailed; // Don't clear items when failed // 任务失败时不收取任务要求的物品
public bool m_bDisplayInTitleTaskUI; // Show in title task UI // 是否显示在称号任务界面里
/* 开启条件 */ /* Opening conditions */
// 变身状态 // Transformation state
public byte m_ucPremiseTransformedForm;
public bool m_bShowByTransformed;
// 等级条件 // Level conditions
public uint m_ulPremise_Lev_Min;
public uint m_ulPremise_Lev_Max;
public uint m_bPremCheckMaxHistoryLevel;
public bool m_bShowByLev;
// 转生次数 // Reincarnation times
public bool m_bPremCheckReincarnation;
public uint m_ulPremReincarnationMin;
public uint m_ulPremReincarnationMax;
public bool m_bShowByReincarnation;
// 境界 // Realm level
public bool m_bPremCheckRealmLevel;
public uint m_ulPremRealmLevelMin;
public uint m_ulPremRealmLevelMax;
public bool m_bPremCheckRealmExpFull;
public bool m_bShowByRealmLevel;
// 所需道具 // Required items
public uint m_ulPremItems;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public ITEM_WANTED[] m_PremItems; //[MAX_ITEM_WANTED];
public bool m_bShowByItems;
public bool m_bPremItemsAnyOne;
// 发放道具 // Given items
public uint m_ulGivenItems;
public uint m_ulGivenCmnCount;
public uint m_ulGivenTskCount;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public ITEM_WANTED[] m_GivenItems; //[MAX_ITEM_WANTED];
// 押金 // Deposit
public uint m_ulPremise_Deposit;
public bool m_bShowByDeposit;
// 声望 // Reputation
public long m_lPremise_Reputation;
public long m_lPremise_RepuMax;
public bool m_bShowByRepu;
// 完成特定任务(成功?失败?),Task ID最高位1表示条件为失败,0为成功 // Complete specific tasks (success? failure?), Task ID highest bit 1 means failure condition, 0 means success condition
public uint m_ulPremise_Task_Count;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_PREM_TASK_COUNT)]
public uint[] m_ulPremise_Tasks;
public bool m_bShowByPreTask;
public uint m_ulPremise_Task_Least_Num; // 多个前提任务需要完成若干个 // Multiple prerequisite tasks need to complete a certain number
// 达到特定时期 // Reach specific period
public uint m_ulPremise_Period;
public bool m_bShowByPeriod;
// 帮派 // Faction
public uint m_ulPremise_Faction;
public int m_iPremise_FactionRole;
public bool m_bShowByFaction;
// 性别 // Gender
public uint m_ulGender;
public bool m_bShowByGender;
// 职业限制 // Occupation restrictions
public uint m_ulOccupations;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_OCCUPATIONS)]
public uint[] m_Occupations;
public bool m_bShowByOccup;
// 夫妻 // Spouse
public bool m_bPremise_Spouse;
public bool m_bShowBySpouse;
public bool m_bPremiseWeddingOwner;
public bool m_bShowByWeddingOwner;
// GM
public bool m_bGM;
// 完美神盾用户 // Perfect Shield user
public bool m_bShieldUser;
// 账号累计充值金额(下限&上限) // Account accumulated recharge amount (lower & upper limit)
public bool m_bShowByRMB;
public uint m_ulPremRMBMin;
public uint m_ulPremRMBMax;
// 角色相关时间 // Character-related time
public bool m_bCharTime;
public bool m_bShowByCharTime;
public int m_iCharStartTime;
public int m_iCharEndTime; // 为0则为当前时间;为1则为m_tmCharEndTime指定时间; // 0 means current time; 1 means the time specified by m_tmCharEndTime;
public task_tm m_tmCharEndTime;
public uint m_ulCharTimeGreaterThan;
// 关联任务 // Related tasks
public uint m_ulPremise_Cotask;
public uint m_ulCoTaskCond;
// 互斥任务 // Mutually exclusive tasks
public uint m_ulMutexTaskCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_MUTEX_TASK_COUNT)]
public uint[] m_ulMutexTasks;
// 生活技能级别 // Life skill levels
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_LIVING_SKILLS)]
public long[] m_lSkillLev;
// 动态任务类型 // Dynamic task type
public byte m_DynTaskType;
// 特殊奖励号,用于运营的活动 // Special award number, used for operational activities
public uint m_ulSpecialAward;
// 组队信息 // Team information
public bool m_bTeamwork; // 组队任务 // Team task
public bool m_bRcvByTeam; // 必须组队接收 // Must be in team to receive
public bool m_bSharedTask; // 新队员分享任务 // New team members share tasks
public bool m_bSharedAchieved; // 分享杀怪、物品数量 // Share kill counts and item counts
public bool m_bCheckTeammate; // 检查队友位置 // Check teammate positions
public float m_fTeammateDist; // 队友距离平方值 // Square of teammate distance
public bool m_bAllFail; // 任意队员失败则全部失败 // Any member fails, all fail
public bool m_bCapFail; // 队长失败则全部失败 // Leader fails, all fail
public bool m_bCapSucc; // 队长成功则全队成功 // Leader succeeds, all succeed
public float m_fSuccDist; // 成功时队员的距离 // Member distance for success
public bool m_bDismAsSelfFail; // 队员离队自身失败 // Member leaves team fails itself
public bool m_bRcvChckMem; // 接任务时检查队员位置 // Check member positions when receiving task
public float m_fRcvMemDist; // 接任务时队员距离平方值 // Square of member distance when receiving task
public bool m_bCntByMemPos; // 队员在有效范围内杀怪有效 // Members in valid range for kill counts
public float m_fCntMemDist; // 队员有效的范围 // Valid range for members
public bool m_bAllSucc; // 任意队员成功则全部成功 // Any member succeeds, all succeed
public bool m_bCoupleOnly; // 队长队员必须为夫妻 // Leader and member must be spouses
public bool m_bDistinguishedOcc; // 队伍中不允许有相同的职业 // No same occupations allowed in team
// 队伍成员需求 // Team member requirements
public uint m_ulTeamMemsWanted;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public TEAM_MEM_WANTED[] m_TeamMemsWanted;
public bool m_bShowByTeam;
// 前提全局key/value // Premise global key/value
public bool m_bPremNeedComp;
public int m_nPremExp1AndOrExp2;
public COMPARE_KEY_VALUE m_Prem1KeyValue;
public COMPARE_KEY_VALUE m_Prem2KeyValue;
public bool m_bPremCheckForce;
public int m_iPremForce;
public bool m_bShowByForce;
public int m_iPremForceReputation;
public bool m_bShowByForceReputation;
public int m_iPremForceContribution; // 扣除战功 // Deduct military merit
public bool m_bShowByForceContribution;
public int m_iPremForceExp; // 经验兑换 // Experience exchange
public bool m_bShowByForceExp;
public int m_iPremForceSP; // 元神兑换 // Spirit exchange
public bool m_bShowByForceSP;
public int m_iPremForceActivityLevel;
public bool m_bShowByForceActivityLevel;
public bool m_bPremIsKing;
public bool m_bShowByKing;
public bool m_bPremNotInTeam;
public bool m_bShowByNotInTeam;
public uint m_iPremTitleNumTotal;
public uint m_iPremTitleNumRequired;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public int[] m_PremTitles;
public bool m_bShowByTitle;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public int[] m_iPremHistoryStageIndex; // 历史阶段 // Historical stage
public bool m_bShowByHistoryStage;
public uint m_ulPremGeneralCardCount; // 收集的卡牌数量 // Number of collected cards
public bool m_bShowByGeneralCard;
public int m_iPremGeneralCardRank; // 要求某品阶的卡牌数量 // Required number of cards of a certain rank
public uint m_ulPremGeneralCardRankCount;
public bool m_bShowByGeneralCardRank;
/* 任务完成的方式及条件 */ /* Task completion methods and conditions */
public uint m_enumMethod;
public uint m_enumFinishType;
/* 任务方式 */ /* Task methods */
public uint m_ulPlayerWanted;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public PLAYER_WANTED[] m_PlayerWanted;
public uint m_ulMonsterWanted;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public MONSTER_WANTED[] m_MonsterWanted;
public uint m_ulItemsWanted;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public ITEM_WANTED[] m_ItemsWanted;
public uint m_ulGoldWanted;
public int m_iFactionContribWanted;
public int m_iFactionExpContribWanted;
public uint m_ulNPCToProtect;
public uint m_ulProtectTimeLen;
public uint m_ulNPCMoving;
public uint m_ulNPCDestSite;
//public ZONE_VERT m_ReachSiteMin;
//public ZONE_VERT m_ReachSiteMax;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public Task_Region[] m_pReachSite;
public uint m_ulReachSiteCnt;
public uint m_ulReachSiteId;
public uint m_ulWaitTime;
//藏宝图 使用已接任务列表中的m_iUsefulData1存储 // Treasure map Use m_iUsefulData1 in the list of accepted tasks
public enum TREASURE_DISTANCE_LEVEL
{
DISTANCE_FAR_FAR_AWAY,
DISTANCE_FAR,
DISTANCE_MEDIUM,
DISTANCE_NEAR,
DISTANCE_VERY_NEAR,
DISTANCE_NUM,
}
// TREA section
public ZONE_VERT m_TreasureStartZone;
public byte m_ucZonesNumX;
public byte m_ucZonesNumZ;
public byte m_ucZoneSide;
//public ZONE_VERT m_LeaveSiteMin;
//public ZONE_VERT m_LeaveSiteMax;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
[NonSerialized]
public Task_Region[] m_pLeaveSite;
public uint m_ulLeaveSiteCnt;
public uint m_ulLeaveSiteId;
// 完成全局key/value // Complete global key/value
public bool m_bFinNeedComp;
public int m_nFinExp1AndOrExp2;
public COMPARE_KEY_VALUE m_Fin1KeyValue;
public COMPARE_KEY_VALUE m_Fin2KeyValue;
// 需显示的全局变量表达式 // Global variable expressions to display
public uint m_ulExpCnt;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public byte[,] m_pszExp;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
[NonSerialized]
public TASK_EXPRESSION[,] m_pExpArr;
// 需显示的全局变量表达式提示字符串 // Global variable expression prompt strings
public uint m_ulTaskCharCnt;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
[NonSerialized]
public ushort[,] m_pTaskChar;
// 变身状态 // Transformation state
public byte m_ucTransformedForm;
// 等级 // Level
public uint m_ulReachLevel;
// 转生次数 // Reincarnation count
public uint m_ulReachReincarnationCount;
// 境界等级 // Realm level
public uint m_ulReachRealmLevel;
public uint m_uiEmotion; // 表情动作 // Emotion action
/* 任务结束后的奖励 */ /* Rewards after task completion */
public uint m_ulAwardType_S;
public uint m_ulAwardType_F;
/* 普通和按每个方式 */ /* Normal and per-method rewards */
// [NonSerialized]
// public AWARD_DATA m_Award_S; /* 成功 */ /* Success */
public uint m_Award_S_ptr;
[NonSerialized]
// public AWARD_DATA m_Award_F; /* 失败 */ /* Failure */
public uint m_Award_F_ptr;
/* 时间比例方式 */ /* Time ratio method */
//TODO: Revert
[NonSerialized]
// public AWARD_RATIO_SCALE m_AwByRatio_S;
public uint m_AwByRatio_S_ptr;
[NonSerialized]
// public AWARD_RATIO_SCALE m_AwByRatio_F;
public uint m_AwByRatio_F_ptr;
/* 按获得物比例方式 */ /* Item ratio method */
//TODO: Revert
[NonSerialized]
// public AWARD_ITEMS_SCALE m_AwByItems_S;
public uint m_AwByItems_S_ptr;
[NonSerialized]
// public AWARD_ITEMS_SCALE m_AwByItems_F;
public uint m_AwByItems_F_ptr;
/* 层次结构 */ /* Hierarchy structure */
public uint m_ulParent;
public uint m_ulPrevSibling;
public uint m_ulNextSibling;
public uint m_ulFirstChild;
/* 库任务相关 */ /* Library task related */
public bool m_bIsLibraryTask;
public float m_fLibraryTasksProbability;
public bool m_bIsUniqueStorageTask;
public int m_iWorldContribution; // 世界贡献度要求 // World contribution requirement
}
public class ATaskTempl
{
public ATaskTemplFixedData m_FixedData;
//Hierarchy
public ATaskTempl m_pParent;
public ATaskTempl m_pPrevSibling;
public ATaskTempl m_pNextSibling;
public ATaskTempl m_pFirstChild;
const int MAX_TASK_NAME_LEN = 30;
public byte m_uValidCount;
public bool LoadFromBinFile(FileStream fp)
{
LoadBinary(fp);
// CheckDepth();
return true;
}
private void LoadBinary(FileStream fp)
{
LoadFixedDataFromBinFile(fp);
// LoadDescriptionBin(fp);
// LoadTributeBin(fp);
//# ifndef _TASK_CLIENT
// CheckMask();
//#else
// SyncTaskType();
//#endif
// namechar code = (namechar)m_ID;
// m_DelvTaskTalk.load(fp);
// convert_talk_text(&m_DelvTaskTalk, code);
// m_UnqualifiedTalk.load(fp);
// convert_talk_text(&m_UnqualifiedTalk, code);
// m_DelvItemTalk.load(fp);
// convert_talk_text(&m_DelvItemTalk, code);
// m_ExeTalk.load(fp);
// convert_talk_text(&m_ExeTalk, code);
// m_AwardTalk.load(fp);
// convert_talk_text(&m_AwardTalk, code);
// fread(&m_nSubCount, sizeof(m_nSubCount), 1, fp);
// for (int i = 0; i < m_nSubCount; i++)
// {
// ATaskTempl* pSub = new ATaskTempl;
// g_ulNewCount++;
// AddSubTaskTempl(pSub);
// pSub->LoadBinary(fp);
// }
// SynchID();
//return true;
}
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;
}
private void ConvertFixedData(FileStream fp, int x2)
{
long readBytes = 0;
BMLogger.Log($"LoadFixedDataFromBinFile: {fp.Length}");
ATaskTemplFixedData fixedData;
var originalPos = fp.Position;
// Task ID
fixedData.m_ID = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // unsigned long m_ID;
BMLogger.LogError($"m_ID: {fixedData.m_ID}");
// Task Name (task_char m_szName[MAX_TASK_NAME_LEN];)
var raw = AAssit.ReadArrayFromBinary<ushort>(fp, TaskTemplConstants.MAX_TASK_NAME_LEN, ref readBytes); //64
fixedData.m_szName = Array.ConvertAll(raw, c => (char)c);
BMLogger.LogError($"m_szName: {new string(fixedData.m_szName)}"); //68
// Has Signature (bool m_bHasSign;)
fixedData.m_bHasSign = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
BMLogger.LogError($"m_bHasSign: {fixedData.m_bHasSign}"); //68
// Signature pointer (task_char* m_pszSignature;)
// Only the pointer address is stored in the binary (skip 4 bytes)
fp.Seek(4, SeekOrigin.Current);
// Task Type (unsigned long m_ulType;)
fixedData.m_ulType = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);//value 103
BMLogger.LogError($"Type: {fixedData.m_ulType}");
// Time Limit (unsigned long m_ulTimeLimit;)
fixedData.m_ulTimeLimit = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
BMLogger.LogError($"m_ulTimeLimit: {fixedData.m_ulTimeLimit}");
// Offline Fail (bool m_bOfflineFail;)
fixedData.m_bOfflineFail = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
BMLogger.LogError($"m_bOfflineFail: {fixedData.m_bOfflineFail}");
// Absolute Fail (bool m_bAbsFail;)
fixedData.m_bAbsFail = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
BMLogger.LogError($"m_bAbsFail: {fixedData.m_bAbsFail}");
// Absolute Fail Time (task_tm m_tmAbsFailTime;)
fixedData.m_tmAbsFailTime = AAssit.ReadFromBinaryOf<task_tm>(fp, ref readBytes);
BMLogger.LogError($"m_tmAbsFailTime: {fixedData.m_tmAbsFailTime.day}");
// (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;
BMLogger.LogError($"m_bItemNotTakeOff: {fixedData.m_bItemNotTakeOff}");
// Absolute Time (bool m_bAbsTime;)
fixedData.m_bAbsTime = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
BMLogger.LogError($"m_bAbsTime: {fixedData.m_bAbsTime}");
// Timetable count (unsigned long m_ulTimetable;)
fixedData.m_ulTimetable = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
BMLogger.LogError($"m_ulTimetable: {fixedData.m_ulTimetable}");
// Timetable type (char m_tmType[MAX_TIMETABLE_SIZE];)
fixedData.m_tmType = AAssit.ReadArrayFromBinary<byte>(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes);
BMLogger.LogError($"m_tmType: {fixedData.m_tmType}");
// 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);
// 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);
// Available frequency (long m_lAvailFrequency;)
fixedData.m_lAvailFrequency = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
BMLogger.LogError($"m_lAvailFrequency: {fixedData.m_lAvailFrequency}");
// Period limit (long m_lPeriodLimit;)
fixedData.m_lPeriodLimit = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
BMLogger.LogError($"m_lPeriodLimit: {fixedData.m_lPeriodLimit}");
// Choose one subtask (bool m_bChooseOne;)
fixedData.m_bChooseOne = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
BMLogger.LogError($"m_bChooseOne: {fixedData.m_bChooseOne}");
// Random one subtask (bool m_bRandOne;)
fixedData.m_bRandOne = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
BMLogger.LogError($"m_bRandOne: {fixedData.m_bRandOne}");
// 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
BMLogger.LogError($"m_bExeChildInOrder: {fixedData.m_bExeChildInOrder}");
// 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
BMLogger.LogError($"m_bParentAlsoFail: {fixedData.m_bParentAlsoFail}");
// 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
BMLogger.LogError($"m_bParentAlsoSucc: {fixedData.m_bParentAlsoSucc}");
// 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
BMLogger.LogError($"m_bCanGiveUp: {fixedData.m_bCanGiveUp}");
// 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
BMLogger.LogError($"m_bCanRedo: {fixedData.m_bCanRedo}");
// 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
BMLogger.LogError($"m_bCanRedoAfterFailure: {fixedData.m_bCanRedoAfterFailure}");
// Give up clears the task
// bool m_bClearAsGiveUp;
fixedData.m_bClearAsGiveUp = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0; // 放弃清空任务 // Give up clears the task
BMLogger.LogError($"m_bClearAsGiveUp: {fixedData.m_bClearAsGiveUp}");
// Whether recording is needed
// bool m_bNeedRecord;
fixedData.m_bNeedRecord = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0; // 是否需要记录 // Whether recording is needed
BMLogger.LogError($"m_bNeedRecord: {fixedData.m_bNeedRecord}");
// Player's death causes failure
// bool m_bFailAsPlayerDie;
fixedData.m_bFailAsPlayerDie = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0; // 玩家被击杀是否认为失败 // Player's death causes failure
BMLogger.LogError($"m_bFailAsPlayerDie: {fixedData.m_bFailAsPlayerDie}");
// Maximum number of receivers
// unsigned long m_ulMaxReceiver;
fixedData.m_ulMaxReceiver = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 接受者上限 // Maximum number of receivers
BMLogger.LogError($"m_ulMaxReceiver: {fixedData.m_ulMaxReceiver}");
// Is in delivery zone
// bool m_bDelvInZone;
fixedData.m_bDelvInZone = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0; // 发放区域 // Is in delivery zone
BMLogger.LogError($"m_bDelvInZone: {fixedData.m_bDelvInZone}");
// Delivery world id
// unsigned long m_ulDelvWorld;
fixedData.m_ulDelvWorld = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 发放世界 // Delivery world id
BMLogger.LogError($"m_ulDelvWorld: {fixedData.m_ulDelvWorld}");
// Number of delivery regions
// unsigned long m_ulDelvRegionCnt;
fixedData.m_ulDelvRegionCnt = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes); // 发放区域计数 // Number of delivery regions
BMLogger.LogError($"m_ulDelvRegionCnt: {fixedData.m_ulDelvRegionCnt}");
fp.Seek(originalPos, SeekOrigin.Begin);
return;
}
#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
string ConvertTxt(string str, char code)
{
char[] chars = str.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
chars[i] = (char)(chars[i] ^ code);
}
return new string(chars);
}
public void IncValidCount() { m_uValidCount++; }
}
}