From b904c00762a3c984d56d59f1607e74c0b747424e Mon Sep 17 00:00:00 2001 From: MinhHai Date: Sat, 1 Nov 2025 19:21:48 +0700 Subject: [PATCH] complete convert fixed data and decription --- .cursor/rules/convert-data-rule.mdc | 28 +- Assets/Scripts/Task/ATaskTemplFixedData.cs | 132 +- Assets/Scripts/Task/ATaskTemplMan.cs | 6 +- Assets/Scripts/Task/AWARD_DATA.cs | 565 +++++++ Assets/Scripts/Task/AWARD_DATA.cs.meta | 3 + Assets/Scripts/Task/AWARD_ITEMS_CAND.cs | 108 ++ Assets/Scripts/Task/AWARD_ITEMS_CAND.cs.meta | 3 + Assets/Scripts/Task/SizeTest.cs | 27 + Assets/Scripts/Task/SizeTest.cs.meta | 2 + Assets/Scripts/Task/TaskTempl.cs | 1475 ++++++++++-------- 10 files changed, 1643 insertions(+), 706 deletions(-) create mode 100644 Assets/Scripts/Task/AWARD_DATA.cs create mode 100644 Assets/Scripts/Task/AWARD_DATA.cs.meta create mode 100644 Assets/Scripts/Task/AWARD_ITEMS_CAND.cs create mode 100644 Assets/Scripts/Task/AWARD_ITEMS_CAND.cs.meta create mode 100644 Assets/Scripts/Task/SizeTest.cs create mode 100644 Assets/Scripts/Task/SizeTest.cs.meta diff --git a/.cursor/rules/convert-data-rule.mdc b/.cursor/rules/convert-data-rule.mdc index 4954635dec..06b1d42942 100644 --- a/.cursor/rules/convert-data-rule.mdc +++ b/.cursor/rules/convert-data-rule.mdc @@ -137,9 +137,9 @@ fixedData.m_tmAbsFailTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); --- -## Case 5: Pointer to Basic Type (Size Not Predefined) +## Case 5: Pointer to Basic Type (Not Inline) -**Pattern**: Pointer to a basic/primitive type where the pointed-to data is not stored inline +**Pattern**: Pointer to a basic/primitive type where only the pointer address is stored in the struct. The pointed-to content (if any) is stored elsewhere in the file and must be read later based on counts/flags. **C++ Examples**: ```cpp @@ -151,20 +151,13 @@ float* m_pFloatArray; // Pointer to float **C# Conversion**: ```csharp -// Skip the size of ONE element of the basic type (not the pointer itself) -fp.Seek(2, SeekOrigin.Current); // ushort = 2 bytes -fp.Seek(4, SeekOrigin.Current); // int = 4 bytes -fp.Seek(1, SeekOrigin.Current); // bool = 1 byte -fp.Seek(4, SeekOrigin.Current); // float = 4 bytes +// Always skip the pointer address (4 bytes in the binary layout) +fp.Seek(4, SeekOrigin.Current); ``` -**Rule**: Skip `sizeof(basicType)` bytes using `fp.Seek(sizeOfType, SeekOrigin.Current)` where: -- `ushort` → 2 bytes -- `int`, `uint`, `float` → 4 bytes -- `byte`, `bool`, `char` → 1 byte -- `long`, `ulong`, `double` → 8 bytes +**Rule**: For any pointer (to basic or user-defined types), always skip 4 bytes to account for the stored pointer address in the C++ binary. The actual data, if present, should be read later using accompanying count/flag fields. -**Note**: Similar to Case 3, the actual array data (if it exists) must be read separately based on count variables or other logic. +**Note**: This assumes the source binary was written with 32-bit pointer sizes. If you ever process binaries with 64-bit pointer sizes, adjust accordingly. --- @@ -177,7 +170,7 @@ Is it a pointer (has * in C++)? ├── YES │ ├── Is it a user-defined type (struct/class)? │ │ ├── YES → Case 3: Skip 4 bytes (pointer address) -│ │ └── NO (basic type) → Case 5: Skip sizeof(basic type) +│ │ └── NO (basic type) → Case 5: Skip 4 bytes (pointer address) │ └── NO │ ├── Is it an array with predefined size? │ │ ├── YES → Case 2: Read array using ReadArrayFromBinary @@ -275,15 +268,16 @@ fixedData.m_bHasSign = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // --- -❌ **Wrong**: Skipping pointer size instead of basic type size for Case 5 +❌ **Wrong**: Skipping only `sizeof(basic type)` for a pointer in Case 5 ```csharp // C++: ushort* m_pszSignature -fp.Seek(4, SeekOrigin.Current); // Wrong! This is Case 3, but ushort* should be Case 5 +fp.Seek(2, SeekOrigin.Current); // Wrong! Do not skip sizeof(ushort) for pointers ``` ✅ **Correct**: ```csharp -fp.Seek(2, SeekOrigin.Current); // Correct! Skip sizeof(ushort) = 2 bytes +// Always skip the pointer address (4 bytes) +fp.Seek(4, SeekOrigin.Current); ``` --- diff --git a/Assets/Scripts/Task/ATaskTemplFixedData.cs b/Assets/Scripts/Task/ATaskTemplFixedData.cs index 5804dd5be4..e0981eac6c 100644 --- a/Assets/Scripts/Task/ATaskTemplFixedData.cs +++ b/Assets/Scripts/Task/ATaskTemplFixedData.cs @@ -14,6 +14,7 @@ namespace PerfectWorld.Scripts.Task public ushort[] m_szName; // 任务署名 // Task signature + [MarshalAs(UnmanagedType.U1)] public bool m_bHasSign; // 署名字符串 // Signature string @@ -27,16 +28,20 @@ namespace PerfectWorld.Scripts.Task public uint m_ulTimeLimit; // 下线任务失败 // Task fails when offline + [MarshalAs(UnmanagedType.U1)] public bool m_bOfflineFail; // 任务失败时间 // Task failure time + [MarshalAs(UnmanagedType.U1)] public bool m_bAbsFail; public task_tm m_tmAbsFailTime; // 任务开启物品检验不收取 // Don't take items when validating task start + [MarshalAs(UnmanagedType.U1)] public bool m_bItemNotTakeOff; // 是否绝对时间 // Whether absolute time + [MarshalAs(UnmanagedType.U1)] public bool m_bAbsTime; // 时间段个数 // Number of time periods @@ -61,42 +66,54 @@ namespace PerfectWorld.Scripts.Task public int m_lPeriodLimit; // 选择单个子任务执行 // Execute single subtask + [MarshalAs(UnmanagedType.U1)] public bool m_bChooseOne; // 随机旋转单个子任务执行 // Randomly rotate single subtask execution + [MarshalAs(UnmanagedType.U1)] public bool m_bRandOne; // 子任务是否有顺序 // Whether subtasks have order + [MarshalAs(UnmanagedType.U1)] public bool m_bExeChildInOrder; // 失败后是否认为父任务也失败 // Whether parent task fails when subtask fails + [MarshalAs(UnmanagedType.U1)] public bool m_bParentAlsoFail; // 子任务成功后父任务成功 // Parent task succeeds when subtask succeeds + [MarshalAs(UnmanagedType.U1)] public bool m_bParentAlsoSucc; // 能否放弃此任务 // Whether task can be abandoned + [MarshalAs(UnmanagedType.U1)] public bool m_bCanGiveUp; // 是否可重复完成 // Whether task can be repeated + [MarshalAs(UnmanagedType.U1)] public bool m_bCanRedo; // 失败后是否可重新完成 // Whether task can be redone after failure + [MarshalAs(UnmanagedType.U1)] public bool m_bCanRedoAfterFailure; // 放弃清空任务 // Clear task when abandoned + [MarshalAs(UnmanagedType.U1)] public bool m_bClearAsGiveUp; // 是否需要记录 // Whether recording is needed + [MarshalAs(UnmanagedType.U1)] public bool m_bNeedRecord; // 玩家被杀死是否认为失败 // Whether task fails when player dies + [MarshalAs(UnmanagedType.U1)] public bool m_bFailAsPlayerDie; // 接受者上限 // Maximum number of receivers public uint m_ulMaxReceiver; // 发放区域 // Distribution area + [MarshalAs(UnmanagedType.U1)] public bool m_bDelvInZone; public uint m_ulDelvWorld; public uint m_ulDelvRegionCnt; @@ -105,6 +122,7 @@ namespace PerfectWorld.Scripts.Task public Task_Region[] m_pDelvRegion; // 进入区域任务失败 // Task fails when entering region + [MarshalAs(UnmanagedType.U1)] public bool m_bEnterRegionFail; public uint m_ulEnterRegionWorld; public uint m_ulEnterRegionCnt; @@ -113,6 +131,7 @@ namespace PerfectWorld.Scripts.Task public Task_Region[] m_pEnterRegion; // 离开区域任务失败 // Task fails when leaving region + [MarshalAs(UnmanagedType.U1)] public bool m_bLeaveRegionFail; public uint m_ulLeaveRegionWorld; public uint m_ulLeaveRegionCnt; @@ -121,40 +140,51 @@ namespace PerfectWorld.Scripts.Task public Task_Region[] m_pLeaveRegion; // 离开阵营失败 // Fails when leaving force + [MarshalAs(UnmanagedType.U1)] public bool m_bLeaveForceFail; // 传送到特定点 // Teleport to specific point + [MarshalAs(UnmanagedType.U1)] public bool m_bTransTo; public uint m_ulTransWldId; public ZONE_VERT m_TransPt; // Monster controller public long m_lMonsCtrl; + [MarshalAs(UnmanagedType.U1)] public bool m_bTrigCtrl; // Auto trigger when conditions are met + [MarshalAs(UnmanagedType.U1)] public bool m_bAutoDeliver; // Whether to display in exclusive UI + [MarshalAs(UnmanagedType.U1)] public bool m_bDisplayInExclusiveUI; + [MarshalAs(UnmanagedType.U1)] public bool m_bReadyToNotifyServer; // Whether used in token shop + [MarshalAs(UnmanagedType.U1)] public bool m_bUsedInTokenShop; // Death trigger + [MarshalAs(UnmanagedType.U1)] public bool m_bDeathTrig; // Whether clear all acquired items + [MarshalAs(UnmanagedType.U1)] public bool m_bClearAcquired; // Recommended level public uint m_ulSuitableLevel; // Whether to show prompt + [MarshalAs(UnmanagedType.U1)] public bool m_bShowPrompt; // Whether it is a key task + [MarshalAs(UnmanagedType.U1)] public bool m_bKeyTask; // Delivery NPC @@ -164,15 +194,19 @@ namespace PerfectWorld.Scripts.Task public uint m_ulAwardNPC; // Whether it is a skill task + [MarshalAs(UnmanagedType.U1)] public bool m_bSkillTask; // Whether can be searched + [MarshalAs(UnmanagedType.U1)] public bool m_bCanSeekOut; // Whether show direction + [MarshalAs(UnmanagedType.U1)] public bool m_bShowDirection; // Marriage + [MarshalAs(UnmanagedType.U1)] public bool m_bMarriage; // Change global key/value @@ -188,27 +222,34 @@ namespace PerfectWorld.Scripts.Task public bool[] m_pbChangeType; // Fail on scene switch + [MarshalAs(UnmanagedType.U1)] public bool m_bSwitchSceneFail; // Hidden task + [MarshalAs(UnmanagedType.U1)] public bool m_bHidden; // Whether deliver skill + [MarshalAs(UnmanagedType.U1)] public bool m_bDeliverySkill; public int m_iDeliveredSkillID; public int m_iDeliveredSkillLevel; // Whether show task completion effect + [MarshalAs(UnmanagedType.U1)] public bool m_bShowGfxFinished; // Whether change player ranking in PQ + [MarshalAs(UnmanagedType.U1)] public bool m_bChangePQRanking; // Compare delivery items with player inventory slots + [MarshalAs(UnmanagedType.U1)] public bool m_bCompareItemAndInventory; public uint m_ulInventorySlotNum; // PQ Task related // PQ任务相关 + [MarshalAs(UnmanagedType.U1)] 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)] @@ -218,7 +259,9 @@ namespace PerfectWorld.Scripts.Task [NonSerialized] public TASK_EXPRESSION[,] m_pPQExpArr; // PQ expression arrays + [MarshalAs(UnmanagedType.U1)] public bool m_bPQSubTask; // Whether it is a PQ subtask // 是否PQ子任务 + [MarshalAs(UnmanagedType.U1)] public bool m_bClearContrib; // Clear contribution when task starts // 任务开始时清空贡献度 public uint m_ulMonsterContribCnt; // Number of monster types // 怪物种类数量 // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] @@ -227,44 +270,61 @@ namespace PerfectWorld.Scripts.Task // Account Task related // 账号任务相关 public int m_iPremNeedRecordTasksNum; // Number of completed record tasks // 记录完成结果任务完成个数 + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByNeedRecordTasksNum; // Show by number of needed record tasks public int m_iPremiseFactionContrib; // Faction contribution // 帮派贡献度 + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByFactionContrib; // Show by faction contribution + [MarshalAs(UnmanagedType.U1)] public bool m_bAccountTaskLimit; // Whether account limits completion times // 是否账号限制完成次数 + [MarshalAs(UnmanagedType.U1)] public bool m_bRoleTaskLimit; // Whether role limits completion times // 是否角色限制完成次数 public uint m_ulAccountTaskLimitCnt; // Account task limit count (deprecated) // 账号限制完成次数,废弃使用了 + [MarshalAs(UnmanagedType.U1)] public bool m_bLeaveFactionFail; // Fail when leaving faction + [MarshalAs(UnmanagedType.U1)] public bool m_bNotIncCntWhenFailed; // Don't increase count when failed // 是否失败时不增加完成次数 + [MarshalAs(UnmanagedType.U1)] public bool m_bNotClearItemWhenFailed; // Don't clear items when failed // 任务失败时不收取任务要求的物品 + [MarshalAs(UnmanagedType.U1)] public bool m_bDisplayInTitleTaskUI; // Show in title task UI // 是否显示在称号任务界面里 /* 开启条件 */ /* Opening conditions */ // 变身状态 // Transformation state public byte m_ucPremiseTransformedForm; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByTransformed; // 等级条件 // Level conditions public uint m_ulPremise_Lev_Min; public uint m_ulPremise_Lev_Max; public uint m_bPremCheckMaxHistoryLevel; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByLev; // 转生次数 // Reincarnation times + [MarshalAs(UnmanagedType.U1)] public bool m_bPremCheckReincarnation; public uint m_ulPremReincarnationMin; public uint m_ulPremReincarnationMax; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByReincarnation; // 境界 // Realm level + [MarshalAs(UnmanagedType.U1)] public bool m_bPremCheckRealmLevel; public uint m_ulPremRealmLevelMin; public uint m_ulPremRealmLevelMax; + [MarshalAs(UnmanagedType.U1)] public bool m_bPremCheckRealmExpFull; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByRealmLevel; // 所需道具 // Required items public uint m_ulPremItems; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] [NonSerialized] public ITEM_WANTED[] m_PremItems; //[MAX_ITEM_WANTED]; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByItems; + [MarshalAs(UnmanagedType.U1)] public bool m_bPremItemsAnyOne; // 发放道具 // Given items public uint m_ulGivenItems; @@ -275,50 +335,66 @@ namespace PerfectWorld.Scripts.Task public ITEM_WANTED[] m_GivenItems; //[MAX_ITEM_WANTED]; // 押金 // Deposit public uint m_ulPremise_Deposit; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByDeposit; // 声望 // Reputation public long m_lPremise_Reputation; public long m_lPremise_RepuMax; + [MarshalAs(UnmanagedType.U1)] 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; + [MarshalAs(UnmanagedType.U1)] 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; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByPeriod; // 帮派 // Faction public uint m_ulPremise_Faction; public int m_iPremise_FactionRole; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByFaction; // 性别 // Gender public uint m_ulGender; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByGender; // 职业限制 // Occupation restrictions public uint m_ulOccupations; [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_OCCUPATIONS)] public uint[] m_Occupations; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByOccup; // 夫妻 // Spouse + [MarshalAs(UnmanagedType.U1)] public bool m_bPremise_Spouse; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowBySpouse; + [MarshalAs(UnmanagedType.U1)] public bool m_bPremiseWeddingOwner; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByWeddingOwner; // GM + [MarshalAs(UnmanagedType.U1)] public bool m_bGM; // 完美神盾用户 // Perfect Shield user + [MarshalAs(UnmanagedType.U1)] public bool m_bShieldUser; // 账号累计充值金额(下限&上限) // Account accumulated recharge amount (lower & upper limit) + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByRMB; public uint m_ulPremRMBMin; public uint m_ulPremRMBMax; // 角色相关时间 // Character-related time + [MarshalAs(UnmanagedType.U1)] public bool m_bCharTime; + [MarshalAs(UnmanagedType.U1)] 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; @@ -341,23 +417,37 @@ namespace PerfectWorld.Scripts.Task public uint m_ulSpecialAward; // 组队信息 // Team information + [MarshalAs(UnmanagedType.U1)] public bool m_bTeamwork; // 组队任务 // Team task + [MarshalAs(UnmanagedType.U1)] public bool m_bRcvByTeam; // 必须组队接收 // Must be in team to receive + [MarshalAs(UnmanagedType.U1)] public bool m_bSharedTask; // 新队员分享任务 // New team members share tasks + [MarshalAs(UnmanagedType.U1)] public bool m_bSharedAchieved; // 分享杀怪、物品数量 // Share kill counts and item counts + [MarshalAs(UnmanagedType.U1)] public bool m_bCheckTeammate; // 检查队友位置 // Check teammate positions public float m_fTeammateDist; // 队友距离平方值 // Square of teammate distance + [MarshalAs(UnmanagedType.U1)] public bool m_bAllFail; // 任意队员失败则全部失败 // Any member fails, all fail + [MarshalAs(UnmanagedType.U1)] public bool m_bCapFail; // 队长失败则全部失败 // Leader fails, all fail + [MarshalAs(UnmanagedType.U1)] public bool m_bCapSucc; // 队长成功则全队成功 // Leader succeeds, all succeed public float m_fSuccDist; // 成功时队员的距离 // Member distance for success + [MarshalAs(UnmanagedType.U1)] public bool m_bDismAsSelfFail; // 队员离队自身失败 // Member leaves team fails itself + [MarshalAs(UnmanagedType.U1)] public bool m_bRcvChckMem; // 接任务时检查队员位置 // Check member positions when receiving task public float m_fRcvMemDist; // 接任务时队员距离平方值 // Square of member distance when receiving task + [MarshalAs(UnmanagedType.U1)] public bool m_bCntByMemPos; // 队员在有效范围内杀怪有效 // Members in valid range for kill counts public float m_fCntMemDist; // 队员有效的范围 // Valid range for members + [MarshalAs(UnmanagedType.U1)] public bool m_bAllSucc; // 任意队员成功则全部成功 // Any member succeeds, all succeed + [MarshalAs(UnmanagedType.U1)] public bool m_bCoupleOnly; // 队长队员必须为夫妻 // Leader and member must be spouses + [MarshalAs(UnmanagedType.U1)] public bool m_bDistinguishedOcc; // 队伍中不允许有相同的职业 // No same occupations allowed in team // 队伍成员需求 // Team member requirements @@ -365,47 +455,64 @@ namespace PerfectWorld.Scripts.Task // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] [NonSerialized] public TEAM_MEM_WANTED[] m_TeamMemsWanted; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByTeam; // 前提全局key/value // Premise global key/value + [MarshalAs(UnmanagedType.U1)] public bool m_bPremNeedComp; public int m_nPremExp1AndOrExp2; public COMPARE_KEY_VALUE m_Prem1KeyValue; public COMPARE_KEY_VALUE m_Prem2KeyValue; + [MarshalAs(UnmanagedType.U1)] public bool m_bPremCheckForce; public int m_iPremForce; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByForce; public int m_iPremForceReputation; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByForceReputation; public int m_iPremForceContribution; // 扣除战功 // Deduct military merit + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByForceContribution; public int m_iPremForceExp; // 经验兑换 // Experience exchange + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByForceExp; public int m_iPremForceSP; // 元神兑换 // Spirit exchange + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByForceSP; public int m_iPremForceActivityLevel; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByForceActivityLevel; + [MarshalAs(UnmanagedType.U1)] public bool m_bPremIsKing; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByKing; + [MarshalAs(UnmanagedType.U1)] public bool m_bPremNotInTeam; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByNotInTeam; public uint m_iPremTitleNumTotal; public uint m_iPremTitleNumRequired; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] [NonSerialized] public int[] m_PremTitles; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByTitle; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public int[] m_iPremHistoryStageIndex; // 历史阶段 // Historical stage + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByHistoryStage; public uint m_ulPremGeneralCardCount; // 收集的卡牌数量 // Number of collected cards + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByGeneralCard; public int m_iPremGeneralCardRank; // 要求某品阶的卡牌数量 // Required number of cards of a certain rank public uint m_ulPremGeneralCardRankCount; + [MarshalAs(UnmanagedType.U1)] public bool m_bShowByGeneralCardRank; /* 任务完成的方式及条件 */ /* Task completion methods and conditions */ @@ -474,6 +581,7 @@ namespace PerfectWorld.Scripts.Task public uint m_ulLeaveSiteId; // 完成全局key/value // Complete global key/value + [MarshalAs(UnmanagedType.U1)] public bool m_bFinNeedComp; public int m_nFinExp1AndOrExp2; public COMPARE_KEY_VALUE m_Fin1KeyValue; @@ -509,30 +617,30 @@ namespace PerfectWorld.Scripts.Task 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; + 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; + 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; + 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 AWARD_ITEMS_SCALE m_AwByItems_S; public uint m_AwByItems_S_ptr; [NonSerialized] - // public AWARD_ITEMS_SCALE m_AwByItems_F; + public AWARD_ITEMS_SCALE m_AwByItems_F; public uint m_AwByItems_F_ptr; /* 层次结构 */ /* Hierarchy structure */ @@ -542,8 +650,10 @@ namespace PerfectWorld.Scripts.Task public uint m_ulFirstChild; /* 库任务相关 */ /* Library task related */ + [MarshalAs(UnmanagedType.U1)] public bool m_bIsLibraryTask; public float m_fLibraryTasksProbability; + [MarshalAs(UnmanagedType.U1)] public bool m_bIsUniqueStorageTask; public int m_iWorldContribution; // 世界贡献度要求 // World contribution requirement } diff --git a/Assets/Scripts/Task/ATaskTemplMan.cs b/Assets/Scripts/Task/ATaskTemplMan.cs index 34c8bfb9e3..a483cbef2e 100644 --- a/Assets/Scripts/Task/ATaskTemplMan.cs +++ b/Assets/Scripts/Task/ATaskTemplMan.cs @@ -70,6 +70,7 @@ namespace PerfectWorld.Scripts.Task // read File and prepare offset array before loading tasks pOffs = AAssit.ReadArrayFromBinary(fs, (int)tph.item_count, ref readBytes); + //Debug.Log((int)tph.item_count); //BMLogger.Log($" [MH] Task File Lenght: {fs.Length}"); for (int i = 1; i < 2; i++) //TODO: tph.item_count { @@ -79,14 +80,15 @@ namespace PerfectWorld.Scripts.Task ATaskTempl pTempl = new ATaskTempl(); g_ulNewCount++; - + + Debug.Log($"Task Index {i}: Attempting to load task template..."); if (!pTempl.LoadFromBinFile(fs)) { CECTaskInterface.WriteLog(0, (int)pTempl.m_FixedData.m_ID, 0, "Cant Load Task"); // LOG_DELETE(pTempl); continue; } - + AddOneTaskTempl(pTempl); // TaskInterface::WriteLog(0, pTempl->m_ID, 2, "LoadTask"); } diff --git a/Assets/Scripts/Task/AWARD_DATA.cs b/Assets/Scripts/Task/AWARD_DATA.cs new file mode 100644 index 0000000000..d1e3bf125e --- /dev/null +++ b/Assets/Scripts/Task/AWARD_DATA.cs @@ -0,0 +1,565 @@ +using System; +using System.Runtime.InteropServices; + +namespace PerfectWorld.Scripts.Task +{ + [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 + [MarshalAs(UnmanagedType.U1)] + 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; + [MarshalAs(UnmanagedType.U1)] + public bool m_bTrigCtrl; + [MarshalAs(UnmanagedType.U1)] + public bool m_bUseLevCo; + [MarshalAs(UnmanagedType.U1)] + public bool m_bDivorce; + [MarshalAs(UnmanagedType.U1)] + 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; + [MarshalAs(UnmanagedType.U1)] + public bool m_bAwardDeath; + [MarshalAs(UnmanagedType.U1)] + public bool m_bAwardDeathWithLoss; + public uint m_ulDividend; // 鸿利值 // Dividend value + + [MarshalAs(UnmanagedType.U1)] + 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 + [MarshalAs(UnmanagedType.U1)] + 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 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(); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Task/AWARD_DATA.cs.meta b/Assets/Scripts/Task/AWARD_DATA.cs.meta new file mode 100644 index 0000000000..04c9ed66a4 --- /dev/null +++ b/Assets/Scripts/Task/AWARD_DATA.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cd2f263c046d4f4299b89979d2438084 +timeCreated: 1761826313 \ No newline at end of file diff --git a/Assets/Scripts/Task/AWARD_ITEMS_CAND.cs b/Assets/Scripts/Task/AWARD_ITEMS_CAND.cs new file mode 100644 index 0000000000..751f5a638a --- /dev/null +++ b/Assets/Scripts/Task/AWARD_ITEMS_CAND.cs @@ -0,0 +1,108 @@ +using System.Runtime.InteropServices; + +namespace PerfectWorld.Scripts.Task +{ + [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; + [MarshalAs(UnmanagedType.U1)] + 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(); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Task/AWARD_ITEMS_CAND.cs.meta b/Assets/Scripts/Task/AWARD_ITEMS_CAND.cs.meta new file mode 100644 index 0000000000..fd9f5cba28 --- /dev/null +++ b/Assets/Scripts/Task/AWARD_ITEMS_CAND.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e4085dad1f98431ab03af71a8a2cf4e8 +timeCreated: 1761826345 \ No newline at end of file diff --git a/Assets/Scripts/Task/SizeTest.cs b/Assets/Scripts/Task/SizeTest.cs new file mode 100644 index 0000000000..40b84820dc --- /dev/null +++ b/Assets/Scripts/Task/SizeTest.cs @@ -0,0 +1,27 @@ +using System.Runtime.InteropServices; +using UnityEngine; + +public class SizeTest : MonoBehaviour +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct TestStruct + { + public int intValue; + public float floatValue; + [MarshalAs(UnmanagedType.U1)] + public bool byteValue; + + + } + + [ContextMenu("Test Size")] + void TestSize() + { + TestStruct q = new(); + + var size = Marshal.SizeOf(typeof(TestStruct)); + // byte[] data = new byte[Marshal.SizeOf(typeof(TestStruct))]; + // q = Marshal.PtrToStructure(); + Debug.Log("Size of TestStruct: " + size); + } +} diff --git a/Assets/Scripts/Task/SizeTest.cs.meta b/Assets/Scripts/Task/SizeTest.cs.meta new file mode 100644 index 0000000000..850662d59d --- /dev/null +++ b/Assets/Scripts/Task/SizeTest.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: df0da79040b03460fa770600fdc054b3 \ No newline at end of file diff --git a/Assets/Scripts/Task/TaskTempl.cs b/Assets/Scripts/Task/TaskTempl.cs index c5cf01b117..533c8637b4 100644 --- a/Assets/Scripts/Task/TaskTempl.cs +++ b/Assets/Scripts/Task/TaskTempl.cs @@ -4,12 +4,14 @@ using System.Runtime.InteropServices; using System; using BrewMonster; using ModelRenderer.Scripts.Common; +using UnityEngine.UIElements; namespace PerfectWorld.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; @@ -307,8 +309,10 @@ namespace PerfectWorld.Scripts.Task 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 @@ -329,6 +333,8 @@ namespace PerfectWorld.Scripts.Task 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; @@ -341,6 +347,13 @@ namespace PerfectWorld.Scripts.Task 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); + } + } [StructLayout(LayoutKind.Sequential, Pack = 1)] @@ -417,8 +430,10 @@ namespace PerfectWorld.Scripts.Task 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; @@ -544,6 +559,7 @@ namespace PerfectWorld.Scripts.Task [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)] @@ -715,6 +731,7 @@ namespace PerfectWorld.Scripts.Task public uint m_ulLevel; public uint m_ulOccupation; public int m_iForce; + [MarshalAs(UnmanagedType.U1)] public bool m_bMale; } @@ -859,110 +876,6 @@ namespace PerfectWorld.Scripts.Task } - - [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 { @@ -1188,559 +1101,6 @@ namespace PerfectWorld.Scripts.Task } } - [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 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 { @@ -1861,8 +1221,15 @@ namespace PerfectWorld.Scripts.Task public ATaskTempl m_pNextSibling; public ATaskTempl m_pFirstChild; - const int MAX_TASK_NAME_LEN = 30; + 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 byte m_uValidCount; public bool LoadFromBinFile(FileStream fp) @@ -1874,7 +1241,7 @@ namespace PerfectWorld.Scripts.Task private void LoadBinary(FileStream fp) { LoadFixedDataFromBinFile(fp); - // LoadDescriptionBin(fp); + LoadDescriptionBin(fp); // LoadTributeBin(fp); //# ifndef _TASK_CLIENT @@ -1914,6 +1281,9 @@ namespace PerfectWorld.Scripts.Task // SynchID(); //return true; } + + #region LoadFixedDataFromBinFile Handle + private bool LoadFixedDataFromBinFile(FileStream fp) { // for (int j = 1; j <= 20; j++) @@ -1925,7 +1295,6 @@ namespace PerfectWorld.Scripts.Task ConvertFixedData(fp, 1); return true; } - public void convert_txt(char[] buffer, int len, char code) { if (buffer == null) return; @@ -1949,7 +1318,7 @@ namespace PerfectWorld.Scripts.Task buffer[i] = (ushort)(buffer[i] ^ code); } } - + private string pointerLog = ""; private void ConvertFixedData(FileStream fp, int x2) { long readBytes = 0; @@ -1957,8 +1326,11 @@ namespace PerfectWorld.Scripts.Task ATaskTemplFixedData fixedData = new ATaskTemplFixedData(); string logContent = ""; + var originalPos = fp.Position; + pointerLog += $" Berfore Read m_ID Position: {fp.Position}\n"; + // Task ID fixedData.m_ID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // unsigned long m_ID; logContent += $"m_ID: {fixedData.m_ID} \n"; @@ -2913,10 +2285,18 @@ namespace PerfectWorld.Scripts.Task fixedData.m_iWorldContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes); logContent += $"m_iWorldContribution: {fixedData.m_iWorldContribution}\n\n"; - //ConvertPointersOfFixedData(fp, ref fixedData, ref readBytes); + 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); + + BMLogger.Log($"---- Pointer Log ---- \n {pointerLog} "); + + m_FixedData = fixedData; return; } @@ -3075,7 +2455,6 @@ namespace PerfectWorld.Scripts.Task 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++) { @@ -3089,7 +2468,7 @@ namespace PerfectWorld.Scripts.Task logContent += $"m_MonstersContrib: {fixedData.m_MonstersContrib}\n"; } - // version 80: delivery regions + // C++ lines 3879 - 3890 if (fixedData.m_ulDelvRegionCnt > 0) { fixedData.m_pDelvRegion = new Task_Region[fixedData.m_ulDelvRegionCnt]; @@ -3107,21 +2486,775 @@ namespace PerfectWorld.Scripts.Task logContent += $"m_pDelvRegion: {fixedData.m_pDelvRegion}\n"; } - + // C++ lines 3891-3902: enter regions if (fixedData.m_ulEnterRegionCnt > 0) { fixedData.m_pEnterRegion = new Task_Region[fixedData.m_ulEnterRegionCnt]; + string eLog = ""; + for (int i = 0; i < fixedData.m_ulEnterRegionCnt; i++) + { + fixedData.m_pEnterRegion[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + eLog += $" {i} = (RegionId:{fixedData.m_pEnterRegion[i].GetLog()}) || "; + } + + logContent += $"m_pEnterRegion: {eLog}\n"; } else { fixedData.m_pEnterRegion = null; + logContent += $"m_pEnterRegion: {fixedData.m_pEnterRegion}\n"; } + // C++ lines 3903-3914: leave regions + if (fixedData.m_ulLeaveRegionCnt > 0) + { + fixedData.m_pLeaveRegion = new Task_Region[fixedData.m_ulLeaveRegionCnt]; + string lLog = ""; + for (int i = 0; i < fixedData.m_ulLeaveRegionCnt; i++) + { + fixedData.m_pLeaveRegion[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + lLog += $" {i} = (RegionId:{fixedData.m_pLeaveRegion[i].GetLog()}) || "; + } + logContent += $"m_pLeaveRegion: {lLog}\n"; + } + else + { + fixedData.m_pLeaveRegion = null; + logContent += $"m_pLeaveRegion: {fixedData.m_pLeaveRegion}\n"; + } + + // C++ lines 3916-3927: premise items + if (fixedData.m_ulPremItems > 0) + { + fixedData.m_PremItems = new ITEM_WANTED[fixedData.m_ulPremItems]; + string premLog = ""; + for (int i = 0; i < fixedData.m_ulPremItems; i++) + { + fixedData.m_PremItems[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + premLog += $" {i} = (Item:{fixedData.m_PremItems[i].m_ulItemTemplId}, Cmn:{fixedData.m_PremItems[i].m_bCommonItem}, Num:{fixedData.m_PremItems[i].m_ulItemNum}) || "; + } + logContent += $"m_PremItems: {premLog}\n"; + } + else + { + fixedData.m_PremItems = null; + logContent += $"m_PremItems: {fixedData.m_PremItems}\n"; + } + + // C++ lines 3929-3945: given items and counts + fixedData.m_ulGivenCmnCount = 0; + fixedData.m_ulGivenTskCount = 0; + if (fixedData.m_ulGivenItems > 0) + { + fixedData.m_GivenItems = new ITEM_WANTED[fixedData.m_ulGivenItems]; + string givenLog = ""; + for (int i = 0; i < fixedData.m_ulGivenItems; i++) + { + fixedData.m_GivenItems[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + if (fixedData.m_GivenItems[i].m_bCommonItem) fixedData.m_ulGivenCmnCount++; + else fixedData.m_ulGivenTskCount++; + givenLog += $" {i} = (Item:{fixedData.m_GivenItems[i].m_ulItemTemplId}, Cmn:{fixedData.m_GivenItems[i].m_bCommonItem}, Num:{fixedData.m_GivenItems[i].m_ulItemNum}) || "; + } + logContent += $"m_GivenItems: {givenLog}\n"; + logContent += $"m_ulGivenCmnCount: {fixedData.m_ulGivenCmnCount}, m_ulGivenTskCount: {fixedData.m_ulGivenTskCount}\n"; + } + else + { + fixedData.m_GivenItems = null; + logContent += $"m_GivenItems: {fixedData.m_GivenItems}\n"; + } + + // C++ lines 3947-3960: team members wanted + if (fixedData.m_bTeamwork) + { + if (fixedData.m_ulTeamMemsWanted > 0) + { + fixedData.m_TeamMemsWanted = new TEAM_MEM_WANTED[fixedData.m_ulTeamMemsWanted]; + string tmwLog = ""; + for (int i = 0; i < fixedData.m_ulTeamMemsWanted; i++) + { + fixedData.m_TeamMemsWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + var v = fixedData.m_TeamMemsWanted[i]; + tmwLog += $" {i} = (Lvl:{v.m_ulLevelMin}-{v.m_ulLevelMax}, Race:{v.m_ulRace}, Occup:{v.m_ulOccupation}, Gender:{v.m_ulGender}, Cnt:{v.m_ulMinCount}-{v.m_ulMaxCount}, Task:{v.m_ulTask}, Force:{v.m_iForce}) || "; + } + logContent += $"m_TeamMemsWanted: {tmwLog}\n"; + } + else + { + fixedData.m_TeamMemsWanted = null; + logContent += $"m_TeamMemsWanted: {fixedData.m_TeamMemsWanted}\n"; + } + } + + // C++ lines 3961-3969: premise titles + if (fixedData.m_iPremTitleNumTotal > 0) + { + fixedData.m_PremTitles = new int[fixedData.m_iPremTitleNumTotal]; + string ptLog = ""; + for (int i = 0; i < fixedData.m_iPremTitleNumTotal; i++) + { + fixedData.m_PremTitles[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + ptLog += $" {i} = {fixedData.m_PremTitles[i]} || "; + } + logContent += $"m_PremTitles: {ptLog}\n"; + } + else + { + fixedData.m_PremTitles = null; + logContent += $"m_PremTitles: {fixedData.m_PremTitles}\n"; + } + + // C++ lines 3973-3983: monster wanted + if (fixedData.m_ulMonsterWanted > 0) + { + fixedData.m_MonsterWanted = new MONSTER_WANTED[fixedData.m_ulMonsterWanted]; + string mwLog = ""; + for (int i = 0; i < fixedData.m_ulMonsterWanted; i++) + { + fixedData.m_MonsterWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + mwLog += $" {i} = (Monster:{fixedData.m_MonsterWanted[i].m_ulMonsterTemplId}, Num:{fixedData.m_MonsterWanted[i].m_ulMonsterNum}) || "; + } + logContent += $"m_MonsterWanted: {mwLog}\n"; + } + else + { + fixedData.m_MonsterWanted = null; + logContent += $"m_MonsterWanted: {fixedData.m_MonsterWanted}\n"; + } + + // C++ lines 3985-3994: player wanted + if (fixedData.m_ulPlayerWanted > 0) + { + fixedData.m_PlayerWanted = new PLAYER_WANTED[fixedData.m_ulPlayerWanted]; + string pwLog = ""; + for (int i = 0; i < fixedData.m_ulPlayerWanted; i++) + { + fixedData.m_PlayerWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + pwLog += $" {i} = (Tpl:{fixedData.m_PlayerWanted[i].m_ulTemplID}, Cnt:{fixedData.m_PlayerWanted[i].m_ulCount}, Lev:{fixedData.m_PlayerWanted[i].m_ulLevel}) || "; + } + logContent += $"m_PlayerWanted: {pwLog}\n"; + } + else + { + fixedData.m_PlayerWanted = null; + logContent += $"m_PlayerWanted: {fixedData.m_PlayerWanted}\n"; + } + + // C++ lines 3996-4006: items wanted + if (fixedData.m_ulItemsWanted > 0) + { + fixedData.m_ItemsWanted = new ITEM_WANTED[fixedData.m_ulItemsWanted]; + string iwLog = ""; + for (int i = 0; i < fixedData.m_ulItemsWanted; i++) + { + fixedData.m_ItemsWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + iwLog += $" {i} = (Item:{fixedData.m_ItemsWanted[i].m_ulItemTemplId}, Cmn:{fixedData.m_ItemsWanted[i].m_bCommonItem}, Num:{fixedData.m_ItemsWanted[i].m_ulItemNum}) || "; + } + logContent += $"m_ItemsWanted: {iwLog}\n"; + } + else + { + fixedData.m_ItemsWanted = null; + logContent += $"m_ItemsWanted: {fixedData.m_ItemsWanted}\n"; + } + + // C++ lines 4008-4021: expressions to display + if (fixedData.m_ulExpCnt > 0) + { + int rowCount = (int)fixedData.m_ulExpCnt; + int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; + + fixedData.m_pszExp = new byte[rowCount, colCount]; + fixedData.m_pExpArr = new TASK_EXPRESSION[rowCount, colCount]; + + for (int i = 0; i < rowCount; i++) + { + byte[] expBytes = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); + for (int j = 0; j < colCount; j++) + { + fixedData.m_pszExp[i, j] = expBytes[j]; + } + + for (int j = 0; j < colCount; j++) + { + fixedData.m_pExpArr[i, j] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + } + } + 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]; + + string tcLog = ""; + for (int i = 0; i < rowCount; i++) + { + ushort[] row = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); + for (int j = 0; j < colCount; j++) + { + fixedData.m_pTaskChar[i, j] = row[j]; + } + tcLog += $" {i} = (...{colCount} chars) || "; + } + logContent += $"m_pTaskChar: {tcLog}\n"; + } + else + { + logContent += $"m_pTaskChar: {fixedData.m_pTaskChar}\n"; + } + + // C++ lines 4035-4058: reach and leave sites + if (fixedData.m_ulReachSiteCnt > 0) + { + fixedData.m_pReachSite = new Task_Region[fixedData.m_ulReachSiteCnt]; + string rsLog = ""; + for (int i = 0; i < fixedData.m_ulReachSiteCnt; i++) + { + fixedData.m_pReachSite[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + rsLog += $" {i} = (RegionId:{fixedData.m_pReachSite[i].GetLog()}) || "; + } + logContent += $"m_pReachSite: {rsLog}\n"; + } + else + { + fixedData.m_pReachSite = null; + logContent += $"m_pReachSite: {fixedData.m_pReachSite}\n"; + } + + if (fixedData.m_ulLeaveSiteCnt > 0) + { + fixedData.m_pLeaveSite = new Task_Region[fixedData.m_ulLeaveSiteCnt]; + string lsLog = ""; + for (int i = 0; i < fixedData.m_ulLeaveSiteCnt; i++) + { + fixedData.m_pLeaveSite[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + lsLog += $" {i} = (RegionId:{fixedData.m_pLeaveSite[i].GetLog()}) || "; + } + logContent += $"m_pLeaveSite: {lsLog}\n"; + } + else + { + fixedData.m_pLeaveSite = null; + logContent += $"m_pLeaveSite: {fixedData.m_pLeaveSite}\n"; + } BMLogger.LogError($" === Task Pointer Datas {fixedData.m_ID} loaded === \n {logContent} "); + + LoadAwardDataBin(fp, ref fixedData.m_Award_S, TaskTemplConstants._task_templ_cur_version, ref readBytes); + 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(fp, ref readBytes); + + // fread(&ad.m_ulItemId, sizeof(ad.m_ulItemId), 1, fp); + ad.m_ulItemId = AAssit.ReadFromBinaryOf(fp, ref readBytes); + + // fread(ad.m_Counts, sizeof(ad.m_Counts), 1, fp); + ad.m_Counts = new uint[TaskTemplConstants.MAX_AWARD_SCALES]; + // ad.m_Counts = AAssit.ReadArrayFromBinary(fp, ref readBytes); + for (int i=0; i < TaskTemplConstants.MAX_AWARD_SCALES; i++) + { + ad.m_Counts[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + } + + // LOG_DELETE_ARR(ad.m_Awards); + // ad.m_Awards = NULL; + + if (ad.m_ulScales > 0) + { + ad.m_Awards = new AWARD_DATA[ad.m_ulScales]; + for (int i = 0; i < ad.m_ulScales; i++) + { + LoadAwardDataBin(fp, ref ad.m_Awards[i], ulVersion, ref readBytes); + } + } + return true; + } + + private bool LoadAwardDataRatioScale(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(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 = new float[TaskTemplConstants.MAX_AWARD_SCALES]; + // int x = 5; + // ad.m_Ratios = AAssit.ReadArrayFromBinary(fp, ref readBytes,-1,ref x); + // TODO: need to load ad.m_Ratios + fp.Seek(20, SeekOrigin.Current); + + // 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(fp, ref readBytes); + logContent += $"m_ulGoldNum: {ad.m_ulGoldNum} \n"; + + ad.m_ulExp = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulExp: {ad.m_ulExp} \n"; + + ad.m_ulRealmExp = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 境界经验 // Realm experience + logContent += $"m_ulRealmExp: {ad.m_ulRealmExp} \n"; + + ad.m_bExpandRealmLevelMax = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 境界等级10整级时提升境界等级上限 // Increase realm level upper limit + logContent += $"m_bExpandRealmLevelMax: {ad.m_bExpandRealmLevelMax} \n"; + + ad.m_ulNewTask = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulNewTask: {ad.m_ulNewTask} \n"; + ad.m_ulSP = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulSP: {ad.m_ulSP} \n"; + ad.m_lReputation = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_lReputation: {ad.m_lReputation} \n"; + ad.m_ulNewPeriod = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulNewPeriod: {ad.m_ulNewPeriod} \n"; + ad.m_ulNewRelayStation = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulNewRelayStation: {ad.m_ulNewRelayStation} \n"; + ad.m_ulStorehouseSize = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulStorehouseSize: {ad.m_ulStorehouseSize} \n"; + ad.m_ulStorehouseSize2 = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulStorehouseSize2: {ad.m_ulStorehouseSize2} \n"; + ad.m_ulStorehouseSize3 = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulStorehouseSize3: {ad.m_ulStorehouseSize3} \n"; + ad.m_ulStorehouseSize4 = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 账号仓库 // Account warehouse + logContent += $"m_ulStorehouseSize4: {ad.m_ulStorehouseSize4} \n"; + ad.m_lInventorySize = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_lInventorySize: {ad.m_lInventorySize} \n"; + ad.m_ulPetInventorySize = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPetInventorySize: {ad.m_ulPetInventorySize} \n"; + ad.m_ulFuryULimit = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulFuryULimit: {ad.m_ulFuryULimit} \n"; + ad.m_ulTransWldId = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulTransWldId: {ad.m_ulTransWldId} \n"; + ad.m_TransPt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_TransPt: ({ad.m_TransPt.x}, {ad.m_TransPt.y}, {ad.m_TransPt.z}) \n"; + ad.m_lMonsCtrl = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_lMonsCtrl: {ad.m_lMonsCtrl} \n"; + ad.m_bTrigCtrl = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bTrigCtrl: {ad.m_bTrigCtrl} \n"; + ad.m_bUseLevCo = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bUseLevCo: {ad.m_bUseLevCo} \n"; + ad.m_bDivorce = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bDivorce: {ad.m_bDivorce} \n"; + ad.m_bSendMsg = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bSendMsg: {ad.m_bSendMsg} \n"; + ad.m_nMsgChannel = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_nMsgChannel: {ad.m_nMsgChannel} \n"; + + // Candidates and summoned monsters (pointers skipped; content read later by counts if needed) + ad.m_ulCandItems = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulCandItems: {ad.m_ulCandItems} \n"; + fp.Seek(4, SeekOrigin.Current); // C++: AWARD_ITEMS_CAND* m_CandItems; skip pointer address + logContent += $"skip 4 bytes -> AWARD_ITEMS_CAND* m_CandItems \n"; + + ad.m_ulSummonedMonsters = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulSummonedMonsters: {ad.m_ulSummonedMonsters} \n"; + fp.Seek(4, SeekOrigin.Current); // C++: AWARD_MONSTERS_SUMMONED* m_SummonedMonsters; skip pointer address + logContent += $"skip 4 bytes -> AWARD_MONSTERS_SUMMONED* m_SummonedMonsters \n"; + + ad.m_bAwardDeath = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bAwardDeath: {ad.m_bAwardDeath} \n"; + ad.m_bAwardDeathWithLoss = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bAwardDeathWithLoss: {ad.m_bAwardDeathWithLoss} \n"; + ad.m_ulDividend = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 鸿利值 // Dividend value + logContent += $"m_ulDividend: {ad.m_ulDividend} \n"; + + ad.m_bAwardSkill = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 是否奖励技能 // Whether to reward skill + logContent += $"m_bAwardSkill: {ad.m_bAwardSkill} \n"; + ad.m_iAwardSkillID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 技能ID // Skill ID + logContent += $"m_iAwardSkillID: {ad.m_iAwardSkillID} \n"; + ad.m_iAwardSkillLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 技能等级 // Skill level + logContent += $"m_iAwardSkillLevel: {ad.m_iAwardSkillLevel} \n"; + + // PQ task reward + ad.m_ulSpecifyContribTaskID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 指定任务贡献度的任务id // Task ID for specified contribution + logContent += $"m_ulSpecifyContribTaskID: {ad.m_ulSpecifyContribTaskID} \n"; + ad.m_ulSpecifyContribSubTaskID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 指定任务贡献度的子任务ID // Subtask ID for specified contribution + logContent += $"m_ulSpecifyContribSubTaskID: {ad.m_ulSpecifyContribSubTaskID} \n"; + ad.m_ulSpecifyContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 指定任务贡献度 // Specified task contribution + logContent += $"m_ulSpecifyContrib: {ad.m_ulSpecifyContrib} \n"; + + ad.m_ulContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 贡献度 // Contribution + logContent += $"m_ulContrib: {ad.m_ulContrib} \n"; + ad.m_ulRandContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 随机贡献度 // Random contribution + logContent += $"m_ulRandContrib: {ad.m_ulRandContrib} \n"; + ad.m_ulLowestcontrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 最低贡献度 // Minimum contribution + logContent += $"m_ulLowestcontrib: {ad.m_ulLowestcontrib} \n"; + + ad.m_iFactionContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 帮派贡献度 // Faction contribution + logContent += $"m_iFactionContrib: {ad.m_iFactionContrib} \n"; + ad.m_iFactionExpContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iFactionExpContrib: {ad.m_iFactionExpContrib} \n"; + + ad.m_ulPQRankingAwardCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPQRankingAwardCnt: {ad.m_ulPQRankingAwardCnt} \n"; + fp.Seek(4, SeekOrigin.Current); // C++: AWARD_PQ_RANKING* m_PQRankingAward; skip pointer address + logContent += $"skip 4 bytes -> AWARD_PQ_RANKING* m_PQRankingAward \n"; + + // Change global key/value arrays (pointers to basic types) + ad.m_ulChangeKeyCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulChangeKeyCnt: {ad.m_ulChangeKeyCnt} \n"; + fp.Seek(4, SeekOrigin.Current); // C++: long* m_plChangeKey; skip sizeof(long) + fp.Seek(4, SeekOrigin.Current); // C++: long* m_plChangeKeyValue; skip sizeof(long) + fp.Seek(4, SeekOrigin.Current); // C++: bool* m_pbChangeType; skip sizeof(bool) + logContent += $"skip 4 pointers -> m_plChangeKey(4) \n m_plChangeKeyValue(4) \n m_pbChangeType(4) \n"; + + // Modify historical progress + ad.m_ulHistoryChangeCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulHistoryChangeCnt: {ad.m_ulHistoryChangeCnt} \n"; + + fp.Seek(4, SeekOrigin.Current); // C++: long* m_plHistoryChangeKey + fp.Seek(4, SeekOrigin.Current); // C++: long* m_plHistoryChangeKeyValue + fp.Seek(4, SeekOrigin.Current); // C++: bool* m_pbHistoryChangeType + logContent += $"skip pointers -> m_plHistoryChangeKey(4) \n m_plHistoryChangeKeyValue(4) \n m_pbHistoryChangeType(4) \n"; + + // Multiplier + ad.m_bMulti = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bMulti: {ad.m_bMulti} \n"; + ad.m_nNumType = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_nNumType: {ad.m_nNumType} \n"; + ad.m_lNum = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_lNum: {ad.m_lNum} \n"; + + // Display global key/value + ad.m_ulDisplayKeyCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulDisplayKeyCnt: {ad.m_ulDisplayKeyCnt} \n"; + fp.Seek(4, SeekOrigin.Current); // C++: long* m_plDisplayKey + logContent += $"skip 4 bytes -> long* m_plDisplayKey \n"; + + // Display global variable expressions + ad.m_ulExpCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulExpCnt: {ad.m_ulExpCnt} \n"; + fp.Seek(4, SeekOrigin.Current); // C++: char (*m_pszExp)[TASK_AWARD_MAX_DISPLAY_CHAR_LEN] + fp.Seek(4, SeekOrigin.Current); // C++: TASK_EXPRESSION (*m_pExpArr)[TASK_AWARD_MAX_DISPLAY_CHAR_LEN] + logContent += $"skip 4 bytes -> m_pszExp(row ptr) \n"; + logContent += $"skip 4 bytes -> m_pExpArr(row ptr) \n"; + + // Display global variable expression prompt strings + ad.m_ulTaskCharCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulTaskCharCnt: {ad.m_ulTaskCharCnt} \n"; + fp.Seek(4, SeekOrigin.Current); // C++: task_char (*m_pTaskChar)[TASK_AWARD_MAX_DISPLAY_CHAR_LEN] + logContent += $"skip 4 bytes -> task_char (*m_pTaskChar)[LEN] \n"; + + // Force-related + ad.m_iForceContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iForceContribution: {ad.m_iForceContribution} \n"; + ad.m_iForceReputation = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iForceReputation: {ad.m_iForceReputation} \n"; + ad.m_iForceActivity = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iForceActivity: {ad.m_iForceActivity} \n"; + ad.m_iForceSetRepu = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iForceSetRepu: {ad.m_iForceSetRepu} \n"; + + ad.m_iTaskLimit = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iTaskLimit: {ad.m_iTaskLimit} \n"; + ad.m_ulTitleNum = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulTitleNum: {ad.m_ulTitleNum} \n"; + fp.Seek(4, SeekOrigin.Current); // C++: TITLE_AWARD* m_pTitleAward + logContent += $"skip 4 bytes -> TITLE_AWARD* m_pTitleAward \n"; + ad.m_iLeaderShip = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iLeaderShip: {ad.m_iLeaderShip} \n"; + + ad.m_iWorldContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 世界贡献度 // World contribution + logContent += $"m_iWorldContribution: {ad.m_iWorldContribution} \n"; + + logContent += "------ Start Pointer datas of AWARD_DATA ------ \n"; + + // 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"; + + + 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"; + + if (ad.m_ulTitleNum > 0) + { + ad.m_pTitleAward = new TITLE_AWARD[ad.m_ulTitleNum]; + ad.m_pTitleAward = AAssit.ReadArrayFromBinary(fp, ref readBytes); + } + logContent += $" AWARD_DATA.m_pTitleAward : {ad.m_ulTitleNum} elements / {fp.Position} \n"; + + if (ad.m_ulChangeKeyCnt > 0) + { + ad.m_plChangeKey = new int[ad.m_ulChangeKeyCnt]; + ad.m_plChangeKey = AAssit.ReadArrayFromBinary(fp, ref readBytes); + + ad.m_plChangeKeyValue = new int[ad.m_ulChangeKeyCnt]; + ad.m_plChangeKeyValue = AAssit.ReadArrayFromBinary(fp, ref readBytes); + + ad.m_pbChangeType = new bool[ad.m_ulChangeKeyCnt]; + ad.m_pbChangeType = AAssit.ReadArrayFromBinary(fp, 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"; + + if (ad.m_ulHistoryChangeCnt > 0) + { + //fread(&ad.m_plHistoryChangeKey[i], sizeof(long), 1, fp); + ad.m_plHistoryChangeKey = new int[ad.m_ulHistoryChangeCnt]; + ad.m_plHistoryChangeKey = AAssit.ReadArrayFromBinary(fp, ref readBytes); + + //fread(&ad.m_plHistoryChangeKeyValue[i], sizeof(long), 1, fp); + ad.m_plHistoryChangeKeyValue = new int[ad.m_ulHistoryChangeCnt]; + ad.m_plHistoryChangeKeyValue = AAssit.ReadArrayFromBinary(fp, ref readBytes); + + //fread(&ad.m_pbHistoryChangeType[i], sizeof(bool), 1, fp); + ad.m_pbHistoryChangeType = new bool[ad.m_ulHistoryChangeCnt]; + ad.m_pbHistoryChangeType = AAssit.ReadArrayFromBinary(fp, 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"; + + if (ad.m_ulDisplayKeyCnt > 0) + { + ad.m_plDisplayKey = new int[ad.m_ulDisplayKeyCnt]; + ad.m_plDisplayKey = AAssit.ReadArrayFromBinary(fp, ref readBytes); + } + logContent += $" AWARD_DATA.m_plDisplayKey : {ad.m_ulDisplayKeyCnt} elements / {fp.Position} \n"; + + if (ad.m_ulExpCnt > 0) + { + int rowCount = (int)ad.m_ulExpCnt; + int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; + + // 显示全局变量表达式显示字节 // Display bytes for global variable expressions + ad.m_pszExp = new byte[rowCount * colCount]; + ad.m_pExpArr = new TASK_EXPRESSION[rowCount * colCount]; + + for (int row = 0; row < rowCount; row++) + { + byte[] expBytesRow = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); + Buffer.BlockCopy(expBytesRow, 0, ad.m_pszExp, row * colCount, colCount); + for (int col = 0; col < colCount; col++) + { + ad.m_pExpArr[row * colCount + col] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + } + } + } + logContent += $" AWARD_DATA.m_pszExp and m_pExpArr : {ad.m_ulExpCnt} rows / {fp.Position} \n"; + + if (ad.m_ulTaskCharCnt > 0) + { + int rowCount = (int)ad.m_ulTaskCharCnt; + int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; + ad.m_pTaskChar = new ushort[rowCount * colCount]; + for (int row = 0; row < rowCount; row++) + { + ushort[] rowChars = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); + Buffer.BlockCopy(rowChars, 0, ad.m_pTaskChar, row * colCount * 2, colCount * 2); + } + } + logContent += $" AWARD_DATA.m_pTaskChar : {ad.m_ulTaskCharCnt} rows / {fp.Position} \n"; + + 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(fp, ref readBytes); + ic.m_bRandChoose = AAssit.ReadFromBinaryOf(fp, ref readBytes); + + pointerLog += $" After Read AWARD_ITEMS_CAND.m_bRandChoose : {fp.Position}\n"; + + ic.m_ulAwardItems = AAssit.ReadFromBinaryOf(fp, ref readBytes); + + pointerLog += $" After Read AWARD_ITEMS_CAND.m_ulAwardItems : {fp.Position}\n"; + + Debug.Log( $"ic.m_bRandChoose : {ic.m_bRandChoose} ic.m_ulAwardItems : {ic.m_ulAwardItems}"); + + + if (ic.m_ulAwardItems > 0) + { + ic.m_AwardItems = new ITEM_WANTED[ic.m_ulAwardItems]; + for (int i = 0; i < ic.m_ulAwardItems; i++) + { + ic.m_AwardItems[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + ITEM_WANTED iw = ic.m_AwardItems[i]; + + if (iw.m_bCommonItem) ic.m_ulAwardCmnItems++; + else ic.m_ulAwardTskItems++; + + valueLog += $" {i} = (Item:{iw.m_ulItemTemplId}, Cmn:{iw.m_bCommonItem}, Num:{iw.m_ulItemNum}) || "; + } + } + else ic.m_AwardItems = null; + + pointerLog += $" After Read m_ulAwardItems : {fp.Position}\n"; + + //BMLogger.Log($"AWARD_ITEMS_CAND.m_AwardItems[] : {valueLog}" ); + + return true; + } + + private bool LoadAwardMonstersBin(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(fp, ref readBytes); + ms.m_ulSummonRadius = AAssit.ReadFromBinaryOf(fp, ref readBytes); + ms.m_bDeathDisappear = AAssit.ReadFromBinaryOf(fp, ref readBytes); + + if (ms.m_ulMonsterNum > 0) + { + ms.m_Monsters = new MONSTERS_SUMMONED[ms.m_ulMonsterNum]; + ms.m_Monsters = AAssit.ReadArrayFromBinary(fp, 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(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 = new RANKING_AWARD[pr.m_ulRankingAwardNum]; + pr.m_RankingAward = AAssit.ReadArrayFromBinary(fp, 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(fp, ref readBytes); + // 描述文本(task_char*) // Description text (task_char*) + m_pwstrDescript = new ushort[len + 1]; + m_pwstrDescript[len] = 0; + if (len > 0) + { + // ushort[] tmp = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + // System.Buffer.BlockCopy(tmp, 0, m_pwstrDescript, 0, (int)len * 2); + m_pwstrDescript = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + convert_txt(m_pwstrDescript, (int)len, (char)m_FixedData.m_ID); + } + + valueLog += $" m_pwstrDescript : len = {len} / " + + $"{ ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrDescript) } / " + + $" Pointer = {fp.Position} \n"; + + // OK 文本 // OK text + len = AAssit.ReadFromBinaryOf(fp, ref readBytes); + m_pwstrOkText = new ushort[len + 1]; + m_pwstrOkText[len] = 0; + if (len > 0) + { + ushort[] tmp = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + System.Buffer.BlockCopy(tmp, 0, m_pwstrOkText, 0, (int)len * 2); + convert_txt(m_pwstrOkText, (int)len, (char)m_FixedData.m_ID); + } + + + valueLog += $" m_pwstrOkText : { ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrOkText) } \n"; + + // NO 文本 // No text + len = AAssit.ReadFromBinaryOf(fp, ref readBytes); + m_pwstrNoText = new ushort[len + 1]; + m_pwstrNoText[len] = 0; + if (len > 0) + { + ushort[] tmp = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + System.Buffer.BlockCopy(tmp, 0, m_pwstrNoText, 0, (int)len * 2); + 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; + } + #region convert from c++ to cs // private bool LoadFixedDataFromBinFile(FileStream fp) @@ -3525,17 +3658,7 @@ namespace PerfectWorld.Scripts.Task // LoadAwardDataItemsScale(fp, *m_AwByItems_S, _task_templ_cur_version); // LoadAwardDataItemsScale(fp, *m_AwByItems_F, _task_templ_cur_version); #endregion - - string convert_txt(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++; } }