diff --git a/.cursor/rules/convert-data-rule.mdc b/.cursor/rules/convert-data-rule.mdc new file mode 100644 index 0000000000..06b1d42942 --- /dev/null +++ b/.cursor/rules/convert-data-rule.mdc @@ -0,0 +1,309 @@ +--- +description: Binary data conversion rules when reading C++ binary files in C# +--- + +# Binary Data Conversion Rules (C++ to C#) + +When reading binary data from C++ files using `FileStream`, follow these conversion patterns based on the variable type in the original C++ struct. + +## Important Type Mappings + +- `unsigned long` in C++ → `uint` in C# +- `bool` in C++ → 1 byte (read as `byte` in C#, then convert with `> 0`) +- `wchar_t` on Windows → 2 bytes +- `task_char` → `ushort` +- Pointer size in C++ binary → typically 4 bytes (32-bit) + +**Critical**: When reading binary data, match the original C++ memory layout exactly, accounting for struct packing and alignment. + +## Case 1: Normal Value Type Variables (Primitives) + +**Pattern**: Directly stored scalar values (no arrays, no pointers, no user-defined structs) + +**C++ Examples**: +```cpp +unsigned long m_ID; +bool m_bHasSign; +int m_lAvailFrequency; +float m_fLibraryTasksProbability; +``` + +**C# Conversion**: +```csharp +// Read value and assign to the field +fixedData.m_ID = AAssit.ReadFromBinaryOf(fp, ref readBytes); + +// Special case for bool: read as byte and compare with > 0 +fixedData.m_bHasSign = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; +fixedData.m_bChooseOne = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + +// Other primitive types +fixedData.m_lAvailFrequency = AAssit.ReadFromBinaryOf(fp, ref readBytes); +fixedData.m_fLibraryTasksProbability = AAssit.ReadFromBinaryOf(fp, ref readBytes); +``` + +**Rule**: Use `AAssit.ReadFromBinaryOf(fp, ref readBytes)` where T is the C# equivalent type. + +**Important for bool**: C++ bool is stored as 1 byte in binary files. Always read as `byte` and convert to C# bool using `> 0`: +```csharp +// Correct pattern for bool +fixedData.m_boolField = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; +``` + +--- + +## Case 2: Fixed-Size Arrays (Inline Memory) + +**Pattern**: Arrays with a known constant size defined by a macro or constant + +**C++ Examples**: +```cpp +task_char m_szName[MAX_TASK_NAME_LEN]; // MAX_TASK_NAME_LEN = 30 +char m_tmType[MAX_TIMETABLE_SIZE]; // MAX_TIMETABLE_SIZE = 32 +task_tm m_tmStart[MAX_TIMETABLE_SIZE]; +task_tm m_tmEnd[MAX_TIMETABLE_SIZE]; +``` + +**C# Conversion**: +```csharp +// Read array from binary and assign to the field +fixedData.m_szName = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TASK_NAME_LEN, ref readBytes); +fixedData.m_tmType = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes); +fixedData.m_tmStart = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes); +fixedData.m_tmEnd = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes); +``` + +**Rule**: Use `AAssit.ReadArrayFromBinary(fp, arraySize, ref readBytes)` where: +- `T` is the C# equivalent element type +- `arraySize` is the predefined constant size + +--- + +## Case 3: Pointer to User-Defined Type or String + +**Pattern**: Fields that store only the pointer address, not the actual object/data + +**C++ Examples**: +```cpp +task_char* m_pszSignature; +AWARD_DATA* m_Award_S; +Task_Region* m_pDelvRegion; +ITEM_WANTED* m_PremItems; +``` + +**C# Conversion**: +```csharp +// Skip pointer size (4 bytes for 32-bit pointers) +// The content is not inlined in the struct +fp.Seek(4, SeekOrigin.Current); +``` + +**Rule**: Skip 4 bytes using `fp.Seek(4, SeekOrigin.Current)` because only the pointer address is stored in the binary file, not the actual data. + +**Note**: If the pointed-to data exists separately in the file, it must be read later based on additional logic (e.g., checking a count variable or flag). + +--- + +## Case 4: User-Defined Struct (Inline, Not Pointer) + +**Pattern**: A complete user-defined struct embedded directly in the parent struct + +**C++ Examples**: +```cpp +task_tm m_tmAbsFailTime; // Inline struct +AWARD_DATA m_Award_S; // Inline struct (if not a pointer) +``` + +**C# Conversion**: +```csharp +// Skip the full size of the struct in bytes +// Check the struct's internal members and padding to calculate correct size +fp.Seek(24, SeekOrigin.Current); // Example: sizeof(task_tm) = 24 bytes on Windows/MSVC +``` + +**Rule**: +1. Calculate the exact size of the struct including padding +2. Skip that many bytes using `fp.Seek(structSize, SeekOrigin.Current)` + +**Important**: Do not rely on hardcoded numbers. Calculate the actual struct size considering: +- Size of each member +- Struct packing (`Pack = 1`, `Pack = 4`, etc.) +- Platform-specific alignment rules + +**Alternative**: If you need the data, read the struct directly: +```csharp +fixedData.m_tmAbsFailTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); +``` + +--- + +## Case 5: Pointer to Basic Type (Not 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 +ushort* m_pszSignature; // Pointer to ushort +int* m_plChangeKey; // Pointer to int +bool* m_pbChangeType; // Pointer to bool +float* m_pFloatArray; // Pointer to float +``` + +**C# Conversion**: +```csharp +// Always skip the pointer address (4 bytes in the binary layout) +fp.Seek(4, SeekOrigin.Current); +``` + +**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**: This assumes the source binary was written with 32-bit pointer sizes. If you ever process binaries with 64-bit pointer sizes, adjust accordingly. + +--- + +## Decision Tree + +Use this flowchart to determine which case applies: + +``` +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 4 bytes (pointer address) +│ └── NO +│ ├── Is it an array with predefined size? +│ │ ├── YES → Case 2: Read array using ReadArrayFromBinary +│ │ └── NO +│ │ ├── Is it a user-defined struct (inline)? +│ │ │ ├── YES → Case 4: Skip sizeof(struct) or read struct +│ │ │ └── NO → Case 1: Read value using ReadFromBinaryOf +``` + +--- + +## Common Patterns and Examples + +### Pattern: Conditional Data Reading + +When a field has associated data only if a flag/count is set: + +**C++ Example**: +```cpp +bool m_bHasSign; +task_char* m_pszSignature; // Only has data if m_bHasSign is true + +unsigned long m_ulTimetable; +task_tm* m_tmStart; // Only has data if m_ulTimetable > 0 +``` + +**C# Conversion**: +```csharp +// First read the flag/count (read bool as byte and convert with > 0) +fixedData.m_bHasSign = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + +// Skip the pointer (Case 3) +fp.Seek(4, SeekOrigin.Current); + +// Later, conditionally read the actual data +if (fixedData.m_bHasSign) +{ + fixedData.m_pszSignature = AAssit.ReadArrayFromBinary(fp, MAX_TASK_NAME_LEN, ref readBytes); +} +``` + +### Pattern: String Conversion + +For `task_char` arrays (which are `ushort` arrays in C#): + +```csharp +// Read the array +fixedData.m_szName = AAssit.ReadArrayFromBinary(fp, MAX_TASK_NAME_LEN, ref readBytes); + +// Convert to readable string +TaskTemplUtils.convert_txt(ref fixedData.m_szName, MAX_TASK_NAME_LEN, TaskTemplUtils.uint_to_ushort(fixedData.m_ID)); +string taskName = ByteToStringUtils.UshortArrayToCP936String(fixedData.m_szName); +``` + +--- + +## Reference: AAssit Helper Methods + +From [AAssit.cs](mdc:Assets/PerfectWorld/Scripts/Common/DataProcess/AAssit.cs): + +```csharp +// Read a single value +public static T ReadFromBinaryOf(FileStream fp, ref long readBytes) where T : struct + +// Read an array of values +public static T[] ReadArrayFromBinary(FileStream fp, int count, ref long readBytes) where T : struct +``` + +--- + +## Best Practices + +1. **Always track readBytes**: Pass `ref readBytes` to track how many bytes have been read for debugging +2. **Match C++ layout exactly**: Ensure struct packing in C# matches C++ (`Pack = 1` is common) +3. **Document your assumptions**: Add comments explaining the byte sizes you're skipping +4. **Verify with logs**: Log read values to verify correctness +5. **Check file position**: Use `fp.Position` to verify you're reading from the expected location +6. **Handle platform differences**: Be aware of 32-bit vs 64-bit pointer sizes (though binary files usually use fixed sizes) + +--- + +## Common Mistakes to Avoid + +❌ **Wrong**: Reading bool directly as bool type +```csharp +// C++: bool m_bHasSign +fixedData.m_bHasSign = AAssit.ReadFromBinaryOf(fp, ref readBytes); // Wrong! +``` + +✅ **Correct**: +```csharp +// Read as byte and compare with > 0 +fixedData.m_bHasSign = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // Correct! +``` + +--- + +❌ **Wrong**: Skipping only `sizeof(basic type)` for a pointer in Case 5 +```csharp +// C++: ushort* m_pszSignature +fp.Seek(2, SeekOrigin.Current); // Wrong! Do not skip sizeof(ushort) for pointers +``` + +✅ **Correct**: +```csharp +// Always skip the pointer address (4 bytes) +fp.Seek(4, SeekOrigin.Current); +``` + +--- + +❌ **Wrong**: Reading inline array as a single value +```csharp +// C++: char m_tmType[MAX_TIMETABLE_SIZE] +byte value = AAssit.ReadFromBinaryOf(fp, ref readBytes); // Wrong! +``` + +✅ **Correct**: +```csharp +byte[] values = AAssit.ReadArrayFromBinary(fp, MAX_TIMETABLE_SIZE, ref readBytes); +``` + +--- + +❌ **Wrong**: Not accounting for struct padding +```csharp +// C++: struct with padding +fp.Seek(20, SeekOrigin.Current); // Might be wrong due to padding! +``` + +✅ **Correct**: +```csharp +// Calculate actual size with padding +// Or read the struct directly if needed +fixedData.m_structField = AAssit.ReadFromBinaryOf(fp, ref readBytes); +``` diff --git a/.cursor/rules/cpp-convert-rules.mdc b/.cursor/rules/cpp-convert-rules.mdc new file mode 100644 index 0000000000..2c63fe6fc8 --- /dev/null +++ b/.cursor/rules/cpp-convert-rules.mdc @@ -0,0 +1,13 @@ +--- +alwaysApply: true +--- +When convert cpp to c# +- unsigned long convert to uint +- unsigned char to byte +- task_char to ushort +- Keeps all the naming +- keeps all the original chinese comments. But add a translated English version side by side +- struct has to be public +- struct has to be use [StructLayout(LayoutKind.Sequential, Pack = 1)] +- all field in struct has to be public +- array has to be use [MarshalAs(UnmanagedType.ByValArray, SizeConst = )] to fix the array size diff --git a/.gitignore b/.gitignore index ebac7aaa5a..07da697b9e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ /[Uu]ser[Ss]ettings/ *.log +.DS_Store + # By default unity supports Blender asset imports, *.blend1 blender files do not need to be commited to version control. *.blend1 *.blend1.meta diff --git a/Assets/PerfectWorld/Scene/TaskTest.unity b/Assets/PerfectWorld/Scene/TaskTest.unity new file mode 100644 index 0000000000..0327c382c8 --- /dev/null +++ b/Assets/PerfectWorld/Scene/TaskTest.unity @@ -0,0 +1,170 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 1 + m_PVRFilteringGaussRadiusAO: 1 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1956623781 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1956623783} + - component: {fileID: 1956623782} + m_Layer: 0 + m_Name: TaskTest + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1956623782 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1956623781} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 561ff33122f704147a67d91c42fde5a4, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &1956623783 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1956623781} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 1956623783} diff --git a/Assets/PerfectWorld/Scene/TaskTest.unity.meta b/Assets/PerfectWorld/Scene/TaskTest.unity.meta new file mode 100644 index 0000000000..e21e053ce8 --- /dev/null +++ b/Assets/PerfectWorld/Scene/TaskTest.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 768ce4fda26964eca987fc64bf5bab70 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/PerfectWorld/Scripts/Common/DataProcess/AAssit.cs b/Assets/PerfectWorld/Scripts/Common/DataProcess/AAssit.cs index 6a34d52b94..6b3c96cf66 100644 --- a/Assets/PerfectWorld/Scripts/Common/DataProcess/AAssit.cs +++ b/Assets/PerfectWorld/Scripts/Common/DataProcess/AAssit.cs @@ -15,6 +15,8 @@ public class AAssit } int size = Marshal.SizeOf(typeof(T)); + if (typeof(T) == typeof(bool)) size = 1; // bool is stored as 1 byte + byte[] buffer = new byte[size]; // Read `size` bytes into `buffer[0..size]` @@ -51,7 +53,21 @@ public class AAssit return array; } - public static T[] ReadArrayFromBinary(FileStream stream, ref long readBytes, long fileOffset = -1) + /// + /// Reads an array from a binary stream where the data layout is: + /// [int32 count] followed by count serialized elements of . + /// If >= 0, seeks to that absolute position before + /// reading the count and re-seeks before reading each element. Updates + /// with the total number of bytes consumed. Returns + /// null when the read count is less than or equal to zero. + /// + /// Open readable to read from. + /// Reference accumulator updated with bytes consumed by this method. + /// Optional absolute file position to seek prior to reads; if >= 0 the stream is + /// re-seeked before reading the count and each element. + /// Element type to deserialize. Must be blittable/marshallable via . + /// The populated array when count > 0; otherwise null. + public static T[] ReadArrayPointerFromBinary(FileStream stream, ref long readBytes, long fileOffset = -1) { // seek to the fileOffset if it's >= 0 if (fileOffset >= 0) diff --git a/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs b/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs index 168cad3e10..af29d073f1 100644 --- a/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs +++ b/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs @@ -312,88 +312,88 @@ namespace ModelRenderer.Scripts.GameData long t = AAssit.GetIntFromFileStream(file, ref dwRead); // if(equipment_addon_array.load(file) != 0) return -1; - equipment_addon_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + equipment_addon_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // if(weapon_major_type_array.load(file) != 0) return -1; - weapon_major_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + weapon_major_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // if(weapon_sub_type_array.load(file) != 0) return -1; - weapon_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + weapon_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // if(weapon_essence_array.load(file) != 0) return -1; - weapon_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + weapon_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // if(armor_major_type_array.load(file) != 0) return -1; - armor_major_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + armor_major_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // if(armor_sub_type_array.load(file) != 0) return -1; - armor_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + armor_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // if(armor_essence_array.load(file) != 0) return -1; - armor_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + armor_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // if(decoration_major_type_array.load(file) != 0) return -1; - decoration_major_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + decoration_major_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // if(decoration_sub_type_array.load(file) != 0) return -1; - decoration_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + decoration_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // if(decoration_essence_array.load(file) != 0) return -1; - decoration_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + decoration_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - medicine_major_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - medicine_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - medicine_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - material_major_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - material_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + medicine_major_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + medicine_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + medicine_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + material_major_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + material_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - material_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - damagerune_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - damagerune_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - armorrune_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - armorrune_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + material_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + damagerune_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + damagerune_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + armorrune_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + armorrune_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // skip the computer's name of the exporter int tag = AAssit.GetIntFromFileStream(file, ref dwRead); AAssit.ReadString(file, ref dwRead, out var result); t = AAssit.GetIntFromFileStream(file, ref dwRead); - skilltome_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - skilltome_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - flysword_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - wingmanwing_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - townscroll_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + skilltome_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + skilltome_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + flysword_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + wingmanwing_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + townscroll_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - unionscroll_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - revivescroll_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - element_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - taskmatter_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - tossmatter_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + unionscroll_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + revivescroll_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + element_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + taskmatter_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + tossmatter_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - projectile_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - projectile_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - quiver_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - quiver_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - stone_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + projectile_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + projectile_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + quiver_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + quiver_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + stone_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - stone_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - monster_addon_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - monster_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - monster_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + stone_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + monster_addon_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + monster_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + monster_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - npc_talk_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_sell_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_buy_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_repair_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_install_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_uninstall_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_task_in_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_task_out_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_task_matter_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_skill_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_heal_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_transmit_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + npc_talk_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_sell_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_buy_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_repair_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_install_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_uninstall_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_task_in_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_task_out_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_task_matter_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_skill_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_heal_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_transmit_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - npc_transport_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_proxy_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_storage_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_make_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_decompose_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + npc_transport_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_proxy_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_storage_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_make_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_decompose_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - npc_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + npc_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); uint sz = AAssit.GetUIntFromFileStream(file, ref dwRead); if (sz <= 0) return -1; @@ -405,87 +405,87 @@ namespace ModelRenderer.Scripts.GameData talk_proc_array[i] = tp; } - face_texture_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - face_shape_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - face_emotion_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - face_expression_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - face_hair_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - face_moustache_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - colorpicker_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - customizedata_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + face_texture_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + face_shape_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + face_emotion_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + face_expression_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + face_hair_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + face_moustache_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + colorpicker_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + customizedata_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - recipe_major_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - recipe_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - recipe_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + recipe_major_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + recipe_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + recipe_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - enemy_faction_config_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - character_class_config_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - param_adjust_config_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - player_action_info_config_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - taskdice_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + enemy_faction_config_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + character_class_config_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + param_adjust_config_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + player_action_info_config_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + taskdice_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - tasknormalmatter_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - face_faling_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - player_levelexp_config_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - mine_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - mine_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + tasknormalmatter_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + face_faling_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + player_levelexp_config_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + mine_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + mine_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - npc_identify_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - fashion_major_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - fashion_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - fashion_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + npc_identify_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + fashion_major_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + fashion_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + fashion_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - faceticket_major_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - faceticket_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - faceticket_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - facepill_major_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - facepill_sub_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + faceticket_major_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + faceticket_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + faceticket_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + facepill_major_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + facepill_sub_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - facepill_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - suite_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - gm_generator_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - gm_generator_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - pet_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + facepill_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + suite_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + gm_generator_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + gm_generator_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + pet_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - pet_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - pet_egg_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - pet_food_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - pet_faceticket_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - fireworks_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + pet_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + pet_egg_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + pet_food_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + pet_faceticket_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + fireworks_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - war_tankcallin_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + war_tankcallin_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); tag = AAssit.GetIntFromFileStream(file, ref dwRead); AAssit.ReadString(file, ref dwRead, out result); - npc_war_towerbuild_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - player_secondlevel_config_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_resetprop_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_petname_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + npc_war_towerbuild_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + player_secondlevel_config_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_resetprop_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_petname_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - npc_petlearnskill_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_petforgetskill_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - skillmatter_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - refine_ticket_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - destroying_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + npc_petlearnskill_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_petforgetskill_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + skillmatter_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + refine_ticket_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + destroying_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - npc_equipbind_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_equipdestroy_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - npc_equipundestroy_service_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - bible_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - speaker_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + npc_equipbind_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_equipdestroy_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + npc_equipundestroy_service_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + bible_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + speaker_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - autohp_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - automp_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - double_exp_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - transmitscroll_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - dye_ticket_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + autohp_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + automp_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + double_exp_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + transmitscroll_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + dye_ticket_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); - goblin_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - goblin_equip_type_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - goblin_equip_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - goblin_exppill_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); - sell_certificate_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); + goblin_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + goblin_equip_type_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + goblin_equip_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + goblin_exppill_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); + sell_certificate_essence_array = AAssit.ReadArrayPointerFromBinary(file, ref dwRead); // target_item_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); // look_info_essence_array = AAssit.ReadArrayFromBinary(file, ref dwRead); diff --git a/Assets/PerfectWorld/Scripts/Task/ATaskTemplFixedData.cs b/Assets/PerfectWorld/Scripts/Task/ATaskTemplFixedData.cs new file mode 100644 index 0000000000..c885d54660 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Task/ATaskTemplFixedData.cs @@ -0,0 +1,661 @@ +using System; +using System.Runtime.InteropServices; +using BrewMonster.Scripts.Task; + +namespace PerfectWorld.Scripts.Task +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct ATaskTemplFixedData + { + // 任务id // Task ID + public uint m_ID; + + // 任务名称 // Task name + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_TASK_NAME_LEN)] + public ushort[] m_szName; + + // 任务署名 // Task signature + [MarshalAs(UnmanagedType.U1)] + public bool m_bHasSign; + + // 署名字符串 // Signature string + // skip 4 bytes + public ushort[] m_pszSignature; + + // 任务类型 // Task type + public uint m_ulType; + + // 时间限制 // Time limit + 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 + public uint m_ulTimetable; + + // 时间方式 // Time method + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_TIMETABLE_SIZE)] + public byte[] m_tmType; + + // 发放起始时间 // Distribution start time + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public task_tm[] m_tmStart; + + // 发放终止时间 // Distribution end time + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public task_tm[] m_tmEnd; + + // 发放频率 // Distribution frequency + public int m_lAvailFrequency; + public int m_lPeriodLimit; + + // 选择单个子任务执行 // Execute single subtask + [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; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_TASKREGION)] + [NonSerialized] + 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; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_TASKREGION)] + [NonSerialized] + 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; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_TASKREGION)] + [NonSerialized] + 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 + public uint m_ulDelvNPC; + + // Award NPC + 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 + public uint m_ulChangeKeyCnt; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public int[] m_plChangeKey; // [TASK_AWARD_MAX_CHANGE_VALUE] + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public int[] m_plChangeKeyValue; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public bool[] m_pbChangeType; + + // Fail on scene switch + [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)] + [NonSerialized] + public byte[,] m_pszPQExp; // PQ expressions + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [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)] + [NonSerialized] + public MONSTERS_CONTRIB[] m_MonstersContrib; // Monster contribution settings // 怪物贡献度设定 + + // 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; + public uint m_ulGivenCmnCount; + public uint m_ulGivenTskCount; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public ITEM_WANTED[] m_GivenItems; //[MAX_ITEM_WANTED]; + // 押金 // Deposit + public uint m_ulPremise_Deposit; + [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; + public task_tm m_tmCharEndTime; + public uint m_ulCharTimeGreaterThan; + + // 关联任务 // Related tasks + public uint m_ulPremise_Cotask; + public uint m_ulCoTaskCond; + // 互斥任务 // Mutually exclusive tasks + public uint m_ulMutexTaskCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_MUTEX_TASK_COUNT)] + public uint[] m_ulMutexTasks; + // 生活技能级别 // Life skill levels + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_LIVING_SKILLS)] + public long[] m_lSkillLev; + // 动态任务类型 // Dynamic task type + public byte m_DynTaskType; + // 特殊奖励号,用于运营的活动 // Special award number, used for operational activities + public uint m_ulSpecialAward; + + // 组队信息 // Team information + [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 + public uint m_ulTeamMemsWanted; + // [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 */ + + public uint m_enumMethod; + public uint m_enumFinishType; + + /* 任务方式 */ /* Task methods */ + + public uint m_ulPlayerWanted; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public PLAYER_WANTED[] m_PlayerWanted; + public uint m_ulMonsterWanted; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public MONSTER_WANTED[] m_MonsterWanted; + + public uint m_ulItemsWanted; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public ITEM_WANTED[] m_ItemsWanted; + public uint m_ulGoldWanted; + + public int m_iFactionContribWanted; + public int m_iFactionExpContribWanted; + + public uint m_ulNPCToProtect; + public uint m_ulProtectTimeLen; + + public uint m_ulNPCMoving; + public uint m_ulNPCDestSite; + + //public ZONE_VERT m_ReachSiteMin; + //public ZONE_VERT m_ReachSiteMax; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public Task_Region[] m_pReachSite; + public uint m_ulReachSiteCnt; + public uint m_ulReachSiteId; + public uint m_ulWaitTime; + + //藏宝图 使用已接任务列表中的m_iUsefulData1存储 // Treasure map Use m_iUsefulData1 in the list of accepted tasks + public enum TREASURE_DISTANCE_LEVEL + { + DISTANCE_FAR_FAR_AWAY, + DISTANCE_FAR, + DISTANCE_MEDIUM, + DISTANCE_NEAR, + DISTANCE_VERY_NEAR, + DISTANCE_NUM, + } + + // TREA section + public ZONE_VERT m_TreasureStartZone; + public byte m_ucZonesNumX; + public byte m_ucZonesNumZ; + public byte m_ucZoneSide; + + //public ZONE_VERT m_LeaveSiteMin; + //public ZONE_VERT m_LeaveSiteMax; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + [NonSerialized] + public Task_Region[] m_pLeaveSite; + public uint m_ulLeaveSiteCnt; + public uint m_ulLeaveSiteId; + + // 完成全局key/value // Complete global key/value + [MarshalAs(UnmanagedType.U1)] + public bool m_bFinNeedComp; + public int m_nFinExp1AndOrExp2; + public COMPARE_KEY_VALUE m_Fin1KeyValue; + public COMPARE_KEY_VALUE m_Fin2KeyValue; + + // 需显示的全局变量表达式 // Global variable expressions to display + public uint m_ulExpCnt; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + public byte[,] m_pszExp; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + [NonSerialized] + public TASK_EXPRESSION[,] m_pExpArr; + + // 需显示的全局变量表达式提示字符串 // Global variable expression prompt strings + public uint m_ulTaskCharCnt; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + [NonSerialized] + public ushort[,] m_pTaskChar; + + // 变身状态 // Transformation state + public byte m_ucTransformedForm; + // 等级 // Level + public uint m_ulReachLevel; + // 转生次数 // Reincarnation count + public uint m_ulReachReincarnationCount; + // 境界等级 // Realm level + public uint m_ulReachRealmLevel; + + public uint m_uiEmotion; // 表情动作 // Emotion action + + /* 任务结束后的奖励 */ /* Rewards after task completion */ + public uint m_ulAwardType_S; + public uint m_ulAwardType_F; + + /* 普通和按每个方式 */ /* Normal and per-method rewards */ + [NonSerialized] + public AWARD_DATA m_Award_S; /* 成功 */ /* Success */ + //public uint m_Award_S_ptr; + [NonSerialized] + public AWARD_DATA m_Award_F; /* 失败 */ /* Failure */ + //public uint m_Award_F_ptr; + + + /* 时间比例方式 */ /* Time ratio method */ + //TODO: Revert + [NonSerialized] + public AWARD_RATIO_SCALE m_AwByRatio_S; + //public uint m_AwByRatio_S_ptr; + [NonSerialized] + public AWARD_RATIO_SCALE m_AwByRatio_F; + // public uint m_AwByRatio_F_ptr; + + /* 按获得物比例方式 */ /* Item ratio method */ + //TODO: Revert + [NonSerialized] + public AWARD_ITEMS_SCALE m_AwByItems_S; + public uint m_AwByItems_S_ptr; + [NonSerialized] + public AWARD_ITEMS_SCALE m_AwByItems_F; + public uint m_AwByItems_F_ptr; + + /* 层次结构 */ /* Hierarchy structure */ + public uint m_ulParent; + public uint m_ulPrevSibling; + public uint m_ulNextSibling; + public uint m_ulFirstChild; + + /* 库任务相关 */ /* Library task related */ + [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 + } +} \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/ATaskTemplFixedData.cs.meta b/Assets/PerfectWorld/Scripts/Task/ATaskTemplFixedData.cs.meta new file mode 100644 index 0000000000..b03042e5bb --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Task/ATaskTemplFixedData.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 98da1f5a890d42488e2ef0b4bce1acef +timeCreated: 1761707323 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs b/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs index c49991ccf9..834dbe4d07 100644 --- a/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs +++ b/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs @@ -67,23 +67,28 @@ namespace BrewMonster.Scripts.Task // fread(pOffs, sizeof(long), tph.item_count, fp); - pOffs = AAssit.ReadArrayFromBinary(fs, tph.item_count, ref readBytes); + // read File and prepare offset array before loading tasks + pOffs = AAssit.ReadArrayFromBinary(fs, (int)tph.item_count, ref readBytes); - - for (int i = 0; i < tph.item_count; i++) + //Debug.Log((int)tph.item_count); + //BMLogger.Log($" [MH] Task File Lenght: {fs.Length}"); + for (int i = 874; i < 875; i++) //TODO: tph.item_count { + // mvoe file pointer to task offset fs.Seek(pOffs[i], SeekOrigin.Begin); + BMLogger.Log(" [MH] Loading Task Templ at offset: " + pOffs[i]); 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"); } @@ -153,7 +158,7 @@ namespace BrewMonster.Scripts.Task if (pTask.m_FixedData.m_bSkillTask) m_SkillTaskLst.Add(pTask); //todo: recheck m_DynTaskType type - if (!string.IsNullOrEmpty(pTask.m_FixedData.m_DynTaskType)) + if (pTask.m_FixedData.m_DynTaskType != '\0') { if (m_DynTaskMap.TryGetValue(pTask.m_FixedData.m_ID, out ATaskTempl task)) { diff --git a/Assets/PerfectWorld/Scripts/Task/AWARD_DATA.cs b/Assets/PerfectWorld/Scripts/Task/AWARD_DATA.cs new file mode 100644 index 0000000000..67b7dfbeee --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Task/AWARD_DATA.cs @@ -0,0 +1,566 @@ +using System; +using System.Runtime.InteropServices; +using BrewMonster.Scripts.Task; + +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/PerfectWorld/Scripts/Task/AWARD_DATA.cs.meta b/Assets/PerfectWorld/Scripts/Task/AWARD_DATA.cs.meta new file mode 100644 index 0000000000..04c9ed66a4 --- /dev/null +++ b/Assets/PerfectWorld/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/PerfectWorld/Scripts/Task/AWARD_ITEMS_CAND.cs b/Assets/PerfectWorld/Scripts/Task/AWARD_ITEMS_CAND.cs new file mode 100644 index 0000000000..065fce75f2 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Task/AWARD_ITEMS_CAND.cs @@ -0,0 +1,109 @@ +using System.Runtime.InteropServices; +using BrewMonster.Scripts.Task; + +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/PerfectWorld/Scripts/Task/AWARD_ITEMS_CAND.cs.meta b/Assets/PerfectWorld/Scripts/Task/AWARD_ITEMS_CAND.cs.meta new file mode 100644 index 0000000000..fd9f5cba28 --- /dev/null +++ b/Assets/PerfectWorld/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/PerfectWorld/Scripts/Task/CECTaskInterface.cs b/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs index 38be64a5b1..ac21f51497 100644 --- a/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs +++ b/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs @@ -1,10 +1,164 @@ using BrewMonster.Network; using BrewMonster.Scripts.Player; using System.Collections.Generic; +using PerfectWorld.Scripts.Task; using UnityEngine; namespace BrewMonster.Scripts.Task { + public class TaskInterfaceConstants + { + // Task Prerequisite Error Code + public const int TASK_PREREQU_FAIL_INDETERMINATE = 1; + public const int TASK_PREREQU_FAIL_NOT_ROOT = 2; + public const int TASK_PREREQU_FAIL_SAME_TASK = 3; + public const int TASK_PREREQU_FAIL_NO_SPACE = 4; + public const int TASK_PREREQU_FAIL_FULL = 5; + public const int TASK_PREREQU_FAIL_CANT_REDO = 6; + public const int TASK_PREREQU_FAIL_BELOW_LEVEL = 7; + public const int TASK_PREREQU_FAIL_ABOVE_LEVEL = 8; + public const int TASK_PREREQU_FAIL_NO_ITEM = 9; + public const int TASK_PREREQU_FAIL_BELOW_REPU = 10; + public const int TASK_PREREQU_FAIL_CLAN = 11; + public const int TASK_PREREQU_FAIL_WRONG_GENDER = 12; + public const int TASK_PREREQU_FAIL_NOT_IN_OCCU = 13; + public const int TASK_PREREQU_FAIL_WRONG_PERIOD = 14; + public const int TASK_PREREQU_FAIL_PREV_TASK = 15; + public const int TASK_PREREQU_FAIL_MAX_RCV = 16; + public const int TASK_PREREQU_FAIL_NO_DEPOSIT = 17; + public const int TASK_PREREQU_FAIL_NO_TASK = 18; + public const int TASK_PREREQU_FAIL_NOT_CAPTAIN = 19; + public const int TASK_PREREQU_FAIL_ILLEGAL_MEM = 20; + public const int TASK_PREREQU_FAIL_WRONG_TIME = 21; + public const int TASK_PREREQU_FAIL_NO_SUCH_SUB = 22; + public const int TASK_PREREQU_FAIL_MUTEX_TASK = 23; + public const int TASK_PREREQU_FAIL_NOT_IN_ZONE = 24; + public const int TASK_PREREQU_FAIL_WRONG_SUB = 25; + public const int TASK_PREREQU_FAIL_OUTOF_DIST = 26; + public const int TASK_PREREQU_FAIL_GIVEN_ITEM = 27; + public const int TASK_PREREQU_FAIL_LIVING_SKILL = 28; + public const int TASK_PREREQU_FAIL_SPECIAL_AWARD = 29; + public const int TASK_PREREQU_FAIL_GM = 30; + public const int TASK_PREREQU_FAIL_GLOBAL_KEYVAL = 31; + public const int TASK_PREREQU_FAIL_SHIELD_USER = 32; + public const int TASK_PREREQU_FAIL_ALREADY_HAS_PQ = 33; + public const int TASK_PREREQU_FAIL_MAX_ACC_CNT = 34; + public const int TASK_PREREQU_FAIL_RMB_NOT_ENOUGH = 35; + public const int TASK_PREREQU_FAIL_NOT_COUPLE = 36; + public const int TASK_PREREQU_FAIL_ERR_CHAR_TIME = 37; + public const int TASK_PREREQU_FAIL_NOT_IVTRSLOTNUM = 38; // version 81 + public const int TASK_PREREQU_FAIL_BELOW_FACTION_CONTRIB = 39; // version 87 + public const int TASK_PREREQU_FAIL_BELOW_RECORD_TASKS_NUM = 40; // version 91 + public const int TASK_PREREQU_FAIL_OVER_RECEIVE_PER_DAY = 41; + public const int TASK_PREREQU_FAIL_TRANSFORM_MASK = 42; + public const int TASK_PREREQU_FAIL_FORCE = 43; + public const int TASK_PREREQU_FAIL_FORCE_REPUTATION = 44; + public const int TASK_PREREQU_FAIL_FORCE_CONTRIBUTION = 45; + public const int TASK_PREREQU_FAIL_EXP = 46; + public const int TASK_PREREQU_FAIL_SP = 47; + public const int TASK_PREREQU_FAIL_FORCE_AL = 48; + public const int TASK_PREREQU_FAIL_WEDDING_OWNER = 49; + public const int TASK_PREREQU_FAIL_CROSSSERVER_NO_ACOUNT_LIMIT = 50; + public const int TASK_PREREQU_FAIL_CROSSSERVER_NO_MARRIAGE = 51; + public const int TASK_PREREQU_FAIL_CROSSSERVER_NO_FORCE = 52; + public const int TASK_PREREQU_FAIL_KING = 53; + public const int TASK_PREREQU_FAIL_IN_TEAM = 54; + public const int TASK_PREREQU_FAIL_TITLE = 55; + public const int TASK_PREREQU_FAIL_HISTORYSTAGE = 56; + public const int TASK_PREREQU_FAIL_NO_GIFTCARD_TASK = 57; + public const int TASK_PREREQU_FAIL_BELOW_REINCARNATION = 57; + public const int TASK_PREREQU_FAIL_ABOVE_REINCARNATION = 58; + public const int TASK_PREREQU_FAIL_BELOW_REALMLEVEL = 59; + public const int TASK_PREREQU_FAIL_ABOVE_REALMLEVEL = 60; + public const int TASK_PREREQU_FAIL_REALM_EXP_FULL = 61; + public const int TASK_PREREQU_FAIL_CARD_COUNT_COLLECTION = 62; + public const int TASK_PREREQU_FAIL_MAX_ROLE_CNT = 63; + public const int TASK_PREREQU_FAIL_CARD_COUNT_RANK = 64; + public const int TASK_PREREQU_FAIL_TASK_FORBID = 65; + public const int TASK_PREREQU_FAIL_NO_NAVIGATE_INSHPAED = 66; + + public const int TASK_AWARD_FAIL_GIVEN_ITEM = 150; + public const int TASK_AWARD_FAIL_NEW_TASK = 151; + public const int TASK_AWARD_FAIL_REPUTATION = 152; + public const int TASK_AWARD_FAIL_GLOBAL_KEYVAL = 153; + public const int TASK_AWARD_FAIL_CROSSSERVER_NO_ACOUNT_LIMIT = 154; + public const int TASK_AWARD_FAIL_CROSSSERVER_NO_ACOUNT_STORAGE = 155; + public const int TASK_AWARD_FAIL_CROSSSERVER_NO_DIVORCE = 156; + public const int TASK_AWARD_FAIL_CROSSSERVER_NO_FACTION_RALATED = 157; + public const int TASK_AWARD_FAIL_CROSSSERVER_NO_FORCE_RALATED = 158; + public const int TASK_AWARD_FAIL_CROSSSERVER_NO_DIVIEND = 159; + public const int TASK_AWARD_FAIL_LEVEL_CHECK = 160; + + + // Task messages + public const int TASK_MSG_NEW = 1; + public const int TASK_MSG_SUCCESS = 2; + public const int TASK_MSG_FAIL = 3; + + public const int TASK_ACTIVE_LIST_HEADER_LEN = 8; + public const int TASK_ACTIVE_LIST_MAX_LEN = 175; + public const int TASK_FINISHED_LIST_MAX_LEN = 2040; + public const int TASK_DATA_BUF_MAX_LEN = 32; + public const int TASK_FINISH_TIME_MAX_LEN = 1700; + public const int TASK_FINISH_COUNT_MAX_LEN = 730; + + // 库任务 // Library tasks + public const int TASK_MAX_DELIVER_COUNT = 5; + public const int TASK_STORAGE_COUNT = 32; + public const int TASK_STORAGE_LEN = 10; + public const int TASK_STORAGE_WHELL_SCALE = 10000; // 10000.f originally + + // 当前激活的任务列表缓冲区大小 // Current active task list buffer size + public const int TASK_ACTIVE_LIST_BUF_SIZE = (TASK_ACTIVE_LIST_MAX_LEN * TASK_DATA_BUF_MAX_LEN + TASK_ACTIVE_LIST_HEADER_LEN); + // 已完成的任务列表缓冲区大小 // Completed task list buffer size + public const int TASK_FINISHED_LIST_BUF_SIZE = 8192; + public const int TASK_FINISHED_LIST_BUF_SIZE_OLD = 4096; + // 任务全局数据大小 // Task global data size + public const int TASK_GLOBAL_DATA_SIZE = 256; + // 任务完成时间 // Task completion time + public const int TASK_FINISH_TIME_LIST_BUF_SIZE = 10240; + //任务完成次数 // Task completion count + public const int TASK_FINISH_COUNT_LIST_BUF_SIZE = 10240; + // 库任务 // Library tasks + public const int TASK_STORAGE_LIST_BUF_SIZE = 1024; + + + // Masks + public const int TASK_MASK_KILL_MONSTER = 0x00000001; + public const int TASK_MASK_COLLECT_ITEM = 0x00000002; + public const int TASK_MASK_TALK_TO_NPC = 0x00000004; + public const int TASK_MASK_REACH_SITE = 0x00000008; + public const int TASK_MASK_ANSWER_QUESTION = 0x00000010; + public const int TASK_MASK_TINY_GAME = 0x00000020; + public const int TASK_MASK_KILL_PQ_MONSTER = 0x00000040; + public const int TASK_MASK_KILL_PLAYER = 0x00000080; + + + public const int MAX_MONSTER_WANTED = 3; // 受ActiveTaskEntry大小限制,最大3 // Limited by ActiveTaskEntry size, max 3 + public const int MAX_PLAYER_WANTED = MAX_MONSTER_WANTED; + public const int MAX_ITEM_WANTED = 10; + public const int MAX_ITEM_AWARD = 64; + public const int MAX_MONSTER_SUMMONED = 32; // 最大召唤出的怪物数量 // Maximum number of summoned monsters + + public const int MAX_OCCUPATIONS = 12; // 职业 // Occupations + + public const int TASK_MSG_CHANNEL_LOCAL = 0; + public const int TASK_MSG_CHANNEL_WORLD = 1; + public const int TASK_MSG_CHANNEL_BROADCAST = 9; + + public const int TASK_TEAM_RELATION_MARRIAGE = 1; + + public const int TASK_AWARD_MAX_CHANGE_VALUE = 255; + public const int TASK_AWARD_MAX_DISPLAY_VALUE = 64; + + public const int TASK_AWARD_MAX_DISPLAY_EXP_CNT = 32; // 表达式的个数 // Number of expressions + public const int TASK_AWARD_MAX_DISPLAY_CHAR_LEN = 64; // 表达式的长度 // Length of expression + + public const int TASK_WORLD_CONTRIBUTION_SPEND_PER_DAY = 30; // 免费玩家每日消费贡献度上限 // Daily contribution spend cap for free players + + } + + public class CECTaskInterface : TaskInterface { public const int TASK_MAX_DELIVER_COUNT = 5; diff --git a/Assets/PerfectWorld/Scripts/Task/SizeTest.cs b/Assets/PerfectWorld/Scripts/Task/SizeTest.cs new file mode 100644 index 0000000000..40b84820dc --- /dev/null +++ b/Assets/PerfectWorld/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/PerfectWorld/Scripts/Task/SizeTest.cs.meta b/Assets/PerfectWorld/Scripts/Task/SizeTest.cs.meta new file mode 100644 index 0000000000..850662d59d --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Task/SizeTest.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: df0da79040b03460fa770600fdc054b3 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/TaskExpAnalyser.cs b/Assets/PerfectWorld/Scripts/Task/TaskExpAnalyser.cs index e7101b9a2b..383d122682 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskExpAnalyser.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskExpAnalyser.cs @@ -1,5 +1,8 @@ -namespace BrewMonster.Scripts.Task +using System.Runtime.InteropServices; + +namespace PerfectWorld.Scripts.Task { + [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TASK_EXPRESSION { public int type; @@ -9,5 +12,24 @@ { return (type == src.type && value == src.value); } + + public override bool Equals(object obj) + { + if (obj is TASK_EXPRESSION other) + { + return Equals(other); + } + return false; + } + + public static bool operator ==(TASK_EXPRESSION lhs, TASK_EXPRESSION rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(TASK_EXPRESSION lhs, TASK_EXPRESSION rhs) + { + return !lhs.Equals(rhs); + } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/TaskLog.txt b/Assets/PerfectWorld/Scripts/Task/TaskLog.txt new file mode 100644 index 0000000000..83590e0757 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Task/TaskLog.txt @@ -0,0 +1,290 @@ +if(m_ID == 33519UL){ + // Log all non-pointer properties of ATaskTemplFixedData, one per line + a_LogOutput(1, "[MH] m_ID=%lu", m_ID); + // m_szName skipped as complex char array; name already converted above + a_LogOutput(1, "[MH] m_bHasSign=%d", (int)m_bHasSign); + a_LogOutput(1, "[MH] m_ulType=%lu", m_ulType); + a_LogOutput(1, "[MH] m_ulTimeLimit=%lu", m_ulTimeLimit); + a_LogOutput(1, "[MH] m_bOfflineFail=%d", (int)m_bOfflineFail); + a_LogOutput(1, "[MH] m_bAbsFail=%d", (int)m_bAbsFail); + a_LogOutput(1, "[MH] m_tmAbsFailTime={year=%ld,month=%ld,day=%ld,hour=%ld,min=%ld,wday=%ld}", + (long)m_tmAbsFailTime.year,(long)m_tmAbsFailTime.month,(long)m_tmAbsFailTime.day,(long)m_tmAbsFailTime.hour,(long)m_tmAbsFailTime.min,(long)m_tmAbsFailTime.wday); + a_LogOutput(1, "[MH] m_bItemNotTakeOff=%d", (int)m_bItemNotTakeOff); + a_LogOutput(1, "[MH] m_bAbsTime=%d", (int)m_bAbsTime); + a_LogOutput(1, "[MH] m_ulTimetable=%lu", m_ulTimetable); + { + char buf[1024]; + int off = 0; + off += snprintf(buf + off, (size_t)(sizeof(buf) - off), "["); + for (unsigned long i = 0; i < (unsigned long)MAX_TIMETABLE_SIZE; ++i){ + off += snprintf(buf + off, (size_t)(sizeof(buf) - off), "%s%d", (i?",":""), (int)m_tmType[i]); + if (off < 0 || off >= (int)sizeof(buf)) break; + } + snprintf(buf + (off<0?0:off), (size_t)((off<0?0:sizeof(buf)-off)), "]"); + a_LogOutput(1, "[MH] m_tmType=%s", buf); + } + a_LogOutput(1, "[MH] m_lAvailFrequency=%ld", m_lAvailFrequency); + a_LogOutput(1, "[MH] m_lPeriodLimit=%ld", m_lPeriodLimit); + a_LogOutput(1, "[MH] m_bChooseOne=%d", (int)m_bChooseOne); + a_LogOutput(1, "[MH] m_bRandOne=%d", (int)m_bRandOne); + a_LogOutput(1, "[MH] m_bExeChildInOrder=%d", (int)m_bExeChildInOrder); + a_LogOutput(1, "[MH] m_bParentAlsoFail=%d", (int)m_bParentAlsoFail); + a_LogOutput(1, "[MH] m_bParentAlsoSucc=%d", (int)m_bParentAlsoSucc); + a_LogOutput(1, "[MH] m_bCanGiveUp=%d", (int)m_bCanGiveUp); + a_LogOutput(1, "[MH] m_bCanRedo=%d", (int)m_bCanRedo); + a_LogOutput(1, "[MH] m_bCanRedoAfterFailure=%d", (int)m_bCanRedoAfterFailure); + a_LogOutput(1, "[MH] m_bClearAsGiveUp=%d", (int)m_bClearAsGiveUp); + a_LogOutput(1, "[MH] m_bNeedRecord=%d", (int)m_bNeedRecord); + a_LogOutput(1, "[MH] m_bFailAsPlayerDie=%d", (int)m_bFailAsPlayerDie); + a_LogOutput(1, "[MH] m_ulMaxReceiver=%lu", m_ulMaxReceiver); + a_LogOutput(1, "[MH] m_bDelvInZone=%d", (int)m_bDelvInZone); + a_LogOutput(1, "[MH] m_ulDelvWorld=%lu", m_ulDelvWorld); + a_LogOutput(1, "[MH] m_ulDelvRegionCnt=%lu", m_ulDelvRegionCnt); + a_LogOutput(1, "[MH] m_bEnterRegionFail=%d", (int)m_bEnterRegionFail); + a_LogOutput(1, "[MH] m_ulEnterRegionWorld=%lu", m_ulEnterRegionWorld); + a_LogOutput(1, "[MH] m_ulEnterRegionCnt=%lu", m_ulEnterRegionCnt); + a_LogOutput(1, "[MH] m_bLeaveRegionFail=%d", (int)m_bLeaveRegionFail); + a_LogOutput(1, "[MH] m_ulLeaveRegionWorld=%lu", m_ulLeaveRegionWorld); + a_LogOutput(1, "[MH] m_ulLeaveRegionCnt=%lu", m_ulLeaveRegionCnt); + a_LogOutput(1, "[MH] m_bLeaveForceFail=%d", (int)m_bLeaveForceFail); + a_LogOutput(1, "[MH] m_bTransTo=%d", (int)m_bTransTo); + a_LogOutput(1, "[MH] m_ulTransWldId=%lu", m_ulTransWldId); + a_LogOutput(1, "[MH] m_TransPt={x=%f,y=%f,z=%f}", m_TransPt.x, m_TransPt.y, m_TransPt.z); + a_LogOutput(1, "[MH] m_lMonsCtrl=%ld", m_lMonsCtrl); + a_LogOutput(1, "[MH] m_bTrigCtrl=%d", (int)m_bTrigCtrl); + a_LogOutput(1, "[MH] m_bAutoDeliver=%d", (int)m_bAutoDeliver); + a_LogOutput(1, "[MH] m_bDisplayInExclusiveUI=%d", (int)m_bDisplayInExclusiveUI); + a_LogOutput(1, "[MH] m_bReadyToNotifyServer=%d", (int)m_bReadyToNotifyServer); + a_LogOutput(1, "[MH] m_bUsedInTokenShop=%d", (int)m_bUsedInTokenShop); + a_LogOutput(1, "[MH] m_bDeathTrig=%d", (int)m_bDeathTrig); + a_LogOutput(1, "[MH] m_bClearAcquired=%d", (int)m_bClearAcquired); + a_LogOutput(1, "[MH] m_ulSuitableLevel=%lu", m_ulSuitableLevel); + a_LogOutput(1, "[MH] m_bShowPrompt=%d", (int)m_bShowPrompt); + a_LogOutput(1, "[MH] m_bKeyTask=%d", (int)m_bKeyTask); + a_LogOutput(1, "[MH] m_ulDelvNPC=%lu", m_ulDelvNPC); + a_LogOutput(1, "[MH] m_ulAwardNPC=%lu", m_ulAwardNPC); + a_LogOutput(1, "[MH] m_bSkillTask=%d", (int)m_bSkillTask); + a_LogOutput(1, "[MH] m_bCanSeekOut=%d", (int)m_bCanSeekOut); + a_LogOutput(1, "[MH] m_bShowDirection=%d", (int)m_bShowDirection); + a_LogOutput(1, "[MH] m_bMarriage=%d", (int)m_bMarriage); + a_LogOutput(1, "[MH] m_ulChangeKeyCnt=%lu", m_ulChangeKeyCnt); + a_LogOutput(1, "[MH] m_bSwitchSceneFail=%d", (int)m_bSwitchSceneFail); + a_LogOutput(1, "[MH] m_bHidden=%d", (int)m_bHidden); + a_LogOutput(1, "[MH] m_bDeliverySkill=%d", (int)m_bDeliverySkill); + a_LogOutput(1, "[MH] m_iDeliveredSkillID=%d", m_iDeliveredSkillID); + a_LogOutput(1, "[MH] m_iDeliveredSkillLevel=%d", m_iDeliveredSkillLevel); + a_LogOutput(1, "[MH] m_bShowGfxFinished=%d", (int)m_bShowGfxFinished); + a_LogOutput(1, "[MH] m_bChangePQRanking=%d", (int)m_bChangePQRanking); + a_LogOutput(1, "[MH] m_bCompareItemAndInventory=%d", (int)m_bCompareItemAndInventory); + a_LogOutput(1, "[MH] m_ulInventorySlotNum=%lu", m_ulInventorySlotNum); + a_LogOutput(1, "[MH] m_bPQTask=%d", (int)m_bPQTask); + a_LogOutput(1, "[MH] m_ulPQExpCnt=%lu", m_ulPQExpCnt); + a_LogOutput(1, "[MH] m_bPQSubTask=%d", (int)m_bPQSubTask); + a_LogOutput(1, "[MH] m_bClearContrib=%d", (int)m_bClearContrib); + a_LogOutput(1, "[MH] m_ulMonsterContribCnt=%lu", m_ulMonsterContribCnt); + a_LogOutput(1, "[MH] m_iPremNeedRecordTasksNum=%d", m_iPremNeedRecordTasksNum); + a_LogOutput(1, "[MH] m_bShowByNeedRecordTasksNum=%d", (int)m_bShowByNeedRecordTasksNum); + a_LogOutput(1, "[MH] m_iPremiseFactionContrib=%d", m_iPremiseFactionContrib); + a_LogOutput(1, "[MH] m_bShowByFactionContrib=%d", (int)m_bShowByFactionContrib); + a_LogOutput(1, "[MH] m_bAccountTaskLimit=%d", (int)m_bAccountTaskLimit); + a_LogOutput(1, "[MH] m_bRoleTaskLimit=%d", (int)m_bRoleTaskLimit); + a_LogOutput(1, "[MH] m_ulAccountTaskLimitCnt=%lu", m_ulAccountTaskLimitCnt); + a_LogOutput(1, "[MH] m_bLeaveFactionFail=%d", (int)m_bLeaveFactionFail); + a_LogOutput(1, "[MH] m_bNotIncCntWhenFailed=%d", (int)m_bNotIncCntWhenFailed); + a_LogOutput(1, "[MH] m_bNotClearItemWhenFailed=%d", (int)m_bNotClearItemWhenFailed); + a_LogOutput(1, "[MH] m_bDisplayInTitleTaskUI=%d", (int)m_bDisplayInTitleTaskUI); + a_LogOutput(1, "[MH] m_ucPremiseTransformedForm=%u", (unsigned int)m_ucPremiseTransformedForm); + a_LogOutput(1, "[MH] m_bShowByTransformed=%d", (int)m_bShowByTransformed); + a_LogOutput(1, "[MH] m_ulPremise_Lev_Min=%lu", m_ulPremise_Lev_Min); + a_LogOutput(1, "[MH] m_ulPremise_Lev_Max=%lu", m_ulPremise_Lev_Max); + a_LogOutput(1, "[MH] m_bPremCheckMaxHistoryLevel=%lu", m_bPremCheckMaxHistoryLevel); + a_LogOutput(1, "[MH] m_bShowByLev=%d", (int)m_bShowByLev); + a_LogOutput(1, "[MH] m_bPremCheckReincarnation=%d", (int)m_bPremCheckReincarnation); + a_LogOutput(1, "[MH] m_ulPremReincarnationMin=%lu", m_ulPremReincarnationMin); + a_LogOutput(1, "[MH] m_ulPremReincarnationMax=%lu", m_ulPremReincarnationMax); + a_LogOutput(1, "[MH] m_bShowByReincarnation=%d", (int)m_bShowByReincarnation); + a_LogOutput(1, "[MH] m_bPremCheckRealmLevel=%d", (int)m_bPremCheckRealmLevel); + a_LogOutput(1, "[MH] m_ulPremRealmLevelMin=%lu", m_ulPremRealmLevelMin); + a_LogOutput(1, "[MH] m_ulPremRealmLevelMax=%lu", m_ulPremRealmLevelMax); + a_LogOutput(1, "[MH] m_bPremCheckRealmExpFull=%d", (int)m_bPremCheckRealmExpFull); + a_LogOutput(1, "[MH] m_bShowByRealmLevel=%d", (int)m_bShowByRealmLevel); + a_LogOutput(1, "[MH] m_ulPremItems=%lu", m_ulPremItems); + a_LogOutput(1, "[MH] m_bShowByItems=%d", (int)m_bShowByItems); + a_LogOutput(1, "[MH] m_bPremItemsAnyOne=%d", (int)m_bPremItemsAnyOne); + a_LogOutput(1, "[MH] m_ulGivenItems=%lu", m_ulGivenItems); + a_LogOutput(1, "[MH] m_ulGivenCmnCount=%lu", m_ulGivenCmnCount); + a_LogOutput(1, "[MH] m_ulGivenTskCount=%lu", m_ulGivenTskCount); + a_LogOutput(1, "[MH] m_ulPremise_Deposit=%lu", m_ulPremise_Deposit); + a_LogOutput(1, "[MH] m_bShowByDeposit=%d", (int)m_bShowByDeposit); + a_LogOutput(1, "[MH] m_lPremise_Reputation=%ld", m_lPremise_Reputation); + a_LogOutput(1, "[MH] m_lPremise_RepuMax=%ld", m_lPremise_RepuMax); + a_LogOutput(1, "[MH] m_bShowByRepu=%d", (int)m_bShowByRepu); + a_LogOutput(1, "[MH] m_ulPremise_Task_Count=%lu", m_ulPremise_Task_Count); + { + char buf[1024]; + int off = 0; + off += snprintf(buf + off, (size_t)(sizeof(buf) - off), "["); + for (unsigned long i = 0; i < m_ulPremise_Task_Count && i < (unsigned long)MAX_PREM_TASK_COUNT; ++i){ + off += snprintf(buf + off, (size_t)(sizeof(buf) - off), "%s%lu", (i?",":""), m_ulPremise_Tasks[i]); + if (off < 0 || off >= (int)sizeof(buf)) break; + } + snprintf(buf + (off<0?0:off), (size_t)((off<0?0:sizeof(buf)-off)), "]"); + a_LogOutput(1, "[MH] m_ulPremise_Tasks=%s", buf); + } + a_LogOutput(1, "[MH] m_bShowByPreTask=%d", (int)m_bShowByPreTask); + a_LogOutput(1, "[MH] m_ulPremise_Task_Least_Num=%lu", m_ulPremise_Task_Least_Num); + a_LogOutput(1, "[MH] m_ulPremise_Period=%lu", m_ulPremise_Period); + a_LogOutput(1, "[MH] m_bShowByPeriod=%d", (int)m_bShowByPeriod); + a_LogOutput(1, "[MH] m_ulPremise_Faction=%lu", m_ulPremise_Faction); + a_LogOutput(1, "[MH] m_iPremise_FactionRole=%d", m_iPremise_FactionRole); + a_LogOutput(1, "[MH] m_bShowByFaction=%d", (int)m_bShowByFaction); + a_LogOutput(1, "[MH] m_ulGender=%lu", m_ulGender); + a_LogOutput(1, "[MH] m_bShowByGender=%d", (int)m_bShowByGender); + a_LogOutput(1, "[MH] m_ulOccupations=%lu", m_ulOccupations); + { + char buf[1024]; + int off = 0; + off += snprintf(buf + off, (size_t)(sizeof(buf) - off), "["); + for (unsigned long i = 0; i < m_ulOccupations && i < (unsigned long)MAX_OCCUPATIONS; ++i){ + off += snprintf(buf + off, (size_t)(sizeof(buf) - off), "%s%lu", (i?",":""), m_Occupations[i]); + if (off < 0 || off >= (int)sizeof(buf)) break; + } + snprintf(buf + (off<0?0:off), (size_t)((off<0?0:sizeof(buf)-off)), "]"); + a_LogOutput(1, "[MH] m_Occupations=%s", buf); + } + a_LogOutput(1, "[MH] m_bShowByOccup=%d", (int)m_bShowByOccup); + a_LogOutput(1, "[MH] m_bPremise_Spouse=%d", (int)m_bPremise_Spouse); + a_LogOutput(1, "[MH] m_bShowBySpouse=%d", (int)m_bShowBySpouse); + a_LogOutput(1, "[MH] m_bPremiseWeddingOwner=%d", (int)m_bPremiseWeddingOwner); + a_LogOutput(1, "[MH] m_bShowByWeddingOwner=%d", (int)m_bShowByWeddingOwner); + a_LogOutput(1, "[MH] m_bGM=%d", (int)m_bGM); + a_LogOutput(1, "[MH] m_bShieldUser=%d", (int)m_bShieldUser); + a_LogOutput(1, "[MH] m_bShowByRMB=%d", (int)m_bShowByRMB); + a_LogOutput(1, "[MH] m_ulPremRMBMin=%lu", m_ulPremRMBMin); + a_LogOutput(1, "[MH] m_ulPremRMBMax=%lu", m_ulPremRMBMax); + a_LogOutput(1, "[MH] m_bCharTime=%d", (int)m_bCharTime); + a_LogOutput(1, "[MH] m_bShowByCharTime=%d", (int)m_bShowByCharTime); + a_LogOutput(1, "[MH] m_iCharStartTime=%d", m_iCharStartTime); + a_LogOutput(1, "[MH] m_iCharEndTime=%d", m_iCharEndTime); + a_LogOutput(1, "[MH] m_tmCharEndTime={year=%ld,month=%ld,day=%ld,hour=%ld,min=%ld,wday=%ld}", + (long)m_tmCharEndTime.year,(long)m_tmCharEndTime.month,(long)m_tmCharEndTime.day,(long)m_tmCharEndTime.hour,(long)m_tmCharEndTime.min,(long)m_tmCharEndTime.wday); + a_LogOutput(1, "[MH] m_ulCharTimeGreaterThan=%lu", m_ulCharTimeGreaterThan); + a_LogOutput(1, "[MH] m_ulPremise_Cotask=%lu", m_ulPremise_Cotask); + a_LogOutput(1, "[MH] m_ulCoTaskCond=%lu", m_ulCoTaskCond); + a_LogOutput(1, "[MH] m_ulMutexTaskCount=%lu", m_ulMutexTaskCount); + { + char buf[512]; + int off = 0; + off += snprintf(buf + off, (size_t)(sizeof(buf) - off), "["); + for (unsigned long i = 0; i < m_ulMutexTaskCount && i < (unsigned long)MAX_MUTEX_TASK_COUNT; ++i){ + off += snprintf(buf + off, (size_t)(sizeof(buf) - off), "%s%lu", (i?",":""), m_ulMutexTasks[i]); + if (off < 0 || off >= (int)sizeof(buf)) break; + } + snprintf(buf + (off<0?0:off), (size_t)((off<0?0:sizeof(buf)-off)), "]"); + a_LogOutput(1, "[MH] m_ulMutexTasks=%s", buf); + } + { + char buf[256]; + snprintf(buf, sizeof(buf), "[%ld,%ld,%ld,%ld]", (long)m_lSkillLev[0], (long)m_lSkillLev[1], (long)m_lSkillLev[2], (long)m_lSkillLev[3]); + a_LogOutput(1, "[MH] m_lSkillLev=%s", buf); + } + a_LogOutput(1, "[MH] m_DynTaskType=%d", (int)m_DynTaskType); + a_LogOutput(1, "[MH] m_ulSpecialAward=%lu", m_ulSpecialAward); + a_LogOutput(1, "[MH] m_bTeamwork=%d", (int)m_bTeamwork); + a_LogOutput(1, "[MH] m_bRcvByTeam=%d", (int)m_bRcvByTeam); + a_LogOutput(1, "[MH] m_bSharedTask=%d", (int)m_bSharedTask); + a_LogOutput(1, "[MH] m_bSharedAchieved=%d", (int)m_bSharedAchieved); + a_LogOutput(1, "[MH] m_bCheckTeammate=%d", (int)m_bCheckTeammate); + a_LogOutput(1, "[MH] m_fTeammateDist=%f", m_fTeammateDist); + a_LogOutput(1, "[MH] m_bAllFail=%d", (int)m_bAllFail); + a_LogOutput(1, "[MH] m_bCapFail=%d", (int)m_bCapFail); + a_LogOutput(1, "[MH] m_bCapSucc=%d", (int)m_bCapSucc); + a_LogOutput(1, "[MH] m_fSuccDist=%f", m_fSuccDist); + a_LogOutput(1, "[MH] m_bDismAsSelfFail=%d", (int)m_bDismAsSelfFail); + a_LogOutput(1, "[MH] m_bRcvChckMem=%d", (int)m_bRcvChckMem); + a_LogOutput(1, "[MH] m_fRcvMemDist=%f", m_fRcvMemDist); + a_LogOutput(1, "[MH] m_bCntByMemPos=%d", (int)m_bCntByMemPos); + a_LogOutput(1, "[MH] m_fCntMemDist=%f", m_fCntMemDist); + a_LogOutput(1, "[MH] m_bAllSucc=%d", (int)m_bAllSucc); + a_LogOutput(1, "[MH] m_bCoupleOnly=%d", (int)m_bCoupleOnly); + a_LogOutput(1, "[MH] m_bDistinguishedOcc=%d", (int)m_bDistinguishedOcc); + a_LogOutput(1, "[MH] m_ulTeamMemsWanted=%lu", m_ulTeamMemsWanted); + a_LogOutput(1, "[MH] m_bShowByTeam=%d", (int)m_bShowByTeam); + a_LogOutput(1, "[MH] m_bPremNeedComp=%d", (int)m_bPremNeedComp); + a_LogOutput(1, "[MH] m_nPremExp1AndOrExp2=%d", m_nPremExp1AndOrExp2); + a_LogOutput(1, "[MH] m_Prem1KeyValue={lType=%d,lNum=%ld,op=%d,rType=%d,rNum=%ld}", m_Prem1KeyValue.nLeftType, (long)m_Prem1KeyValue.lLeftNum, m_Prem1KeyValue.nCompOper, m_Prem1KeyValue.nRightType, (long)m_Prem1KeyValue.lRightNum); + a_LogOutput(1, "[MH] m_Prem2KeyValue={lType=%d,lNum=%ld,op=%d,rType=%d,rNum=%ld}", m_Prem2KeyValue.nLeftType, (long)m_Prem2KeyValue.lLeftNum, m_Prem2KeyValue.nCompOper, m_Prem2KeyValue.nRightType, (long)m_Prem2KeyValue.lRightNum); + a_LogOutput(1, "[MH] m_bPremCheckForce=%d", (int)m_bPremCheckForce); + a_LogOutput(1, "[MH] m_iPremForce=%d", m_iPremForce); + a_LogOutput(1, "[MH] m_bShowByForce=%d", (int)m_bShowByForce); + a_LogOutput(1, "[MH] m_iPremForceReputation=%d", m_iPremForceReputation); + a_LogOutput(1, "[MH] m_bShowByForceReputation=%d", (int)m_bShowByForceReputation); + a_LogOutput(1, "[MH] m_iPremForceContribution=%d", m_iPremForceContribution); + a_LogOutput(1, "[MH] m_bShowByForceContribution=%d", (int)m_bShowByForceContribution); + a_LogOutput(1, "[MH] m_iPremForceExp=%d", m_iPremForceExp); + a_LogOutput(1, "[MH] m_bShowByForceExp=%d", (int)m_bShowByForceExp); + a_LogOutput(1, "[MH] m_iPremForceSP=%d", m_iPremForceSP); + a_LogOutput(1, "[MH] m_bShowByForceSP=%d", (int)m_bShowByForceSP); + a_LogOutput(1, "[MH] m_iPremForceActivityLevel=%d", m_iPremForceActivityLevel); + a_LogOutput(1, "[MH] m_bShowByForceActivityLevel=%d", (int)m_bShowByForceActivityLevel); + a_LogOutput(1, "[MH] m_bPremIsKing=%d", (int)m_bPremIsKing); + a_LogOutput(1, "[MH] m_bShowByKing=%d", (int)m_bShowByKing); + a_LogOutput(1, "[MH] m_bPremNotInTeam=%d", (int)m_bPremNotInTeam); + a_LogOutput(1, "[MH] m_bShowByNotInTeam=%d", (int)m_bShowByNotInTeam); + a_LogOutput(1, "[MH] m_iPremTitleNumTotal=%lu", m_iPremTitleNumTotal); + a_LogOutput(1, "[MH] m_iPremTitleNumRequired=%lu", m_iPremTitleNumRequired); + a_LogOutput(1, "[MH] m_bShowByTitle=%d", (int)m_bShowByTitle); + { + char buf[128]; + snprintf(buf, sizeof(buf), "[%d,%d]", m_iPremHistoryStageIndex[0], m_iPremHistoryStageIndex[1]); + a_LogOutput(1, "[MH] m_iPremHistoryStageIndex=%s", buf); + } + a_LogOutput(1, "[MH] m_bShowByHistoryStage=%d", (int)m_bShowByHistoryStage); + a_LogOutput(1, "[MH] m_ulPremGeneralCardCount=%lu", m_ulPremGeneralCardCount); + a_LogOutput(1, "[MH] m_bShowByGeneralCard=%d", (int)m_bShowByGeneralCard); + a_LogOutput(1, "[MH] m_iPremGeneralCardRank=%d", m_iPremGeneralCardRank); + a_LogOutput(1, "[MH] m_ulPremGeneralCardRankCount=%lu", m_ulPremGeneralCardRankCount); + a_LogOutput(1, "[MH] m_bShowByGeneralCardRank=%d", (int)m_bShowByGeneralCardRank); + a_LogOutput(1, "[MH] m_enumMethod=%lu", m_enumMethod); + a_LogOutput(1, "[MH] m_enumFinishType=%lu", m_enumFinishType); + a_LogOutput(1, "[MH] m_ulPlayerWanted=%lu", m_ulPlayerWanted); + a_LogOutput(1, "[MH] m_ulMonsterWanted=%lu", m_ulMonsterWanted); + a_LogOutput(1, "[MH] m_ulItemsWanted=%lu", m_ulItemsWanted); + a_LogOutput(1, "[MH] m_ulGoldWanted=%lu", m_ulGoldWanted); + a_LogOutput(1, "[MH] m_iFactionContribWanted=%d", m_iFactionContribWanted); + a_LogOutput(1, "[MH] m_iFactionExpContribWanted=%d", m_iFactionExpContribWanted); + a_LogOutput(1, "[MH] m_ulNPCToProtect=%lu", m_ulNPCToProtect); + a_LogOutput(1, "[MH] m_ulProtectTimeLen=%lu", m_ulProtectTimeLen); + a_LogOutput(1, "[MH] m_ulNPCMoving=%lu", m_ulNPCMoving); + a_LogOutput(1, "[MH] m_ulNPCDestSite=%lu", m_ulNPCDestSite); + a_LogOutput(1, "[MH] m_ulReachSiteCnt=%lu", m_ulReachSiteCnt); + a_LogOutput(1, "[MH] m_ulReachSiteId=%lu", m_ulReachSiteId); + a_LogOutput(1, "[MH] m_ulWaitTime=%lu", m_ulWaitTime); + a_LogOutput(1, "[MH] m_TreasureStartZone={x=%f,y=%f,z=%f}", m_TreasureStartZone.x, m_TreasureStartZone.y, m_TreasureStartZone.z); + a_LogOutput(1, "[MH] m_ucZonesNumX=%u", (unsigned int)m_ucZonesNumX); + a_LogOutput(1, "[MH] m_ucZonesNumZ=%u", (unsigned int)m_ucZonesNumZ); + a_LogOutput(1, "[MH] m_ucZoneSide=%u", (unsigned int)m_ucZoneSide); + a_LogOutput(1, "[MH] m_ulLeaveSiteCnt=%lu", m_ulLeaveSiteCnt); + a_LogOutput(1, "[MH] m_ulLeaveSiteId=%lu", m_ulLeaveSiteId); + a_LogOutput(1, "[MH] m_bFinNeedComp=%d", (int)m_bFinNeedComp); + a_LogOutput(1, "[MH] m_nFinExp1AndOrExp2=%d", m_nFinExp1AndOrExp2); + a_LogOutput(1, "[MH] m_Fin1KeyValue={lType=%d,lNum=%ld,op=%d,rType=%d,rNum=%ld}", m_Fin1KeyValue.nLeftType, (long)m_Fin1KeyValue.lLeftNum, m_Fin1KeyValue.nCompOper, m_Fin1KeyValue.nRightType, (long)m_Fin1KeyValue.lRightNum); + a_LogOutput(1, "[MH] m_Fin2KeyValue={lType=%d,lNum=%ld,op=%d,rType=%d,rNum=%ld}", m_Fin2KeyValue.nLeftType, (long)m_Fin2KeyValue.lLeftNum, m_Fin2KeyValue.nCompOper, m_Fin2KeyValue.nRightType, (long)m_Fin2KeyValue.lRightNum); + a_LogOutput(1, "[MH] m_ulExpCnt=%lu", m_ulExpCnt); + a_LogOutput(1, "[MH] m_ulTaskCharCnt=%lu", m_ulTaskCharCnt); + a_LogOutput(1, "[MH] m_ucTransformedForm=%u", (unsigned int)m_ucTransformedForm); + a_LogOutput(1, "[MH] m_ulReachLevel=%lu", m_ulReachLevel); + a_LogOutput(1, "[MH] m_ulReachReincarnationCount=%lu", m_ulReachReincarnationCount); + a_LogOutput(1, "[MH] m_ulReachRealmLevel=%lu", m_ulReachRealmLevel); + a_LogOutput(1, "[MH] m_uiEmotion=%u", (unsigned int)m_uiEmotion); + a_LogOutput(1, "[MH] m_ulAwardType_S=%lu", m_ulAwardType_S); + a_LogOutput(1, "[MH] m_ulAwardType_F=%lu", m_ulAwardType_F); + a_LogOutput(1, "[MH] m_ulParent=%lu", m_ulParent); + a_LogOutput(1, "[MH] m_ulPrevSibling=%lu", m_ulPrevSibling); + a_LogOutput(1, "[MH] m_ulNextSibling=%lu", m_ulNextSibling); + a_LogOutput(1, "[MH] m_ulFirstChild=%lu", m_ulFirstChild); + a_LogOutput(1, "[MH] m_bIsLibraryTask=%d", (int)m_bIsLibraryTask); + a_LogOutput(1, "[MH] m_fLibraryTasksProbability=%f", m_fLibraryTasksProbability); + a_LogOutput(1, "[MH] m_bIsUniqueStorageTask=%d", (int)m_bIsUniqueStorageTask); + a_LogOutput(1, "[MH] m_iWorldContribution=%d", m_iWorldContribution); + } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/TaskLog.txt.meta b/Assets/PerfectWorld/Scripts/Task/TaskLog.txt.meta new file mode 100644 index 0000000000..ad753bdfa7 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Task/TaskLog.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b430595362eaf4a248b120d46a7dc5e2 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/PerfectWorld/Scripts/Task/TaskProcess.cs b/Assets/PerfectWorld/Scripts/Task/TaskProcess.cs index 9491d3c884..b65efb6d5d 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskProcess.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskProcess.cs @@ -3,174 +3,177 @@ using System.Runtime.InteropServices; using BrewMonster.Scripts.Task; using UnityEngine; -public class TaskProcess +namespace PerfectWorld.Scripts.Task { - -} -[Flags] -public enum TaskState : byte -{ - TASK_STATE_FINISHED = 0x01, // Is finished - TASK_STATE_SUCCESS = 0x02, // Is successful - TASK_STATE_GIVEUP = 0x04, // Is given up - TASK_STATE_ERR_REPORTED = 0x08, // Error has been reported to client - TASK_STATE_AWARD_NOTIFY_TEAM = 0x10, // Award has been notified to team - TASK_STATE_CONTRIBUTION_FINISH = 0x20 // Contribution finished -} - -// Cur Size 21 bytes -public class TASK_ENTRY_FIXED_DATA -{ - public ushort m_ID; // ID - public char m_ParentIndex; // Parent node index - public char m_PrevSblIndex; // Previous sibling node index - public char m_NextSblIndex; // Next sibling node index - public char m_ChildIndex; // Child node index - public char m_uState; // Task state - public ulong m_ulTaskTime; // Timestamp - public ushort m_uCapTaskId; // Captain task ID - public ulong m_ulTemplAddr; // Template address - public ulong m_ulCapTemplAddr; // Captain task template address -}; - - // ´óСΪTASK_DATA_BUF_MAX_LEN -public class ActiveTaskEntry : TASK_ENTRY_FIXED_DATA -{ - // Buffer union simplified (C# does not support union directly) - public byte[] m_BufData; // Raw data buffer - public ushort[] m_wMonsterNum; // Monster numbers - public int m_iUsefulData1; - public char m_iUsefulData2; - - // bool IsFinished() const { return (m_uState & TASK_STATE_FINISHED) != 0; } - // bool IsSuccess() const { return (m_uState & TASK_STATE_SUCCESS) != 0; } - // bool IsGiveUp() const { return (m_uState & TASK_STATE_GIVEUP) != 0; } - // bool IsErrReported() const { return (m_uState & TASK_STATE_ERR_REPORTED) != 0; } - // bool IsAwardNotifyTeam() const { return (m_uState & TASK_STATE_AWARD_NOTIFY_TEAM) != 0; } - // bool IsContributionFinish() const { return (m_uState & TASK_STATE_CONTRIBUTION_FINISH) != 0; } - // --- State check methods --- - public bool IsFinished() => (m_uState & (byte)TaskState.TASK_STATE_FINISHED) != 0; - public bool IsSuccess() => (m_uState & (byte)TaskState.TASK_STATE_SUCCESS) != 0; - public bool IsGiveUp() => (m_uState & (byte)TaskState.TASK_STATE_GIVEUP) != 0; - public bool IsErrReported() => (m_uState & (byte)TaskState.TASK_STATE_ERR_REPORTED) != 0; - public bool IsAwardNotifyTeam() => (m_uState & (byte)TaskState.TASK_STATE_AWARD_NOTIFY_TEAM) != 0; - public bool IsContributionFinish() => (m_uState & (byte)TaskState.TASK_STATE_CONTRIBUTION_FINISH) != 0; - - // void SetFinished() { m_uState |= TASK_STATE_FINISHED; } - // void ClearFinished() { m_uState &= ~TASK_STATE_FINISHED; } - // void SetSuccess() { m_uState |= TASK_STATE_SUCCESS; } - // void ClearSuccess() { m_uState &= ~TASK_STATE_SUCCESS; } - // void SetGiveUp() { m_uState |= TASK_STATE_GIVEUP; } - // void ClearGiveUp() { m_uState &= ~TASK_STATE_GIVEUP; } - // void SetErrReported() { m_uState |= TASK_STATE_ERR_REPORTED; } - // void ClearErrReported() { m_uState &= ~TASK_STATE_ERR_REPORTED; } - // void SetAwardNotifyTeam() { m_uState |= TASK_STATE_AWARD_NOTIFY_TEAM; } - // void ClearAwardNotifyTeam() { m_uState &= ~TASK_STATE_AWARD_NOTIFY_TEAM; } - // void SetContributionFinish() { m_uState |= TASK_STATE_CONTRIBUTION_FINISH; } - // void ClearContributionFinish() { m_uState &= ~TASK_STATE_CONTRIBUTION_FINISH; } - // - public ATaskTempl GetTempl() + public class TaskProcess { - if (m_ulTemplAddr == 0) return null; - return Marshal.PtrToStructure( - new IntPtr(unchecked((long)m_ulTemplAddr)) - ); - // return reinterpret_cast(m_ulTemplAddr); + } - // const ATaskTempl* GetCap() const { return reinterpret_cast(m_ulCapTemplAddr); } - // const ATaskTempl* GetCapOrSelf() const - // { - // if (m_ulCapTemplAddr) return GetCap(); - // else return GetTempl(); - // } - // bool HasParent() const { return m_ParentIndex != 0xff; } - // bool HasChildren() const { return m_ChildIndex != 0xff; } - // bool IsValid(unsigned char uIndex, unsigned char uMaxCount) const - // { - // if (m_ParentIndex != 0xff) - // { - // if (m_ParentIndex >= uIndex || m_ParentIndex >= uMaxCount) - // return false; - // } - // - // if (m_PrevSblIndex != 0xff) - // { - // if (m_PrevSblIndex >= uIndex || m_PrevSblIndex >= uMaxCount) - // return false; - // } - // - // if (m_NextSblIndex != 0xff) - // { - // if (m_NextSblIndex <= uIndex || m_NextSblIndex >= uMaxCount) - // return false; - // } - // - // if (m_ChildIndex != 0xff) - // { - // if (m_ChildIndex <= uIndex || m_ChildIndex >= uMaxCount) - // return false; - // } - // - // return true; - // } -}; - -public class ActiveTaskList -{ - // --- Header Fields --- - public byte[] header = new byte[CECTaskInterface.TASK_ACTIVE_LIST_HEADER_LEN]; - - public byte m_uTaskCount; // number of tasks - public byte m_uUsedCount; // used count - public ushort m_Version; // version - public byte m_uTopShowTaskCount; // top show task count - public byte m_uListState; // list state - public byte m_uTopHideTaskCount; // top hide task count - - private byte _flags; // simulate bitfield (1 bit + 7 bits) - - public bool m_uMaxSimultaneousCount + [Flags] + public enum TaskState : byte { - get => (_flags & 0x01) != 0; - set + TASK_STATE_FINISHED = 0x01, // Is finished + TASK_STATE_SUCCESS = 0x02, // Is successful + TASK_STATE_GIVEUP = 0x04, // Is given up + TASK_STATE_ERR_REPORTED = 0x08, // Error has been reported to client + TASK_STATE_AWARD_NOTIFY_TEAM = 0x10, // Award has been notified to team + TASK_STATE_CONTRIBUTION_FINISH = 0x20 // Contribution finished + } + + // Cur Size 21 bytes + public class TASK_ENTRY_FIXED_DATA + { + public ushort m_ID; // ID + public char m_ParentIndex; // Parent node index + public char m_PrevSblIndex; // Previous sibling node index + public char m_NextSblIndex; // Next sibling node index + public char m_ChildIndex; // Child node index + public char m_uState; // Task state + public ulong m_ulTaskTime; // Timestamp + public ushort m_uCapTaskId; // Captain task ID + public ulong m_ulTemplAddr; // Template address + public ulong m_ulCapTemplAddr; // Captain task template address + }; + + // ´óСΪTASK_DATA_BUF_MAX_LEN + public class ActiveTaskEntry : TASK_ENTRY_FIXED_DATA + { + // Buffer union simplified (C# does not support union directly) + public byte[] m_BufData; // Raw data buffer + public ushort[] m_wMonsterNum; // Monster numbers + public int m_iUsefulData1; + public char m_iUsefulData2; + + // bool IsFinished() const { return (m_uState & TASK_STATE_FINISHED) != 0; } + // bool IsSuccess() const { return (m_uState & TASK_STATE_SUCCESS) != 0; } + // bool IsGiveUp() const { return (m_uState & TASK_STATE_GIVEUP) != 0; } + // bool IsErrReported() const { return (m_uState & TASK_STATE_ERR_REPORTED) != 0; } + // bool IsAwardNotifyTeam() const { return (m_uState & TASK_STATE_AWARD_NOTIFY_TEAM) != 0; } + // bool IsContributionFinish() const { return (m_uState & TASK_STATE_CONTRIBUTION_FINISH) != 0; } + // --- State check methods --- + public bool IsFinished() => (m_uState & (byte)TaskState.TASK_STATE_FINISHED) != 0; + public bool IsSuccess() => (m_uState & (byte)TaskState.TASK_STATE_SUCCESS) != 0; + public bool IsGiveUp() => (m_uState & (byte)TaskState.TASK_STATE_GIVEUP) != 0; + public bool IsErrReported() => (m_uState & (byte)TaskState.TASK_STATE_ERR_REPORTED) != 0; + public bool IsAwardNotifyTeam() => (m_uState & (byte)TaskState.TASK_STATE_AWARD_NOTIFY_TEAM) != 0; + public bool IsContributionFinish() => (m_uState & (byte)TaskState.TASK_STATE_CONTRIBUTION_FINISH) != 0; + + // void SetFinished() { m_uState |= TASK_STATE_FINISHED; } + // void ClearFinished() { m_uState &= ~TASK_STATE_FINISHED; } + // void SetSuccess() { m_uState |= TASK_STATE_SUCCESS; } + // void ClearSuccess() { m_uState &= ~TASK_STATE_SUCCESS; } + // void SetGiveUp() { m_uState |= TASK_STATE_GIVEUP; } + // void ClearGiveUp() { m_uState &= ~TASK_STATE_GIVEUP; } + // void SetErrReported() { m_uState |= TASK_STATE_ERR_REPORTED; } + // void ClearErrReported() { m_uState &= ~TASK_STATE_ERR_REPORTED; } + // void SetAwardNotifyTeam() { m_uState |= TASK_STATE_AWARD_NOTIFY_TEAM; } + // void ClearAwardNotifyTeam() { m_uState &= ~TASK_STATE_AWARD_NOTIFY_TEAM; } + // void SetContributionFinish() { m_uState |= TASK_STATE_CONTRIBUTION_FINISH; } + // void ClearContributionFinish() { m_uState &= ~TASK_STATE_CONTRIBUTION_FINISH; } + // + public ATaskTempl GetTempl() { - if (value) _flags |= 0x01; - else _flags &= unchecked((byte)~0x01); + if (m_ulTemplAddr == 0) return null; + return Marshal.PtrToStructure( + new IntPtr(unchecked((long)m_ulTemplAddr)) + ); + // return reinterpret_cast(m_ulTemplAddr); } - } + // const ATaskTempl* GetCap() const { return reinterpret_cast(m_ulCapTemplAddr); } + // const ATaskTempl* GetCapOrSelf() const + // { + // if (m_ulCapTemplAddr) return GetCap(); + // else return GetTempl(); + // } + // bool HasParent() const { return m_ParentIndex != 0xff; } + // bool HasChildren() const { return m_ChildIndex != 0xff; } + // bool IsValid(unsigned char uIndex, unsigned char uMaxCount) const + // { + // if (m_ParentIndex != 0xff) + // { + // if (m_ParentIndex >= uIndex || m_ParentIndex >= uMaxCount) + // return false; + // } + // + // if (m_PrevSblIndex != 0xff) + // { + // if (m_PrevSblIndex >= uIndex || m_PrevSblIndex >= uMaxCount) + // return false; + // } + // + // if (m_NextSblIndex != 0xff) + // { + // if (m_NextSblIndex <= uIndex || m_NextSblIndex >= uMaxCount) + // return false; + // } + // + // if (m_ChildIndex != 0xff) + // { + // if (m_ChildIndex <= uIndex || m_ChildIndex >= uMaxCount) + // return false; + // } + // + // return true; + // } + }; - public byte m_uTitleTaskCount + public class ActiveTaskList { - get => (byte)((_flags & 0xFE) >> 1); - set => _flags = (byte)((_flags & 0x01) | ((value & 0x7F) << 1)); - } + // --- Header Fields --- + public byte[] header = new byte[CECTaskInterface.TASK_ACTIVE_LIST_HEADER_LEN]; - public ActiveTaskEntry[] m_TaskEntries = new ActiveTaskEntry[CECTaskInterface.TASK_ACTIVE_LIST_MAX_LEN]; + public byte m_uTaskCount; // number of tasks + public byte m_uUsedCount; // used count + public ushort m_Version; // version + public byte m_uTopShowTaskCount; // top show task count + public byte m_uListState; // list state + public byte m_uTopHideTaskCount; // top hide task count - // void UpdateTaskMask(unsigned long& ulMask) const; - // void UpdateUsedCount(); - // void RealignTask(ActiveTaskEntry* pEntry, unsigned char uReserve); - // void ClearTask(TaskInterface* pTask, ActiveTaskEntry* pEntry, bool bRemoveItem); - // void RecursiveClearTask(TaskInterface* pTask, ActiveTaskEntry* pEntry, bool bRemoveItem, bool bRemoveAcquired, bool bClearTask); - // void ClearChildrenOf(TaskInterface* pTask, ActiveTaskEntry* pParent, bool bRemoveItem = true); - // ActiveTaskEntry* GetEntry(unsigned long ulId) - // { - // for (unsigned char i = 0; i < m_uTaskCount; i++) - // if (m_TaskEntries[i].m_ID == ulId) - // return &m_TaskEntries[i]; - // - // return NULL; - // } - // void RemoveAll() - // { - // unsigned short ver = m_Version; - // memset(this, 0, sizeof(*this)); - // m_Version = ver; - // } - // bool IsValid() const { return m_uTaskCount <= TASK_ACTIVE_LIST_MAX_LEN; } - // bool IsTimeMarkUpdate() const { return (m_uListState & TLIST_STATE_UPDATE_TIME_MARK) != 0; } - // void SetTimeMarkUpdate() { m_uListState |= TLIST_STATE_UPDATE_TIME_MARK; } - // void ClearTimeMarkUpdate() { m_uListState &= ~TLIST_STATE_UPDATE_TIME_MARK; } - // int GetMaxSimultaneousCount() {return m_uMaxSimultaneousCount ? TASK_MAX_SIMULTANEOUS_COUT : TASK_DEFAULT_MAX_SIMULTANEOUS_COUT;} - // void ExpandMaxSimultaneousCount() {m_uMaxSimultaneousCount = 1;} -}; \ No newline at end of file + private byte _flags; // simulate bitfield (1 bit + 7 bits) + + public bool m_uMaxSimultaneousCount + { + get => (_flags & 0x01) != 0; + set + { + if (value) _flags |= 0x01; + else _flags &= unchecked((byte)~0x01); + } + } + + public byte m_uTitleTaskCount + { + get => (byte)((_flags & 0xFE) >> 1); + set => _flags = (byte)((_flags & 0x01) | ((value & 0x7F) << 1)); + } + + public ActiveTaskEntry[] m_TaskEntries = new ActiveTaskEntry[CECTaskInterface.TASK_ACTIVE_LIST_MAX_LEN]; + + // void UpdateTaskMask(unsigned long& ulMask) const; + // void UpdateUsedCount(); + // void RealignTask(ActiveTaskEntry* pEntry, unsigned char uReserve); + // void ClearTask(TaskInterface* pTask, ActiveTaskEntry* pEntry, bool bRemoveItem); + // void RecursiveClearTask(TaskInterface* pTask, ActiveTaskEntry* pEntry, bool bRemoveItem, bool bRemoveAcquired, bool bClearTask); + // void ClearChildrenOf(TaskInterface* pTask, ActiveTaskEntry* pParent, bool bRemoveItem = true); + // ActiveTaskEntry* GetEntry(unsigned long ulId) + // { + // for (unsigned char i = 0; i < m_uTaskCount; i++) + // if (m_TaskEntries[i].m_ID == ulId) + // return &m_TaskEntries[i]; + // + // return NULL; + // } + // void RemoveAll() + // { + // unsigned short ver = m_Version; + // memset(this, 0, sizeof(*this)); + // m_Version = ver; + // } + // bool IsValid() const { return m_uTaskCount <= TASK_ACTIVE_LIST_MAX_LEN; } + // bool IsTimeMarkUpdate() const { return (m_uListState & TLIST_STATE_UPDATE_TIME_MARK) != 0; } + // void SetTimeMarkUpdate() { m_uListState |= TLIST_STATE_UPDATE_TIME_MARK; } + // void ClearTimeMarkUpdate() { m_uListState &= ~TLIST_STATE_UPDATE_TIME_MARK; } + // int GetMaxSimultaneousCount() {return m_uMaxSimultaneousCount ? TASK_MAX_SIMULTANEOUS_COUT : TASK_DEFAULT_MAX_SIMULTANEOUS_COUT;} + // void ExpandMaxSimultaneousCount() {m_uMaxSimultaneousCount = 1;} + }; +} \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs b/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs index 89bd3962b6..ea577ec432 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs @@ -1,51 +1,715 @@ using UnityEngine; using System.IO; using System.Runtime.InteropServices; +using System; +using BrewMonster; +using ModelRenderer.Scripts.Common; +using PerfectWorld.Scripts.Task; +using UnityEngine.UIElements; namespace BrewMonster.Scripts.Task { - public sealed class TaskConstant + public class TaskTemplConstants { - public const int MAX_OCCUPATIONS = 12; - + public const uint _task_templ_cur_version = 121; public const int MAX_TASK_NAME_LEN = 30; public const int MAX_AWARD_NPC_NUM = 8; public const int MAX_PREM_TASK_COUNT = 20; public const int MAX_MUTEX_TASK_COUNT = 5; + public const int MAX_OCCUPATIONS = 12; // 职业 // Occupations public const int MAX_TEAM_MEM_WANTED = MAX_OCCUPATIONS; public const int MAX_TIMETABLE_SIZE = 24; + public const int TASK_AWARD_MAX_DISPLAY_CHAR_LEN = 64; + public const int MAX_ITEM_WANTED = 10; public const int MAX_AWARD_SCALES = 5; public const int MAX_AWARD_CANDIDATES = 12; public const int MAX_LIVING_SKILLS = 4; - public const int MAX_CONTRIB_MONSTERS = 100; - public const int MAX_AWARD_PQ_RANKING = 32; + public const int MAX_CONTRIB_MONSTERS = 100; // PQ子任务贡献度最大怪物种类 // Maximum monster types for PQ subtask contribution + public const int MAX_AWARD_PQ_RANKING = 32; // PQ子任务奖励最大排名数 // Maximum ranking count for PQ subtask rewards public const int MAX_TITLE_NUM = 10; - public const int MAX_TASKREGION = 8; + + public const int MAX_TASKREGION = 8; // 最大区域个数 // Maximum number of regions + public const int TASK_GENDER_NONE = 0; public const int TASK_GENDER_MALE = 1; public const int TASK_GENDER_FEMALE = 2; + public const int TASK_MAX_PATH = 260; - public const int INVALID_VAL = -1; + public const uint INVALID_VAL = uint.MaxValue; + public const int TASK_MAX_LINE_LEN = TASK_MAX_PATH; + public const int TASK_MAX_VALID_COUNT = 6; - public const int TASK_TREASURE_MAP_SIDE_MULTIPLE = 30; + public const int TASK_TREASURE_MAP_SIDE_MULTIPLE = 30; // 藏宝图边长与小区域边长的比 // Ratio of treasure map side length to small region side length + public const int NUM_SPECIAL_AWARD = 2; + public static readonly int[] TASK_SPECIAL_AWARD = new int[NUM_SPECIAL_AWARD] { 26969, 26970 }; - public readonly long[] task_week_map = - { - 7, - 1, - 2, - 3, - 4, - 5, - 6 - }; + public const uint TASK_PACK_MAGIC = 0x93858361; + + // Race-occupation mapping array + public static readonly uint[] _race_occ_map = new uint[MAX_OCCUPATIONS]; } + public enum DynTaskType + { + enumDTTNone = 0, + enumDTTSpecialAward, + enumDTTNormal, + enumDTTGiftCard, + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct NPC_INFO + { + public uint id; + public short x; + public short y; + public short z; + } + + public class ServerNotificationConstants + { + // 新任务发放 // New task issued + public const int TASK_SVR_NOTIFY_NEW = 1; + + // 任务完毕 // Task completed + public const int TASK_SVR_NOTIFY_COMPLETE = 2; + + // 任务放弃 // Task abandoned + public const int TASK_SVR_NOTIFY_GIVE_UP = 3; + + // 杀怪数量 // Monster kill count + public const int TASK_SVR_NOTIFY_MONSTER_KILLED = 4; + + // 处于得到奖励状态 // In reward receiving state + public const int TASK_SVR_NOTIFY_FINISHED = 5; + + // 错误码 // Error code + public const int TASK_SVR_NOTIFY_ERROR_CODE = 6; + + // 遗忘生活技能 // Forget life skill + public const int TASK_SVR_NOTIFY_FORGET_SKILL = 7; + + // 动态任务时间标记 // Dynamic task time mark + public const int TASK_SVR_NOTIFY_DYN_TIME_MARK = 8; + + // 动态任务数据 // Dynamic task data + public const int TASK_SVR_NOTIFY_DYN_DATA = 9; + + // 特殊奖励信息 // Special reward info + public const int TASK_SVR_NOTIFY_SPECIAL_AWARD = 10; + + // 仓库数据 // Storage data + public const int TASK_SVR_NOTIFY_STORAGE = 11; + + // 显示全局变量 // Display global variables + public const int TASK_SVR_NOTIFY_DIS_GLOBAL_VAL = 12; + + // 藏宝位置 // Treasure location + public const int TASK_SVR_NOTIFY_TREASURE_MAP = 13; + + // 设置任务列表上限 // Set task list limit + public const int TASK_SVR_NOTIFY_SET_TASK_LIMIT = 14; + + // 杀人数量 // Player kill count + public const int TASK_SVR_NOTIFY_PLAYER_KILLED = 15; + } + + public class ClientNotificationConstants + { + // 检查完成 // Check completion + public const int TASK_CLT_NOTIFY_CHECK_FINISH = 1; + + // 检查放弃 // Check abandonment + public const int TASK_CLT_NOTIFY_CHECK_GIVEUP = 2; + + // 到达地点 // Reach location + public const int TASK_CLT_NOTIFY_REACH_SITE = 3; + + // 自动交付 // Auto delivery + public const int TASK_CLT_NOTIFY_AUTO_DELV = 4; + + // 手动触发 // Manual trigger + public const int TASK_CLT_NOTIFY_MANUAL_TRIG = 5; + + // 强制放弃 // Force abandon + public const int TASK_CLT_NOTIFY_FORCE_GIVEUP = 6; + + // 动态任务时间标记 // Dynamic task time mark + public const int TASK_CLT_NOTIFY_DYN_TIMEMARK = 7; + + // 动态任务数据 // Dynamic task data + public const int TASK_CLT_NOTIFY_DYN_DATA = 8; + + // 特殊奖励 // Special reward + public const int TASK_CLT_NOTIFY_SPECIAL_AWARD = 9; + + // 离开地点 // Leave location + public const int TASK_CLT_NOTIFY_LEAVE_SITE = 10; + + // PQ检查初始化 // PQ check initialization + public const int TASK_CLT_NOTIFY_PQ_CHECK_INIT = 11; + + // 仓库 // Storage + public const int TASK_CLT_NOTIFY_STORAGE = 12; + + // 请求宝藏索引 // Request treasure index + public const int TASK_CLT_NOTIFY_REQUEST_TREASURE_INDEX = 14; + + // 15天未登录 // 15 days no login + public const int TASK_CLT_NOTIFY_15DAYS_NOLOGIN = 15; + + // 特殊奖励掩码 // Special reward mask + public const int TASK_CLT_NOTIFY_SPECIAL_AWARD_MASK = 16; + + // 称号任务 // Title task + public const int TASK_CLT_NOTIFY_TITLE_TASK = 17; + + // 选择奖励 // Choose reward + public const int TASK_CLT_NOTIFY_CHOOSE_AWARD = 18; + + // 购买代币商店物品 // Buy token shop item + public const int TASK_CLT_NOTIFY_BUY_TOKENSHOP_ITEM = 20; + + // 通过世界贡献完成任务 // Complete task by world contribution + public const int TASK_CLT_NOTIFY_FINISH_TASK_BY_WORLD_CONTRIBUTION = 21; + + // 移除完成任务 // Remove completed task + public const int TASK_CLT_NOTIFY_RM_FINISH_TASK = 150; + } + + + public static class PlayerNotificationConstants + { + // Notify receiving team member task // 通知接收队员任务 + public const int TASK_PLY_NOTIFY_NEW_MEM_TASK = 1; + + // Whole team fails // 全队失败 + public const int TASK_PLY_NOTIFY_FORCE_FAIL = 2; + + // Whole team succeeds // 全队成功 + public const int TASK_PLY_NOTIFY_FORCE_SUCC = 3; + } + + public static class GlobalDataReasonConstants + { + public const int TASK_GLOBAL_CHECK_RCV_NUM = 1; + public const int TASK_GLOBAL_CHECK_COTASK = 2; + public const int TASK_GLOBAL_CHECK_ADD_MEM = 3; + public const int TASK_GLOBAL_NPC_KILLED_TIME = 4; + public const int TASK_GLOBAL_ADD_TIME_MARK = 5; + public const int TASK_GLOBAL_DEL_TIME_MARK = 6; + public const int TASK_GLOBAL_PROTECT_NPC = 7; + } + + public static class CotaskConditionConstants + { + public const int COTASK_CORRESPOND = 0; + public const int COTASK_ONCE = 1; + } + + // 任务类型 // Task types + public enum ENUM_TASK_TYPE + { + enumTTDaily = 100, // 每日 // Daily + enumTTLevel2, // 修真 // Cultivation + enumTTMajor, // 主线 // Main quest + enumTTBranch, // 支线 // Branch quest + enumTTEvent, // 活动 // Event + enumTTQiShaList, // 七杀榜 // Seven Killers List + enumTTFaction, // 帮派 // Faction + enumTTFunction, // 经营 // Management + enumTTLegend, // 传奇 // Legend + enumTTQuestion, // 答题 // Quiz + + enumTTEnd, + } + + // 完成方式 // Completion methods + public enum TaskCompletionMethod + { + enumTMNone = 0, // 无 // None + enumTMKillNumMonster, // 杀数量怪 // Kill specific number of monsters + enumTMCollectNumArticle, // 获得数量道具 // Collect specific number of items + enumTMTalkToNPC, // 与特定NPC对话 // Talk to specific NPC + enumTMReachSite, // 到达特定地点 // Reach specific location + enumTMWaitTime, // 等待特定时间 // Wait for specific time + enumTMAnswerQuestion, // 选择问答 // Answer questions + enumTMTinyGame, // 小游戏 // Mini game + enumTMProtectNPC, // 保护特定NPC // Protect specific NPC + enumTMNPCReachSite, // NPC到达特定地点 // NPC reaches specific location + enumTMGlobalValOK, // 全局变量满足条件 // Global variable meets condition + enumTMLeaveSite, // 离开特定地点 // Leave specific location + enumTMReachTreasureZone, // 达到藏宝区域 // Reach treasure zone + enumTMKillPlayer, // 杀死玩家 // Kill player + enumTMTransform, // 变身状态 // Transform state + enumTMReachLevel, // 检查等级:普通等级,转生次数,境界等级 // Check level: normal level, reincarnation count, realm level + enumTMSimpleClientTask, // 简单任务,只做客户端验证,目前只验证表情动作 // Simple task, client-side verification only, currently only verifies emote actions + enumTMSimpleClientTaskForceNavi, // 强制移动 // Force movement + } + + // 完成条件 // Completion conditions + public enum TaskFinishType + { + enumTFTDirect = 0, // 直接完成 // Direct completion + enumTFTNPC, // NPC完成 // NPC completion + enumTFTConfirm // 需要确认完成 // Need confirmation to complete + } + + // 奖励方式 // Reward methods + public enum TaskAwardType + { + enumTATNormal = 0, // 普通 // Normal + enumTATEach, // 按杀怪数目、获得物品乘 // Multiply by monster kills, items obtained + enumTATRatio, // 按时间比例 // By time ratio + enumTATItemCount // 按获得物品个数分不同档次 // Different tiers based on number of items obtained + } + + // 任务重复间隔 // Task repeat interval + public enum TaskAwardFreq + { + enumTAFNormal = 0, // 普通 // Normal + enumTAFEachDay, // 每天 // Daily + enumTAFEachWeek, // 每周 // Weekly + enumTAFEachMonth, // 每月 // Monthly + enumTAFEachYear // 每年 // Yearly + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct TASK_PACK_HEADER + { + public uint magic; + public uint version; + public uint item_count; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct ZONE_VERT + { + public float x; + public float y; + public float z; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct PLAYER_WANTED + { + public uint m_ulTemplID; // Player Template ID + public uint m_ulCount; // Count + public uint m_ulLevel; // Level + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct MONSTER_WANTED + { + public uint m_ulMonsterTemplId; // Monster template ID + public uint m_ulMonsterNum; // Number of monsters + public uint m_ulDropItemId; // Drop item ID + public uint m_ulDropItemCount; // Drop item count + [MarshalAs(UnmanagedType.U1)] + public bool m_bDropCmnItem; // Is common item drop + public float m_fDropProb; // Drop probability + [MarshalAs(UnmanagedType.U1)] + public bool m_bKillerLev; // Killer level flag + public int m_iDPH; // Damage per hit + public int m_iDPS; // Damage per second + + public bool Equals(MONSTER_WANTED src) + { + return (m_ulMonsterTemplId == src.m_ulMonsterTemplId && + m_ulMonsterNum == src.m_ulMonsterNum && + m_ulDropItemId == src.m_ulDropItemId && + m_ulDropItemCount == src.m_ulDropItemCount && + m_bDropCmnItem == src.m_bDropCmnItem && + m_fDropProb == src.m_fDropProb && + m_bKillerLev == src.m_bKillerLev); + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct ITEM_WANTED + { + public uint m_ulItemTemplId; + // when check bool -> m_bCommonItem > 0 == true + [MarshalAs(UnmanagedType.U1)] + public bool m_bCommonItem; + public uint m_ulItemNum; + public float m_fProb; + public int m_lPeriod; + + public bool Equals(ITEM_WANTED src) + { + return (m_ulItemTemplId == src.m_ulItemTemplId && + m_bCommonItem == src.m_bCommonItem && + m_ulItemNum == src.m_ulItemNum && + m_lPeriod == src.m_lPeriod); + } + + public string GetLog() + { + return string.Format("ITEM_WANTED: ID={0}, Common={1}, Num={2}, Period={3}", + m_ulItemTemplId, m_bCommonItem, m_ulItemNum, m_lPeriod); + } + + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct TITLE_AWARD + { + public uint m_ulTitleID; + public int m_lPeriod; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct TEAM_MEM_ITEM_WANTED + { + public uint m_ulItemTemplId; + public bool m_bCommonItem; + public uint m_ulItemNum; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct MONSTERS_SUMMONED + { + public uint m_ulMonsterTemplId; + public uint m_ulMonsterNum; + public float m_fSummonProb; + public int m_lPeriod; + + public bool Equals(MONSTERS_SUMMONED src) + { + return (m_ulMonsterTemplId == src.m_ulMonsterTemplId && + m_ulMonsterNum == src.m_ulMonsterNum && + m_fSummonProb == src.m_fSummonProb && + m_lPeriod == src.m_lPeriod); + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct MONSTERS_CONTRIB + { + public uint m_ulMonsterTemplId; // Monster ID // 怪物ID + public int m_iWholeContrib; // Team exclusive contribution // 组队间独享贡献度 + public int m_iShareContrib; // Team shared contribution // 组队间共享贡献度 + public int m_iPersonalWholeContrib; // Personal exclusive contribution // 个人独享贡献度 + + public bool Equals(MONSTERS_CONTRIB src) + { + return (m_ulMonsterTemplId == src.m_ulMonsterTemplId && + m_iWholeContrib == src.m_iWholeContrib && + m_iShareContrib == src.m_iShareContrib && + m_iPersonalWholeContrib == src.m_iPersonalWholeContrib); + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct RANKING_AWARD + { + public uint m_iRankingStart; + public uint m_iRankingEnd; + public bool m_bCommonItem; + public ulong m_ulAwardItemId; + public ulong m_ulAwardItemNum; + public long m_lPeriod; + + public bool Equals(RANKING_AWARD src) + { + return (m_iRankingStart == src.m_iRankingStart && + m_iRankingEnd == src.m_iRankingEnd && + m_bCommonItem == src.m_bCommonItem && + m_ulAwardItemId == src.m_ulAwardItemId && + m_ulAwardItemNum == src.m_ulAwardItemNum && + m_lPeriod == src.m_lPeriod); + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct AWARD_MONSTERS_SUMMONED + { + public uint m_ulMonsterNum; + [MarshalAs(UnmanagedType.U1)] + public bool m_bRandChoose; + public uint m_ulSummonRadius; + [MarshalAs(UnmanagedType.U1)] + public bool m_bDeathDisappear; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskInterfaceConstants.MAX_MONSTER_SUMMONED)] + public MONSTERS_SUMMONED[] m_Monsters; + + public int MarshalBasicData(byte[] pData) + { + int offset = 0; + + pData[offset] = m_bRandChoose ? (byte)1 : (byte)0; + offset++; + + pData[offset] = (byte)m_ulSummonRadius; + offset++; + + pData[offset] = (byte)m_ulMonsterNum; + offset++; + + pData[offset] = m_bDeathDisappear ? (byte)1 : (byte)0; + offset++; + + int sz = Marshal.SizeOf(typeof(MONSTERS_SUMMONED)) * (int)m_ulMonsterNum; + if (sz > 0) + { + // Copy MONSTERS_SUMMONED array to byte array + GCHandle handle = GCHandle.Alloc(m_Monsters, GCHandleType.Pinned); + try + { + IntPtr ptr = handle.AddrOfPinnedObject(); + Marshal.Copy(ptr, pData, offset, sz); + } + finally + { + handle.Free(); + } + offset += sz; + } + + return offset; + } + + public int UnmarshalBasicData(byte[] pData) + { + int offset = 0; + + m_bRandChoose = pData[offset] != 0; + offset++; + + m_ulSummonRadius = pData[offset]; + offset++; + + m_ulMonsterNum = pData[offset]; + offset++; + + m_bDeathDisappear = pData[offset] != 0; + offset++; + + if (m_ulMonsterNum > 0) + { + m_Monsters = new MONSTERS_SUMMONED[m_ulMonsterNum]; + + int sz = Marshal.SizeOf(typeof(MONSTERS_SUMMONED)) * (int)m_ulMonsterNum; + // Copy byte array to MONSTERS_SUMMONED array + for (uint i = 0; i < m_ulMonsterNum; i++) + { + IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MONSTERS_SUMMONED))); + try + { + Marshal.Copy(pData, offset, ptr, Marshal.SizeOf(typeof(MONSTERS_SUMMONED))); + m_Monsters[i] = (MONSTERS_SUMMONED)Marshal.PtrToStructure(ptr, typeof(MONSTERS_SUMMONED)); + } + finally + { + Marshal.FreeHGlobal(ptr); + } + offset += Marshal.SizeOf(typeof(MONSTERS_SUMMONED)); + } + } + + return offset; + } + + public static bool operator ==(AWARD_MONSTERS_SUMMONED a, AWARD_MONSTERS_SUMMONED b) + { + if (a.m_ulMonsterNum != b.m_ulMonsterNum) + { + return false; + } + + for (uint i = 0; i < a.m_ulMonsterNum; ++i) + { + if (!(a.m_Monsters[i].Equals(b.m_Monsters[i]))) + { + return false; + } + } + + return (a.m_bRandChoose == b.m_bRandChoose && + a.m_ulSummonRadius == b.m_ulSummonRadius && + a.m_bDeathDisappear == b.m_bDeathDisappear); + } + + public static bool operator !=(AWARD_MONSTERS_SUMMONED a, AWARD_MONSTERS_SUMMONED b) + { + return !(a == b); + } + + public override bool Equals(object obj) + { + if (obj is AWARD_MONSTERS_SUMMONED) + return this == (AWARD_MONSTERS_SUMMONED)obj; + return false; + } + + public override int GetHashCode() + { + return m_ulMonsterNum.GetHashCode() ^ + m_bRandChoose.GetHashCode() ^ + m_ulSummonRadius.GetHashCode() ^ + m_bDeathDisappear.GetHashCode(); + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct AWARD_PQ_RANKING + { + [MarshalAs(UnmanagedType.U1)] + public bool m_bAwardByProf; + public uint m_ulRankingAwardNum; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_AWARD_PQ_RANKING)] + public RANKING_AWARD[] m_RankingAward; + + public int MarshalBasicData(byte[] pData) + { + int offset = 0; + + pData[offset] = m_bAwardByProf ? (byte)1 : (byte)0; + offset++; + + pData[offset] = (byte)m_ulRankingAwardNum; + offset++; + + int sz = Marshal.SizeOf(typeof(RANKING_AWARD)) * (int)m_ulRankingAwardNum; + if (sz > 0) + { + // Copy RANKING_AWARD array to byte array + GCHandle handle = GCHandle.Alloc(m_RankingAward, GCHandleType.Pinned); + try + { + IntPtr ptr = handle.AddrOfPinnedObject(); + Marshal.Copy(ptr, pData, offset, sz); + } + finally + { + handle.Free(); + } + offset += sz; + } + + return offset; + } + + public int UnmarshalBasicData(byte[] pData) + { + int offset = 0; + + m_bAwardByProf = pData[offset] != 0; + offset++; + + m_ulRankingAwardNum = pData[offset]; + offset++; + + if (m_ulRankingAwardNum > 0) + { + m_RankingAward = new RANKING_AWARD[m_ulRankingAwardNum]; + + int sz = Marshal.SizeOf(typeof(RANKING_AWARD)) * (int)m_ulRankingAwardNum; + // Copy byte array to RANKING_AWARD array + for (uint i = 0; i < m_ulRankingAwardNum; i++) + { + IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(RANKING_AWARD))); + try + { + Marshal.Copy(pData, offset, ptr, Marshal.SizeOf(typeof(RANKING_AWARD))); + m_RankingAward[i] = (RANKING_AWARD)Marshal.PtrToStructure(ptr, typeof(RANKING_AWARD)); + } + finally + { + Marshal.FreeHGlobal(ptr); + } + offset += Marshal.SizeOf(typeof(RANKING_AWARD)); + } + } + + return offset; + } + + public static bool operator ==(AWARD_PQ_RANKING a, AWARD_PQ_RANKING b) + { + if (a.m_bAwardByProf != b.m_bAwardByProf) + { + return false; + } + if (a.m_ulRankingAwardNum != b.m_ulRankingAwardNum) + { + return false; + } + + for (uint i = 0; i < a.m_ulRankingAwardNum; ++i) + { + if (!(a.m_RankingAward[i].Equals(b.m_RankingAward[i]))) + { + return false; + } + } + return true; + } + + public static bool operator !=(AWARD_PQ_RANKING a, AWARD_PQ_RANKING b) + { + return !(a == b); + } + + public override bool Equals(object obj) + { + if (obj is AWARD_PQ_RANKING) + return this == (AWARD_PQ_RANKING)obj; + return false; + } + + public override int GetHashCode() + { + return m_bAwardByProf.GetHashCode() ^ m_ulRankingAwardNum.GetHashCode(); + } + } + + public class TaskTemplUtils + { + /// + /// 必须定义operator == // Must define operator == + /// + /// The type of the objects to compare + /// First object to compare + /// Second object to compare + /// True if both objects are equal or both are null + public static bool CompareTwoPointer(T_NAME p1, T_NAME p2) + { + if (p1 == null && p2 == null) + { + return true; + } + else if (p1 != null && p2 != null) + { + return p1.Equals(p2); + } + else + return false; + } + + public static ushort uint_to_ushort(uint id) + { + return (ushort)(id & 0xFF); + } + + public static void convert_txt(ref ushort[] str, int len, ushort code) + { + for (int i = 0; i < len; i++) + { + str[i] ^= code; + } + } + } + + + + [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct task_tm { public int year; @@ -54,38 +718,391 @@ namespace BrewMonster.Scripts.Task public int hour; public int min; public int wday; - } - - public struct TASK_PACK_HEADER - { - public uint magic; - public uint version; - public int item_count; - } - - public struct MONSTERS_CONTRIB - { - public ulong m_ulMonsterTemplId; // Monster ID - public int m_iWholeContrib; // Team exclusive contribution - public int m_iShareContrib; // Team shared contribution - public int m_iPersonalWholeContrib; // Personal exclusive contribution - - public bool Equals(MONSTERS_CONTRIB src) + + public string GetLog() { - return (m_ulMonsterTemplId == src.m_ulMonsterTemplId && - m_iWholeContrib == src.m_iWholeContrib && - m_iShareContrib == src.m_iShareContrib && - m_iPersonalWholeContrib == src.m_iPersonalWholeContrib); + return string.Format("{0}-{1}-{2} {3}:{4} (wday:{5})", year, month, day, hour, min, wday); } } - public struct ZONE_VERT + // Define task_team_member_info struct required by TEAM_MEM_WANTED + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct task_team_member_info { - public float x; - public float y; - public float z; + public uint m_ulLevel; + public uint m_ulOccupation; + public int m_iForce; + [MarshalAs(UnmanagedType.U1)] + public bool m_bMale; } + // Race-occupation mapping array + public static class TaskTemplMapping + { + public static readonly uint[] _race_occ_map = new uint[TaskTemplConstants.MAX_OCCUPATIONS]; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct TEAM_MEM_WANTED + { + public uint m_ulLevelMin; + public uint m_ulLevelMax; + public uint m_ulRace; + public uint m_ulOccupation; + public uint m_ulGender; + public uint m_ulMinCount; + public uint m_ulMaxCount; + public uint m_ulTask; + public int m_iForce; + // public uint m_ulTeamMemsItemWanted; + // public TEAM_MEM_ITEM_WANTED[] m_TeamMemItemWanted; //[MAX_ITEM_WANTED]; + // public bool m_bJustCheck; + + // Initialize fields with default values to avoid constructor issues + public static TEAM_MEM_WANTED Create() + { + TEAM_MEM_WANTED result = new TEAM_MEM_WANTED(); + result.Init(); + return result; + } + + public bool IsMeetBaseInfo(task_team_member_info pInfo) + { + if (m_ulLevelMin != 0 && pInfo.m_ulLevel < m_ulLevelMin) return false; + + if (m_ulLevelMax != 0 && pInfo.m_ulLevel > m_ulLevelMax) return false; + + if (m_ulRace != 0) + { + if (pInfo.m_ulOccupation >= TaskTemplConstants.MAX_OCCUPATIONS) return false; + if (TaskTemplMapping._race_occ_map[pInfo.m_ulOccupation] != m_ulRace) return false; + } + else if (m_ulOccupation != TaskTemplConstants.INVALID_VAL && pInfo.m_ulOccupation != m_ulOccupation) + return false; + + if (m_iForce != 0) + { + if (m_iForce == -1) + { + if (pInfo.m_iForce == 0) + return false; + } + else if (pInfo.m_iForce != m_iForce) return false; + } + +#if !_TASK_CLIENT + if (m_ulGender == TaskTemplConstants.TASK_GENDER_MALE && !pInfo.m_bMale + || m_ulGender == TaskTemplConstants.TASK_GENDER_FEMALE && pInfo.m_bMale) + return false; +#endif + + return true; + } + + public bool IsMeetCount(uint ulCount) + { + if (m_ulMinCount != 0 && ulCount < m_ulMinCount) return false; + + if (m_ulMaxCount != 0 && ulCount > m_ulMaxCount) return false; + + return true; + } + + public void Init() + { + m_ulLevelMin = 0; + m_ulLevelMax = 0; + m_ulRace = 0; + m_ulOccupation = TaskTemplConstants.INVALID_VAL; + m_ulGender = 0; + m_ulMinCount = 0; + m_ulMaxCount = 0; + m_ulTask = 0; + m_iForce = 0; + // m_ulTeamMemsItemWanted = 0; + // m_TeamMemItemWanted = null; + // m_bJustCheck = false; + } + + public bool IsValid() + { + return !( + m_ulLevelMin == 0 && + m_ulLevelMax == 0 && + m_ulRace == 0 && + m_ulOccupation == TaskTemplConstants.INVALID_VAL && + m_ulGender == 0 && + m_ulMinCount == 0 && + m_ulMaxCount == 0 && + m_ulTask == 0 // && + // m_ulTeamMemsItemWanted == 0 && + // m_TeamMemItemWanted == null && + // m_bJustCheck == false + ); + } + + public static bool operator ==(TEAM_MEM_WANTED a, TEAM_MEM_WANTED b) + { + return ( + a.m_ulLevelMin == b.m_ulLevelMin && + a.m_ulLevelMax == b.m_ulLevelMax && + a.m_ulRace == b.m_ulRace && + a.m_ulOccupation == b.m_ulOccupation && + a.m_ulGender == b.m_ulGender && + a.m_ulMinCount == b.m_ulMinCount && + a.m_ulMaxCount == b.m_ulMaxCount && + a.m_ulTask == b.m_ulTask // && + // a.m_ulTeamMemsItemWanted == b.m_ulTeamMemsItemWanted && + // *a.m_TeamMemItemWanted == *(b.m_TeamMemItemWanted) && + // a.m_bJustCheck == b.m_bJustCheck + ); + } + + public static bool operator !=(TEAM_MEM_WANTED a, TEAM_MEM_WANTED b) + { + return !(a == b); + } + + public override bool Equals(object obj) + { + if (obj is TEAM_MEM_WANTED) + return this == (TEAM_MEM_WANTED)obj; + return false; + } + + public override int GetHashCode() + { + return m_ulLevelMin.GetHashCode() ^ m_ulLevelMax.GetHashCode() ^ m_ulRace.GetHashCode() ^ m_ulOccupation.GetHashCode(); + } + } + + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct AWARD_RATIO_SCALE + { + static uint g_ulNewCount; // Static counter for memory tracking + + // Default constructor not available in C# 9.0, fields are initialized directly + public uint m_ulScales; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_AWARD_SCALES)] + public float[] m_Ratios; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_AWARD_SCALES)] + public AWARD_DATA[] m_Awards; //[MAX_AWARD_SCALES]; + + // Initialize method instead of constructor + public void Initialize() + { + m_ulScales = 0; + m_Ratios = new float[TaskTemplConstants.MAX_AWARD_SCALES]; + m_Awards = null; + +#if TASK_TEMPL_EDITOR + m_Awards = new AWARD_DATA[TaskTemplConstants.MAX_AWARD_SCALES]; + g_ulNewCount++; +#endif + } + + public static bool operator ==(AWARD_RATIO_SCALE a, AWARD_RATIO_SCALE b) + { + if (a.m_ulScales != b.m_ulScales) + { + return false; + } + + for (uint i = 0; i < a.m_ulScales; ++i) + { + // Add null check + if (a.m_Ratios[i] != b.m_Ratios[i] || + (a.m_Awards != null && b.m_Awards != null && i < a.m_Awards.Length && i < b.m_Awards.Length && + !(a.m_Awards[i] == b.m_Awards[i]))) + { + return false; + } + } + return true; + } + + public static bool operator !=(AWARD_RATIO_SCALE a, AWARD_RATIO_SCALE b) + { + return !(a == b); + } + + public override bool Equals(object obj) + { + if (obj is AWARD_RATIO_SCALE) + return this == (AWARD_RATIO_SCALE)obj; + return false; + } + + public override int GetHashCode() + { + return m_ulScales.GetHashCode(); + } + + // Copy constructor equivalent method + public static AWARD_RATIO_SCALE CreateCopy(AWARD_RATIO_SCALE src) + { + AWARD_RATIO_SCALE result = new AWARD_RATIO_SCALE(); + result.m_ulScales = src.m_ulScales; + result.m_Ratios = new float[TaskTemplConstants.MAX_AWARD_SCALES]; + + // Copy the ratios array + for (int i = 0; i < src.m_Ratios.Length && i < TaskTemplConstants.MAX_AWARD_SCALES; i++) + { + result.m_Ratios[i] = src.m_Ratios[i]; + } + +#if !TASK_TEMPL_EDITOR + if (src.m_ulScales > 0) + { + result.m_Awards = new AWARD_DATA[src.m_ulScales]; + g_ulNewCount++; + } +#else + result.m_Awards = new AWARD_DATA[TaskTemplConstants.MAX_AWARD_SCALES]; + g_ulNewCount++; +#endif + + // Copy awards if available + if (src.m_Awards != null && result.m_Awards != null) + { + for (uint i = 0; i < src.m_ulScales && i < result.m_Awards.Length && i < src.m_Awards.Length; i++) + { + result.m_Awards[i] = src.m_Awards[i]; + } + } + + return result; + } + + public bool HasAward() + { + if (m_Awards == null) + return false; + + for (uint i = 0; i < m_ulScales && i < m_Awards.Length; i++) + if (m_Awards[i].HasAward()) + return true; + + return false; + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct AWARD_ITEMS_SCALE + { + static uint g_ulNewCount; // Static counter for memory tracking + + // Default constructor not available in C# 9.0, fields are initialized directly + public uint m_ulScales; + public uint m_ulItemId; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_AWARD_SCALES)] + public uint[] m_Counts; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskTemplConstants.MAX_AWARD_SCALES)] + public AWARD_DATA[] m_Awards; //[MAX_AWARD_SCALES]; + + // Initialize method instead of constructor + public void Initialize() + { + m_ulScales = 0; + m_ulItemId = 0; + m_Counts = new uint[TaskTemplConstants.MAX_AWARD_SCALES]; + m_Awards = null; + +#if TASK_TEMPL_EDITOR + m_Awards = new AWARD_DATA[TaskTemplConstants.MAX_AWARD_SCALES]; + g_ulNewCount++; +#endif + } + + public static bool operator ==(AWARD_ITEMS_SCALE a, AWARD_ITEMS_SCALE b) + { + if (a.m_ulScales != b.m_ulScales) + { + return false; + } + for (uint i = 0; i < a.m_ulScales; ++i) + { + // Add null check + if (a.m_Counts[i] != b.m_Counts[i] || + (a.m_Awards != null && b.m_Awards != null && i < a.m_Awards.Length && i < b.m_Awards.Length && + !(a.m_Awards[i] == b.m_Awards[i]))) + { + return false; + } + } + + return a.m_ulItemId == b.m_ulItemId; + } + + public static bool operator !=(AWARD_ITEMS_SCALE a, AWARD_ITEMS_SCALE b) + { + return !(a == b); + } + + public override bool Equals(object obj) + { + if (obj is AWARD_ITEMS_SCALE) + return this == (AWARD_ITEMS_SCALE)obj; + return false; + } + + public override int GetHashCode() + { + return m_ulScales.GetHashCode() ^ m_ulItemId.GetHashCode(); + } + + // Copy constructor equivalent method + public static AWARD_ITEMS_SCALE CreateCopy(AWARD_ITEMS_SCALE src) + { + AWARD_ITEMS_SCALE result = new AWARD_ITEMS_SCALE(); + result.m_ulScales = src.m_ulScales; + result.m_ulItemId = src.m_ulItemId; + result.m_Counts = new uint[TaskTemplConstants.MAX_AWARD_SCALES]; + + // Copy the counts array + for (int i = 0; i < src.m_Counts.Length && i < TaskTemplConstants.MAX_AWARD_SCALES; i++) + { + result.m_Counts[i] = src.m_Counts[i]; + } + +#if !TASK_TEMPL_EDITOR + if (src.m_ulScales > 0) + { + result.m_Awards = new AWARD_DATA[src.m_ulScales]; + g_ulNewCount++; + } +#else + result.m_Awards = new AWARD_DATA[TaskTemplConstants.MAX_AWARD_SCALES]; + g_ulNewCount++; +#endif + + // Copy awards if available + if (src.m_Awards != null && result.m_Awards != null) + { + for (uint i = 0; i < src.m_ulScales && i < result.m_Awards.Length && i < src.m_Awards.Length; i++) + { + result.m_Awards[i] = src.m_Awards[i]; + } + } + + return result; + } + + public bool HasAward() + { + if (m_Awards == null) + return false; + + for (uint i = 0; i < m_ulScales && i < m_Awards.Length; i++) + if (m_Awards[i].HasAward()) + return true; + + return false; + } + } + + public enum task_tm_type { enumTaskTimeDate = 0, @@ -94,7 +1111,7 @@ namespace BrewMonster.Scripts.Task enumTaskTimeDay }; - + /// /// Completion Method /// @@ -120,6 +1137,42 @@ namespace BrewMonster.Scripts.Task enumTMSimpleClientTaskForceNavi // Force navigation } + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct COMPARE_KEY_VALUE + { + public int nLeftType; + public int lLeftNum; + public int nCompOper; + public int nRightType; + public int lRightNum; + + public static bool operator ==(COMPARE_KEY_VALUE a, COMPARE_KEY_VALUE b) + { + return (a.nLeftType == b.nLeftType && a.lLeftNum == b.lLeftNum && + a.nCompOper == b.nCompOper && a.nRightType == b.nRightType && + a.lRightNum == b.lRightNum); + } + + public static bool operator !=(COMPARE_KEY_VALUE a, COMPARE_KEY_VALUE b) + { + return !(a == b); + } + + public override bool Equals(object obj) + { + if (obj is COMPARE_KEY_VALUE) + return this == (COMPARE_KEY_VALUE)obj; + return false; + } + + public override int GetHashCode() + { + return nLeftType.GetHashCode() ^ lLeftNum.GetHashCode() ^ nCompOper.GetHashCode() ^ + nRightType.GetHashCode() ^ lRightNum.GetHashCode(); + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Task_Region { public ZONE_VERT zvMin; @@ -152,591 +1205,2653 @@ namespace BrewMonster.Scripts.Task { return zvMin.GetHashCode() ^ zvMax.GetHashCode(); } - } - - public struct ATaskTemplFixedData - { - /* Task object properties */ - - // Task ID - public uint m_ID; - // Task name - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskConstant.MAX_TASK_NAME_LEN)] - public ushort[] m_szName; - // Task signature - public bool m_bHasSign; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskConstant.MAX_TASK_NAME_LEN)] - public ushort[] m_pszSignature; - // Task type - public uint m_ulType; - // Time limit - public uint m_ulTimeLimit; - - // Task fails when offline - public bool m_bOfflineFail; - - // Absolute failure time - public bool m_bAbsFail; - public task_tm m_tmAbsFailTime; - - // Do not take items during task validation - public bool m_bItemNotTakeOff; - - // Whether using absolute time - public bool m_bAbsTime; - // Number of time periods - public ulong m_ulTimetable; - // Time method - [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskConstant.MAX_TIMETABLE_SIZE)] - public byte[] m_tmType; - // Start time for delivery - public task_tm[] m_tmStart; // [MAX_TIMETABLE_SIZE] - // End time for delivery - public task_tm[] m_tmEnd; // [MAX_TIMETABLE_SIZE] - // Delivery frequency - public long m_lAvailFrequency; - public long m_lPeriodLimit; - // Execute single subtask - public bool m_bChooseOne; - // Randomly rotate single subtask execution - public bool m_bRandOne; - // Whether subtasks have order - public bool m_bExeChildInOrder; - // Whether parent task fails when subtask fails - public bool m_bParentAlsoFail; - // Whether parent task succeeds when subtask succeeds - public bool m_bParentAlsoSucc; - // Whether task can be abandoned - public bool m_bCanGiveUp; - // Whether task can be repeated - public bool m_bCanRedo; - // Whether task can be redone after failure - public bool m_bCanRedoAfterFailure; - // Clear task on abandonment - public bool m_bClearAsGiveUp; - // Whether recording is needed - public bool m_bNeedRecord; - // Whether task fails when player dies - public bool m_bFailAsPlayerDie; - // Maximum number of receivers - public uint m_ulMaxReceiver; - // Delivery zone - public bool m_bDelvInZone; - public uint m_ulDelvWorld; - public uint m_ulDelvRegionCnt; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskConstant.MAX_TASKREGION)] - public Task_Region[] m_pDelvRegion; - - // Enter region task failure - public bool m_bEnterRegionFail; - public uint m_ulEnterRegionWorld; - public uint m_ulEnterRegionCnt; - //public ZONE_VERT m_EnterRegionMinVert; - //public ZONE_VERT m_EnterRegionMaxVert; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskConstant.MAX_TASKREGION)] - public Task_Region[] m_pEnterRegion; - // Leave region task failure - public bool m_bLeaveRegionFail; - public uint m_ulLeaveRegionWorld; - public uint m_ulLeaveRegionCnt; - //public ZONE_VERT m_LeaveRegionMinVert; - //public ZONE_VERT m_LeaveRegionMaxVert; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = TaskConstant.MAX_TASKREGION)] - public Task_Region[] m_pLeaveRegion; - - // Leave force failure - public bool m_bLeaveForceFail; - - // Transport to specific point - public bool m_bTransTo; - public uint m_ulTransWldId; - public ZONE_VERT m_TransPt; - - // Monster controller - public long m_lMonsCtrl; - public bool m_bTrigCtrl; - - // Auto trigger when conditions are met - public bool m_bAutoDeliver; - - // Whether to display in exclusive UI - public bool m_bDisplayInExclusiveUI; - public bool m_bReadyToNotifyServer; - - // Whether used in token shop - public bool m_bUsedInTokenShop; - - // Death trigger - public bool m_bDeathTrig; - - // Whether clear all acquired items - public bool m_bClearAcquired; - - // Recommended level - public uint m_ulSuitableLevel; - - // Whether to show prompt - public bool m_bShowPrompt; - - // Whether it is a key task - public bool m_bKeyTask; - - // Delivery NPC - public uint m_ulDelvNPC; - - // Award NPC - public uint m_ulAwardNPC; - - // Whether it is a skill task - public bool m_bSkillTask; - - // Whether can be searched - public bool m_bCanSeekOut; - - // Whether show direction - public bool m_bShowDirection; - - // Marriage - public bool m_bMarriage; - - // Change global key/value - public uint m_ulChangeKeyCnt; - public long[] m_plChangeKey; // [TASK_AWARD_MAX_CHANGE_VALUE] - public long[] m_plChangeKeyValue; - public bool[] m_pbChangeType; - - // Fail on scene switch - public bool m_bSwitchSceneFail; - - // Hidden task - public bool m_bHidden; - - // Whether deliver skill - public bool m_bDeliverySkill; - public int m_iDeliveredSkillID; - public int m_iDeliveredSkillLevel; - - // Whether show task completion effect - public bool m_bShowGfxFinished; - - // Whether change player ranking in PQ - public bool m_bChangePQRanking; - - // Compare delivery items with player inventory slots - public bool m_bCompareItemAndInventory; - public uint m_ulInventorySlotNum; - -/////////////////////////////////////////////// PQ Task start - // 是否是PQ任务 - public bool m_bPQTask; - // PQ任务全局变量显示 - public uint m_ulPQExpCnt; - - - - - public uint m_ulNPCToProtect; - public uint m_ulProtectTimeLen; - public uint m_enumMethod; - public uint m_enumFinishType; - - // Required items - public ulong m_ulPremItems; - // public ItemWanted[] m_PremItems; // [MAX_ITEM_WANTED] - public bool m_bShowByItems; - public bool m_bPremItemsAnyOne; - - // Level condition - public ulong m_ulPremise_Lev_Min; - public ulong m_ulPremise_Lev_Max; - public ulong m_bPremCheckMaxHistoryLevel; - public bool m_bShowByLev; - - // Dynamic task type - public string m_DynTaskType; - - // Special award ID, used for events - public ulong m_ulSpecialAward; - // Whether to display in the title task UI - public bool m_bDisplayInTitleTaskUI; - - - + public string GetLog() + { + return $"Min({zvMin.x}, {zvMin.y}, {zvMin.z}) - Max({zvMax.x}, {zvMax.y}, {zvMax.z})"; + } } + public class ATaskTempl { public ATaskTemplFixedData m_FixedData; - + //Hierarchy public ATaskTempl m_pParent; public ATaskTempl m_pPrevSibling; public ATaskTempl m_pNextSibling; public ATaskTempl m_pFirstChild; + private byte m_uDepth; // 深度 // Depth - 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 ushort[] m_pwstrTribute; + + // 发放/验证/执行/奖励对话 // Delivery/Unqualified/Execute/Award talks + public talk_proc m_DelvTaskTalk; // 发放任务对话 // Delivery task talk + public talk_proc m_UnqualifiedTalk; // 不符合条件对话 // Unqualified talk + public talk_proc m_DelvItemTalk; // 发放物品对话 // Deliver item talk + public talk_proc m_ExeTalk; // 执行任务对话 // Execute task talk + public talk_proc m_AwardTalk; // 任务奖励对话 // Award talk + public int m_nSubCount; // 子任务数量 // Subtask count + public byte m_uValidCount; + private uint m_ulMask; // 任务掩码 // Task mask public bool LoadFromBinFile(FileStream fp) { LoadBinary(fp); - // CheckDepth(); + CheckDepth(); return true; } private void LoadBinary(FileStream fp) { LoadFixedDataFromBinFile(fp); -// LoadDescriptionBin(fp); -// LoadTributeBin(fp); + LoadDescriptionBin(fp); + pointerLog += $" After LoadDescriptionBin : {fp.Position}\n"; + LoadTributeBin(fp); + pointerLog += $" After LoadTributeBin : {fp.Position}\n"; -//# ifndef _TASK_CLIENT -// CheckMask(); -//#else -// SyncTaskType(); -//#endif + BMLogger.Log($"---- Pointer Log ---- \n {pointerLog} "); + + // TODO: Check task type consistency + # if _TASK_CLIENT + CheckMask(); + #else + SyncTaskType(); + #endif -// namechar code = (namechar)m_ID; + // namechar code = (namechar)m_ID; -// m_DelvTaskTalk.load(fp); -// convert_talk_text(&m_DelvTaskTalk, code); + // m_DelvTaskTalk.load(fp); + // convert_talk_text(&m_DelvTaskTalk, code); + // 加载并转换发放任务对话 // Load and convert delivery task talk + m_DelvTaskTalk = new talk_proc(); + m_DelvTaskTalk.Read(fp); + convert_talk_text(ref m_DelvTaskTalk, (char)m_FixedData.m_ID); -// m_UnqualifiedTalk.load(fp); -// convert_talk_text(&m_UnqualifiedTalk, code); + // m_UnqualifiedTalk.load(fp); + // convert_talk_text(&m_UnqualifiedTalk, code); + // 加载并转换不符合条件对话 // Load and convert unqualified talk + m_UnqualifiedTalk = new talk_proc(); + m_UnqualifiedTalk.Read(fp); + convert_talk_text(ref m_UnqualifiedTalk, (char)m_FixedData.m_ID); -// m_DelvItemTalk.load(fp); -// convert_talk_text(&m_DelvItemTalk, code); + // m_DelvItemTalk.load(fp); + // convert_talk_text(&m_DelvItemTalk, code); + // 加载并转换发放物品对话 // Load and convert deliver item talk + m_DelvItemTalk = new talk_proc(); + m_DelvItemTalk.Read(fp); + convert_talk_text(ref m_DelvItemTalk, (char)m_FixedData.m_ID); -// m_ExeTalk.load(fp); -// convert_talk_text(&m_ExeTalk, code); + // m_ExeTalk.load(fp); + // convert_talk_text(&m_ExeTalk, code); + // 加载并转换执行任务对话 // Load and convert execute task talk + m_ExeTalk = new talk_proc(); + m_ExeTalk.Read(fp); + convert_talk_text(ref m_ExeTalk, (char)m_FixedData.m_ID); -// m_AwardTalk.load(fp); -// convert_talk_text(&m_AwardTalk, code); + // m_AwardTalk.load(fp); + // convert_talk_text(&m_AwardTalk, code); + // 加载并转换任务奖励对话 // Load and convert award talk + m_AwardTalk = new talk_proc(); + m_AwardTalk.Read(fp); + convert_talk_text(ref m_AwardTalk, (char)m_FixedData.m_ID); -// fread(&m_nSubCount, sizeof(m_nSubCount), 1, fp); + // fread(&m_nSubCount, sizeof(m_nSubCount), 1, fp); + // 读取子任务数量 // Read subtask count + long readBytes = 0; + m_nSubCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); -// for (int i = 0; i < m_nSubCount; i++) -// { -// ATaskTempl* pSub = new ATaskTempl; -// g_ulNewCount++; -// AddSubTaskTempl(pSub); -// pSub->LoadBinary(fp); -// } + // for (int i = 0; i < m_nSubCount; i++) + // { + // ATaskTempl* pSub = new ATaskTempl; + // g_ulNewCount++; + // AddSubTaskTempl(pSub); + // pSub->LoadBinary(fp); + // } + // 上述C++逻辑的C#实现 // C# implementation of the above C++ logic + if (m_nSubCount > 0) + { + for (int i = 0; i < m_nSubCount; i++) + { + var pSub = new ATaskTempl(); + AddSubTaskTempl(pSub); + pSub.LoadBinary(fp); + } + } -// SynchID(); + SynchID(); //return true; } + + #region LoadFixedDataFromBinFile Handle + private bool LoadFixedDataFromBinFile(FileStream fp) { - - ulong i; - long readBytes = 0; - ATaskTemplFixedData fixedData = AAssit.ReadFromBinaryOf(fp, ref readBytes); - - //convert_txt(m_szName, MAX_TASK_NAME_LEN, (namechar)m_ID); - - // m_Award_S = new AWARD_DATA; - // g_ulNewCount++; - // m_Award_F = new AWARD_DATA; - // g_ulNewCount++; - // m_AwByRatio_S = new AWARD_RATIO_SCALE; - // g_ulNewCount++; - // m_AwByRatio_F = new AWARD_RATIO_SCALE; - // g_ulNewCount++; - // m_AwByItems_S = new AWARD_ITEMS_SCALE; - // g_ulNewCount++; - // m_AwByItems_F = new AWARD_ITEMS_SCALE; - // g_ulNewCount++; - // m_tmStart = NULL; - // m_tmEnd = NULL; - // m_plChangeKey = NULL; - // m_plChangeKeyValue = NULL; - // m_pbChangeType = NULL; - // m_PremItems = NULL; - // m_GivenItems = NULL; - // m_TeamMemsWanted= NULL; - // m_ItemsWanted = NULL; - // m_PlayerWanted = NULL; - // m_MonsterWanted = NULL; - // m_pszSignature = NULL; - // m_pszExp = NULL; - // m_pExpArr = NULL; - // m_pTaskChar = NULL; - // m_pszPQExp = NULL; - // m_pPQExpArr = NULL; - // m_MonstersContrib = NULL; - // m_PremTitles = NULL; - - // if (m_bHasSign) + // for (int j = 1; j <= 20; j++) // { - // m_pszSignature = new task_char[MAX_TASK_NAME_LEN]; - // g_ulNewCount++; - // fread(m_pszSignature, sizeof(task_char), MAX_TASK_NAME_LEN, fp); - // convert_txt(m_pszSignature, MAX_TASK_NAME_LEN, (namechar)m_ID); + // Debug.LogError($"==== {j} ==="); + // ConvertFixedData(fp, j); + // Debug.LogError($"=========="); // } + ConvertFixedData(fp, 1); + return true; + } + public void convert_txt(char[] buffer, int len, char code) + { + if (buffer == null) return; + if (len < 0) len = 0; + if (len > buffer.Length) len = buffer.Length; + for (int i = 0; i < len; i++) + { + buffer[i] = (char)(buffer[i] ^ code); + } + } + + public void convert_txt(ushort[] buffer, int len, char code) + { + if (buffer == null) return; + if (len < 0) len = 0; + if (len > buffer.Length) len = buffer.Length; + + for (int i = 0; i < len; i++) + { + buffer[i] = (ushort)(buffer[i] ^ code); + } + } + private string pointerLog = ""; + private void ConvertFixedData(FileStream fp, int x2) + { + long readBytes = 0; + BMLogger.Log($"LoadFixedDataFromBinFile: {fp.Length}"); + ATaskTemplFixedData fixedData = new ATaskTemplFixedData(); + string logContent = ""; + + + var originalPos = fp.Position; + + pointerLog += $" Berfore Read m_ID Position: {fp.Position}\n"; + + // Task ID + fixedData.m_ID = AAssit.ReadFromBinaryOf(fp, ref readBytes); // unsigned long m_ID; + logContent += $"m_ID: {fixedData.m_ID} \n"; + + // Task Name (task_char m_szName[MAX_TASK_NAME_LEN];) + fixedData.m_szName = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TASK_NAME_LEN, ref readBytes); //64 + convert_txt(fixedData.m_szName, TaskTemplConstants.MAX_TASK_NAME_LEN, (char)(fixedData.m_ID)); + logContent += $"m_szName: {ByteToStringUtils.UshortArrayToUnicodeString(fixedData.m_szName)}\n"; //68 + + // Has Signature (bool m_bHasSign;) + fixedData.m_bHasSign = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bHasSign: {fixedData.m_bHasSign}\n"; //68 + + // Signature pointer (task_char* m_pszSignature;) + // Only the pointer address is stored in the binary (skip 4 bytes) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pszSignature: ushort[] and skip 4 bytes \n"; + + + // Task Type (unsigned long m_ulType;) + fixedData.m_ulType = AAssit.ReadFromBinaryOf(fp, ref readBytes);//value 103 + logContent += $"Type: {fixedData.m_ulType}\n"; + + // Time Limit (unsigned long m_ulTimeLimit;) + fixedData.m_ulTimeLimit = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulTimeLimit: {fixedData.m_ulTimeLimit}\n"; + + // Offline Fail (bool m_bOfflineFail;) + fixedData.m_bOfflineFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bOfflineFail: {fixedData.m_bOfflineFail}\n"; + + // Absolute Fail (bool m_bAbsFail;) + fixedData.m_bAbsFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bAbsFail: {fixedData.m_bAbsFail}\n"; + + // Absolute Fail Time (task_tm m_tmAbsFailTime;) + fixedData.m_tmAbsFailTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_tmAbsFailTime.day: {fixedData.m_tmAbsFailTime.day}\n"; + + + // (unsigned long m_ulAbsFailTime;) // commented out in C++ source + + // Item Not Take Off (bool m_bItemNotTakeOff;) + fixedData.m_bItemNotTakeOff = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bItemNotTakeOff: {fixedData.m_bItemNotTakeOff}\n"; + + // Absolute Time (bool m_bAbsTime;) + fixedData.m_bAbsTime = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bAbsTime: {fixedData.m_bAbsTime}\n"; + + // Timetable count (unsigned long m_ulTimetable;) + fixedData.m_ulTimetable = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulTimetable: {fixedData.m_ulTimetable}\n"; + + // Timetable type (char m_tmType[MAX_TIMETABLE_SIZE];) + fixedData.m_tmType = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes); + logContent += $"m_tmType: {fixedData.m_tmType}\n"; + + // Start time pointer (task_tm* m_tmStart; [MAX_TIMETABLE_SIZE]) // if (m_ulTimetable) // { - // m_tmStart = new task_tm[m_ulTimetable]; - // g_ulNewCount++; - // m_tmEnd = new task_tm[m_ulTimetable]; - // g_ulNewCount++; + // m_tmStart = new task_tm[m_ulTimetable]; + // g_ulNewCount++; + // m_tmEnd = new task_tm[m_ulTimetable]; + // g_ulNewCount++; // } + // Start time pointer (task_tm* m_tmStart; [MAX_TIMETABLE_SIZE]) + // Only the pointer address is stored in the binary (skip 4 bytes) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_tmStart: task_tm[] and skip 4 bytes \n"; + + // End time pointer (task_tm* m_tmEnd; [MAX_TIMETABLE_SIZE]) + // Only the pointer address is stored in the binary (skip 4 bytes) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_tmEnd: task_tm[] and skip 4 bytes \n"; + + // Available frequency (long m_lAvailFrequency;) + fixedData.m_lAvailFrequency = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_lAvailFrequency: {fixedData.m_lAvailFrequency}\n"; - // for (i = 0; i < m_ulTimetable; i++) - // { - // fread(&m_tmStart[i], sizeof(task_tm), 1, fp); - // fread(&m_tmEnd[i], sizeof(task_tm), 1, fp); - // } + // Period limit (long m_lPeriodLimit;) + fixedData.m_lPeriodLimit = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_lPeriodLimit: {fixedData.m_lPeriodLimit}\n"; - // if (m_ulChangeKeyCnt) - // { - // m_plChangeKey = new long[m_ulChangeKeyCnt]; - // m_plChangeKeyValue = new long[m_ulChangeKeyCnt]; - // m_pbChangeType = new bool[m_ulChangeKeyCnt]; - // } + // Choose one subtask (bool m_bChooseOne;) + fixedData.m_bChooseOne = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bChooseOne: {fixedData.m_bChooseOne}\n"; - // for (i=0; i(fp, ref readBytes) > 0; + logContent += $"m_bRandOne: {fixedData.m_bRandOne}\n"; - // if (m_ulPQExpCnt) - // { - // m_pszPQExp = new char[m_ulPQExpCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN]; - // memset(m_pszPQExp, 0, m_ulPQExpCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN); + // bool m_bExeChildInOrder; + // Whether subtasks are executed in order + fixedData.m_bExeChildInOrder = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 是否子任务有顺序 // Whether subtasks are executed in order + logContent += $"m_bExeChildInOrder: {fixedData.m_bExeChildInOrder}\n"; - // m_pPQExpArr = new TASK_EXPRESSION[m_ulPQExpCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN]; - // memset(m_pPQExpArr, 0, sizeof(TASK_EXPRESSION)*m_ulPQExpCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN); + // bool m_bParentAlsoFail; + // Whether the parent task fails if this one does + fixedData.m_bParentAlsoFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 失败后是否认为父任务也失败 // Whether the parent task fails if this one does + logContent += $"m_bParentAlsoFail: {fixedData.m_bParentAlsoFail}\n"; - // for (i=0; i(fp, ref readBytes) > 0; // 子任务成功后父任务成功 // Whether parent task succeeds after subtask succeeds + logContent += $"m_bParentAlsoSucc: {fixedData.m_bParentAlsoSucc}\n"; - // if (m_ulMonsterContribCnt) - // { - // m_MonstersContrib = new MONSTERS_CONTRIB[m_ulMonsterContribCnt]; - // g_ulNewCount++; - // } + // Whether this task can be abandoned + // bool m_bCanGiveUp; + fixedData.m_bCanGiveUp = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 能否放弃此任务 // Whether this task can be abandoned + logContent += $"m_bCanGiveUp: {fixedData.m_bCanGiveUp}\n"; - // for (i = 0; i < m_ulMonsterContribCnt; i++) - // { - // MONSTERS_CONTRIB& mc = m_MonstersContrib[i]; - // fread(&mc, sizeof(mc), 1, fp); - // } + // Whether the task can be repeated/completed again + // bool m_bCanRedo; + fixedData.m_bCanRedo = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 是否可重复完成 // Whether the task can be repeated/completed again + logContent += $"m_bCanRedo: {fixedData.m_bCanRedo}\n"; - // // version 80 - // if (m_ulDelvRegionCnt>0) - // { - // m_pDelvRegion = new Task_Region[m_ulDelvRegionCnt]; - // g_ulNewCount++; - // } - // else m_pDelvRegion = NULL; + // Whether task can be repeated after failure + // bool m_bCanRedoAfterFailure; - // for (i=0;i0) - // { - // m_pEnterRegion = new Task_Region[m_ulEnterRegionCnt]; - // g_ulNewCount++; - // } - // else m_pEnterRegion = NULL; + fixedData.m_bCanRedoAfterFailure = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 失败后是否可重新完成 // Whether task can be repeated after failure + logContent += $"m_bCanRedoAfterFailure: {fixedData.m_bCanRedoAfterFailure}\n"; - // for (i=0;i0) - // { - // m_pLeaveRegion = new Task_Region[m_ulLeaveRegionCnt]; - // g_ulNewCount++; - // } - // else m_pLeaveRegion = NULL; + // Give up clears the task + // bool m_bClearAsGiveUp; + fixedData.m_bClearAsGiveUp = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 放弃清空任务 // Give up clears the task + logContent += $"m_bClearAsGiveUp: {fixedData.m_bClearAsGiveUp}\n"; - // for (i=0;i(fp, ref readBytes) > 0; // 是否需要记录 // Whether recording is needed + logContent += $"m_bNeedRecord: {fixedData.m_bNeedRecord}\n"; - // // ÈÎÎñ¿ªÆôÌõ¼þ¼°·½Ê½ - // if (m_ulPremItems) - // { - // m_PremItems = new ITEM_WANTED[m_ulPremItems]; - // g_ulNewCount++; - // } + // Player's death causes failure + // bool m_bFailAsPlayerDie; + fixedData.m_bFailAsPlayerDie = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 玩家被击杀是否认为失败 // Player's death causes failure + logContent += $"m_bFailAsPlayerDie: {fixedData.m_bFailAsPlayerDie}\n"; - // for (i = 0; i < m_ulPremItems; i++) - // { - // ITEM_WANTED& iw = m_PremItems[i]; - // fread(&iw, sizeof(iw), 1, fp); - // } + // Maximum number of receivers + // unsigned long m_ulMaxReceiver; + fixedData.m_ulMaxReceiver = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 接受者上限 // Maximum number of receivers + logContent += $"m_ulMaxReceiver: {fixedData.m_ulMaxReceiver}\n"; - // m_ulGivenCmnCount = 0; - // m_ulGivenTskCount = 0; + // Is in delivery zone + // bool m_bDelvInZone; + fixedData.m_bDelvInZone = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 发放区域 // Is in delivery zone + logContent += $"m_bDelvInZone: {fixedData.m_bDelvInZone}\n"; - // if (m_ulGivenItems) - // { - // m_GivenItems = new ITEM_WANTED[m_ulGivenItems]; - // g_ulNewCount++; - // } + // Delivery world id + // unsigned long m_ulDelvWorld; + fixedData.m_ulDelvWorld = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 发放世界 // Delivery world id + logContent += $"m_ulDelvWorld: {fixedData.m_ulDelvWorld}\n"; - // for (i = 0; i < m_ulGivenItems; i++) - // { - // ITEM_WANTED& iw = m_GivenItems[i]; - // fread(&iw, sizeof(iw), 1, fp); + // Number of delivery regions + // unsigned long m_ulDelvRegionCnt; + fixedData.m_ulDelvRegionCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); // 发放区域计数 // Number of delivery regions + logContent += $"m_ulDelvRegionCnt: {fixedData.m_ulDelvRegionCnt}\n"; - // if (iw.m_bCommonItem) m_ulGivenCmnCount++; - // else m_ulGivenTskCount++; - // } + // Delivery regions pointer (Task_Region* m_pDelvRegion;) + // Only the pointer address is stored in the binary (skip 4 bytes) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pDelvRegion: Task_Region[] and skip 4 bytes \n\n"; - // if (m_bTeamwork) - // { - // if (m_ulTeamMemsWanted) - // { - // m_TeamMemsWanted = new TEAM_MEM_WANTED[m_ulTeamMemsWanted]; - // g_ulNewCount++; - // } + // Enter region fail (bool m_bEnterRegionFail;) + fixedData.m_bEnterRegionFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 进入区域任务失败 // Task fails when entering region + logContent += $"m_bEnterRegionFail: {fixedData.m_bEnterRegionFail}\n\n"; - // for (i = 0; i < m_ulTeamMemsWanted; i++) - // { - // TEAM_MEM_WANTED& tmw = m_TeamMemsWanted[i]; - // fread(&tmw, sizeof(tmw), 1, fp); - // } - // } - // if (m_iPremTitleNumTotal) - // { - // m_PremTitles = new int[m_iPremTitleNumTotal]; - // g_ulNewCount++; - // for (i = 0; i < m_iPremTitleNumTotal; i++) - // { - // fread(&m_PremTitles[i], sizeof(int), 1, fp); - // } - // } + // Enter region world (unsigned long m_ulEnterRegionWorld;) + fixedData.m_ulEnterRegionWorld = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulEnterRegionWorld: {fixedData.m_ulEnterRegionWorld}\n\n"; - // /* ÈÎÎñÍê³ÉµÄ·½Ê½¼°Ìõ¼þ */ + // Enter region count (unsigned long m_ulEnterRegionCnt;) + fixedData.m_ulEnterRegionCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulEnterRegionCnt: {fixedData.m_ulEnterRegionCnt}\n\n"; - // if (m_ulMonsterWanted) - // { - // m_MonsterWanted = new MONSTER_WANTED[m_ulMonsterWanted]; - // g_ulNewCount++; - // } + // Enter region pointer (Task_Region* m_pEnterRegion;) + // Only the pointer address is stored in the binary (skip 4 bytes) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pEnterRegion: Task_Region[] and skip 4 bytes \n\n"; - // for (i = 0; i < m_ulMonsterWanted; i++) - // { - // MONSTER_WANTED& mw = m_MonsterWanted[i]; - // fread(&mw, sizeof(mw), 1, fp); - // } + // Leave region fail (bool m_bLeaveRegionFail;) + fixedData.m_bLeaveRegionFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 离开区域任务失败 // Task fails when leaving region + logContent += $"m_bLeaveRegionFail: {fixedData.m_bLeaveRegionFail}\n\n"; - // if (m_ulPlayerWanted) - // { - // m_PlayerWanted = new PLAYER_WANTED[m_ulPlayerWanted]; - // g_ulNewCount++; - // } - // for (i = 0; i < m_ulPlayerWanted; ++i) - // { - // PLAYER_WANTED& pw = m_PlayerWanted[i]; - // fread(&pw, sizeof(pw), 1, fp); - // } + // Leave region world (unsigned long m_ulLeaveRegionWorld;) + fixedData.m_ulLeaveRegionWorld = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulLeaveRegionWorld: {fixedData.m_ulLeaveRegionWorld}\n\n"; - // if (m_ulItemsWanted) - // { - // m_ItemsWanted = new ITEM_WANTED[m_ulItemsWanted]; - // g_ulNewCount++; - // } + // Leave region count (unsigned long m_ulLeaveRegionCnt;) + fixedData.m_ulLeaveRegionCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulLeaveRegionCnt: {fixedData.m_ulLeaveRegionCnt}\n\n"; - // for (i = 0; i < m_ulItemsWanted; i++) - // { - // ITEM_WANTED& iw = m_ItemsWanted[i]; - // fread(&iw, sizeof(iw), 1, fp); - // } + // Leave region pointer (Task_Region* m_pLeaveRegion;) + // Only the pointer address is stored in the binary (skip 4 bytes) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pLeaveRegion: Task_Region[] and skip 4 bytes \n\n"; - // if (m_ulExpCnt) - // { - // m_pszExp = new char[m_ulExpCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN]; - // memset(m_pszExp, 0, m_ulExpCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN); + // Leave force fail (bool m_bLeaveForceFail;) + fixedData.m_bLeaveForceFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 离开阵营失败 // Fails when leaving force + logContent += $"m_bLeaveForceFail: {fixedData.m_bLeaveForceFail}\n\n"; - // m_pExpArr = new TASK_EXPRESSION[m_ulExpCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN]; - // memset(m_pExpArr, 0, sizeof(TASK_EXPRESSION)*m_ulExpCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN); + // Teleport to specific point (bool m_bTransTo;) + fixedData.m_bTransTo = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; // 传送到特定点 // Teleport to specific point + logContent += $"m_bTransTo: {fixedData.m_bTransTo}\n\n"; - // for (i=0; i(fp, ref readBytes); + logContent += $"m_ulTransWldId: {fixedData.m_ulTransWldId}\n\n"; - // if (m_ulTaskCharCnt) - // { - // m_pTaskChar = new task_char[m_ulTaskCharCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN]; - // memset(m_pTaskChar, 0, sizeof(task_char)*m_ulTaskCharCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN); + // Teleport position (ZONE_VERT m_TransPt;) + fixedData.m_TransPt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_TransPt: ({fixedData.m_TransPt.x}, {fixedData.m_TransPt.y}, {fixedData.m_TransPt.z})\n\n"; + + // Monster controller (long m_lMonsCtrl;) + fixedData.m_lMonsCtrl = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_lMonsCtrl: {fixedData.m_lMonsCtrl}\n\n"; - // for (i=0; i(fp, ref readBytes) > 0; + logContent += $"m_bTrigCtrl: {fixedData.m_bTrigCtrl}\n\n"; - // // version 80 - // if (m_ulReachSiteCnt>0) - // { - // m_pReachSite = new Task_Region[m_ulReachSiteCnt]; - // g_ulNewCount++; - // } - // else m_pReachSite = NULL; + // Auto deliver (bool m_bAutoDeliver;) + fixedData.m_bAutoDeliver = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bAutoDeliver: {fixedData.m_bAutoDeliver}\n\n"; - // for (i=0;i0) - // { - // m_pLeaveSite = new Task_Region[m_ulLeaveSiteCnt]; - // g_ulNewCount++; - // } - // else m_pLeaveSite = NULL; + // Display in exclusive UI (bool m_bDisplayInExclusiveUI;) + fixedData.m_bDisplayInExclusiveUI = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bDisplayInExclusiveUI: {fixedData.m_bDisplayInExclusiveUI}\n\n"; - // for (i=0;i(fp, ref readBytes) > 0; + logContent += $"m_bReadyToNotifyServer: {fixedData.m_bReadyToNotifyServer}\n\n"; - // LoadAwardDataBin(fp, *m_Award_S, _task_templ_cur_version); - // LoadAwardDataBin(fp, *m_Award_F, _task_templ_cur_version); + // Used in token shop (bool m_bUsedInTokenShop;) + fixedData.m_bUsedInTokenShop = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bUsedInTokenShop: {fixedData.m_bUsedInTokenShop}\n\n"; - // LoadAwardDataRatioScale(fp, *m_AwByRatio_S, _task_templ_cur_version); - // LoadAwardDataRatioScale(fp, *m_AwByRatio_F, _task_templ_cur_version); + // Death trigger (bool m_bDeathTrig;) + fixedData.m_bDeathTrig = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bDeathTrig: {fixedData.m_bDeathTrig}\n\n"; - // LoadAwardDataItemsScale(fp, *m_AwByItems_S, _task_templ_cur_version); - // LoadAwardDataItemsScale(fp, *m_AwByItems_F, _task_templ_cur_version); + // Clear acquired (bool m_bClearAcquired;) + fixedData.m_bClearAcquired = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bClearAcquired: {fixedData.m_bClearAcquired}\n\n"; + // Suitable level (uint m_ulSuitableLevel;) + fixedData.m_ulSuitableLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulSuitableLevel: {fixedData.m_ulSuitableLevel}\n\n"; + + // Show prompt (bool m_bShowPrompt;) + fixedData.m_bShowPrompt = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowPrompt: {fixedData.m_bShowPrompt}\n\n"; + + // Key task (bool m_bKeyTask;) + fixedData.m_bKeyTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bKeyTask: {fixedData.m_bKeyTask}\n\n"; + + // Delivery NPC (uint m_ulDelvNPC;) + fixedData.m_ulDelvNPC = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulDelvNPC: {fixedData.m_ulDelvNPC}\n\n"; + + // Award NPC (uint m_ulAwardNPC;) + fixedData.m_ulAwardNPC = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulAwardNPC: {fixedData.m_ulAwardNPC}\n\n"; + + // Skill task (bool m_bSkillTask;) + fixedData.m_bSkillTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bSkillTask: {fixedData.m_bSkillTask}\n\n"; + + // Can seek out (bool m_bCanSeekOut;) + fixedData.m_bCanSeekOut = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bCanSeekOut: {fixedData.m_bCanSeekOut}\n\n"; + + // Show direction (bool m_bShowDirection;) + fixedData.m_bShowDirection = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowDirection: {fixedData.m_bShowDirection}\n\n"; + + // Marriage (bool m_bMarriage;) + fixedData.m_bMarriage = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bMarriage: {fixedData.m_bMarriage}\n\n"; + + // Change global key/value count (uint m_ulChangeKeyCnt;) + fixedData.m_ulChangeKeyCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulChangeKeyCnt: {fixedData.m_ulChangeKeyCnt}\n\n"; + + // Pointers to basic types (int* m_plChangeKey; int* m_plChangeKeyValue; bool* m_pbChangeType;) + // Skip sizeof(int), sizeof(int), sizeof(bool) respectively per conversion rule + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_plChangeKey: int[] pointer, skip 4 bytes (sizeof(int))\n\n"; + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_plChangeKeyValue: int[] pointer, skip 4 bytes (sizeof(int))\n\n"; + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pbChangeType: bool[] pointer, skip 4 byte (sizeof(bool))\n\n"; + + // Switch scene fail (bool m_bSwitchSceneFail;) + fixedData.m_bSwitchSceneFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bSwitchSceneFail: {fixedData.m_bSwitchSceneFail}\n\n"; + + // Hidden (bool m_bHidden;) + fixedData.m_bHidden = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bHidden: {fixedData.m_bHidden}\n\n"; + + // Delivery skill (bool m_bDeliverySkill;) + fixedData.m_bDeliverySkill = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bDeliverySkill: {fixedData.m_bDeliverySkill}\n\n"; + + // Delivered skill ID/Level (int m_iDeliveredSkillID; int m_iDeliveredSkillLevel;) + fixedData.m_iDeliveredSkillID = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iDeliveredSkillID: {fixedData.m_iDeliveredSkillID}\n\n"; + fixedData.m_iDeliveredSkillLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iDeliveredSkillLevel: {fixedData.m_iDeliveredSkillLevel}\n\n"; + + // Show GFX finished (bool m_bShowGfxFinished;) + fixedData.m_bShowGfxFinished = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowGfxFinished: {fixedData.m_bShowGfxFinished}\n\n"; + + // Change PQ ranking (bool m_bChangePQRanking;) + fixedData.m_bChangePQRanking = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bChangePQRanking: {fixedData.m_bChangePQRanking}\n\n"; + + // Compare items and inventory (bool m_bCompareItemAndInventory;) + fixedData.m_bCompareItemAndInventory = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bCompareItemAndInventory: {fixedData.m_bCompareItemAndInventory}\n\n"; + + // Inventory slots (uint m_ulInventorySlotNum;) + fixedData.m_ulInventorySlotNum = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulInventorySlotNum: {fixedData.m_ulInventorySlotNum}\n\n"; + + // PQ task (bool m_bPQTask;) + fixedData.m_bPQTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPQTask: {fixedData.m_bPQTask}\n\n"; + + // PQ expression count (uint m_ulPQExpCnt;) + fixedData.m_ulPQExpCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPQExpCnt: {fixedData.m_ulPQExpCnt}\n\n"; + + // PQ expressions pointer (byte[,] m_pszPQExp;) + // Only the pointer address is stored in the binary (skip 1 bytes) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pszPQExp: byte[,] pointer, skip 4 bytes \n\n"; + + // PQ expression array pointer (TASK_EXPRESSION[,] m_pPQExpArr;) + // Only the pointer address is stored in the binary (skip 4 bytes) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pPQExpArr: TASK_EXPRESSION[,] pointer, skip 4 bytes \n\n"; + + // Is PQ subtask (bool m_bPQSubTask;) + fixedData.m_bPQSubTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPQSubTask: {fixedData.m_bPQSubTask}\n\n"; + + // Clear contribution on start (bool m_bClearContrib;) + fixedData.m_bClearContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bClearContrib: {fixedData.m_bClearContrib}\n\n"; + + // Monster contribution count (uint m_ulMonsterContribCnt;) + fixedData.m_ulMonsterContribCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulMonsterContribCnt: {fixedData.m_ulMonsterContribCnt}\n\n"; + + // Monster contribution pointer (MONSTERS_CONTRIB[] m_MonstersContrib;) + // Only the pointer address is stored in the binary (skip 4 bytes) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_MonstersContrib: MONSTERS_CONTRIB[] pointer, skip 4 bytes \n\n"; + + // Account Task related + fixedData.m_iPremNeedRecordTasksNum = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremNeedRecordTasksNum: {fixedData.m_iPremNeedRecordTasksNum}\n\n"; + + fixedData.m_bShowByNeedRecordTasksNum = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByNeedRecordTasksNum: {fixedData.m_bShowByNeedRecordTasksNum}\n\n"; + + fixedData.m_iPremiseFactionContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremiseFactionContrib: {fixedData.m_iPremiseFactionContrib}\n\n"; + + fixedData.m_bShowByFactionContrib = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByFactionContrib: {fixedData.m_bShowByFactionContrib}\n\n"; + + fixedData.m_bAccountTaskLimit = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bAccountTaskLimit: {fixedData.m_bAccountTaskLimit}\n\n"; + + fixedData.m_bRoleTaskLimit = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bRoleTaskLimit: {fixedData.m_bRoleTaskLimit}\n\n"; + + fixedData.m_ulAccountTaskLimitCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulAccountTaskLimitCnt: {fixedData.m_ulAccountTaskLimitCnt}\n\n"; + + fixedData.m_bLeaveFactionFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bLeaveFactionFail: {fixedData.m_bLeaveFactionFail}\n\n"; + + fixedData.m_bNotIncCntWhenFailed = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bNotIncCntWhenFailed: {fixedData.m_bNotIncCntWhenFailed}\n\n"; + + fixedData.m_bNotClearItemWhenFailed = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bNotClearItemWhenFailed: {fixedData.m_bNotClearItemWhenFailed}\n\n"; + + fixedData.m_bDisplayInTitleTaskUI = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bDisplayInTitleTaskUI: {fixedData.m_bDisplayInTitleTaskUI}\n\n"; + + // Opening conditions + fixedData.m_ucPremiseTransformedForm = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ucPremiseTransformedForm: {fixedData.m_ucPremiseTransformedForm}\n\n"; + + fixedData.m_bShowByTransformed = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByTransformed: {fixedData.m_bShowByTransformed}\n\n"; + + fixedData.m_ulPremise_Lev_Min = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremise_Lev_Min: {fixedData.m_ulPremise_Lev_Min}\n\n"; + + fixedData.m_ulPremise_Lev_Max = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremise_Lev_Max: {fixedData.m_ulPremise_Lev_Max}\n\n"; + + fixedData.m_bPremCheckMaxHistoryLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_bPremCheckMaxHistoryLevel: {fixedData.m_bPremCheckMaxHistoryLevel}\n\n"; + + fixedData.m_bShowByLev = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByLev: {fixedData.m_bShowByLev}\n\n"; + + fixedData.m_bPremCheckReincarnation = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPremCheckReincarnation: {fixedData.m_bPremCheckReincarnation}\n\n"; + + fixedData.m_ulPremReincarnationMin = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremReincarnationMin: {fixedData.m_ulPremReincarnationMin}\n\n"; + + fixedData.m_ulPremReincarnationMax = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremReincarnationMax: {fixedData.m_ulPremReincarnationMax}\n\n"; + + fixedData.m_bShowByReincarnation = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByReincarnation: {fixedData.m_bShowByReincarnation}\n\n"; + + fixedData.m_bPremCheckRealmLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPremCheckRealmLevel: {fixedData.m_bPremCheckRealmLevel}\n\n"; + + fixedData.m_ulPremRealmLevelMin = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremRealmLevelMin: {fixedData.m_ulPremRealmLevelMin}\n\n"; + + fixedData.m_ulPremRealmLevelMax = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremRealmLevelMax: {fixedData.m_ulPremRealmLevelMax}\n\n"; + + fixedData.m_bPremCheckRealmExpFull = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPremCheckRealmExpFull: {fixedData.m_bPremCheckRealmExpFull}\n\n"; + + fixedData.m_bShowByRealmLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByRealmLevel: {fixedData.m_bShowByRealmLevel}\n\n"; + + fixedData.m_ulPremItems = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremItems: {fixedData.m_ulPremItems}\n\n"; + + // PremItems pointer (ITEM_WANTED[] m_PremItems;) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_PremItems: ITEM_WANTED[] pointer, skip 4 bytes \n\n"; + + fixedData.m_bShowByItems = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByItems: {fixedData.m_bShowByItems}\n\n"; + + fixedData.m_bPremItemsAnyOne = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPremItemsAnyOne: {fixedData.m_bPremItemsAnyOne}\n\n"; + + fixedData.m_ulGivenItems = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulGivenItems: {fixedData.m_ulGivenItems}\n\n"; + + fixedData.m_ulGivenCmnCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulGivenCmnCount: {fixedData.m_ulGivenCmnCount}\n\n"; + + fixedData.m_ulGivenTskCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulGivenTskCount: {fixedData.m_ulGivenTskCount}\n\n"; + + // GivenItems pointer (ITEM_WANTED[] m_GivenItems;) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_GivenItems: ITEM_WANTED[] pointer, skip 4 bytes \n\n"; + + fixedData.m_ulPremise_Deposit = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremise_Deposit: {fixedData.m_ulPremise_Deposit}\n\n"; + + fixedData.m_bShowByDeposit = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByDeposit: {fixedData.m_bShowByDeposit}\n\n"; + + fixedData.m_lPremise_Reputation = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_lPremise_Reputation: {fixedData.m_lPremise_Reputation}\n\n"; + + fixedData.m_lPremise_RepuMax = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_lPremise_RepuMax: {fixedData.m_lPremise_RepuMax}\n\n"; + + fixedData.m_bShowByRepu = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByRepu: {fixedData.m_bShowByRepu}\n\n"; + + fixedData.m_ulPremise_Task_Count = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremise_Task_Count: {fixedData.m_ulPremise_Task_Count}\n\n"; + + fixedData.m_ulPremise_Tasks = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_PREM_TASK_COUNT, ref readBytes); + logContent += $"m_ulPremise_Tasks[0..{TaskTemplConstants.MAX_PREM_TASK_COUNT - 1}] loaded\n\n"; + + fixedData.m_bShowByPreTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByPreTask: {fixedData.m_bShowByPreTask}\n\n"; + + fixedData.m_ulPremise_Task_Least_Num = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremise_Task_Least_Num: {fixedData.m_ulPremise_Task_Least_Num}\n\n"; + + fixedData.m_ulPremise_Period = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremise_Period: {fixedData.m_ulPremise_Period}\n\n"; + + fixedData.m_bShowByPeriod = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByPeriod: {fixedData.m_bShowByPeriod}\n\n"; + + fixedData.m_ulPremise_Faction = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremise_Faction: {fixedData.m_ulPremise_Faction}\n\n"; + + fixedData.m_iPremise_FactionRole = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremise_FactionRole: {fixedData.m_iPremise_FactionRole}\n\n"; + + fixedData.m_bShowByFaction = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByFaction: {fixedData.m_bShowByFaction}\n\n"; + + // Gender and occupation restrictions + fixedData.m_ulGender = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulGender: {fixedData.m_ulGender}\n\n"; + + fixedData.m_bShowByGender = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByGender: {fixedData.m_bShowByGender}\n\n"; + + fixedData.m_ulOccupations = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulOccupations: {fixedData.m_ulOccupations}\n\n"; + + fixedData.m_Occupations = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_OCCUPATIONS, ref readBytes); + logContent += $"m_Occupations[0..{TaskTemplConstants.MAX_OCCUPATIONS - 1}] loaded\n\n"; + + fixedData.m_bShowByOccup = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByOccup: {fixedData.m_bShowByOccup}\n\n"; + + // Spouse related + fixedData.m_bPremise_Spouse = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPremise_Spouse: {fixedData.m_bPremise_Spouse}\n\n"; + + fixedData.m_bShowBySpouse = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowBySpouse: {fixedData.m_bShowBySpouse}\n\n"; + + fixedData.m_bPremiseWeddingOwner = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPremiseWeddingOwner: {fixedData.m_bPremiseWeddingOwner}\n\n"; + + fixedData.m_bShowByWeddingOwner = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByWeddingOwner: {fixedData.m_bShowByWeddingOwner}\n\n"; + + // GM and shield user + fixedData.m_bGM = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bGM: {fixedData.m_bGM}\n\n"; + + fixedData.m_bShieldUser = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShieldUser: {fixedData.m_bShieldUser}\n\n"; + + // RMB limits + fixedData.m_bShowByRMB = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByRMB: {fixedData.m_bShowByRMB}\n\n"; + + fixedData.m_ulPremRMBMin = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremRMBMin: {fixedData.m_ulPremRMBMin}\n\n"; + + fixedData.m_ulPremRMBMax = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremRMBMax: {fixedData.m_ulPremRMBMax}\n\n"; + + // Character time + fixedData.m_bCharTime = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bCharTime: {fixedData.m_bCharTime}\n\n"; + + fixedData.m_bShowByCharTime = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByCharTime: {fixedData.m_bShowByCharTime}\n\n"; + + fixedData.m_iCharStartTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iCharStartTime: {fixedData.m_iCharStartTime}\n\n"; + + fixedData.m_iCharEndTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iCharEndTime: {fixedData.m_iCharEndTime}\n\n"; + + fixedData.m_tmCharEndTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_tmCharEndTime.day: {fixedData.m_tmCharEndTime.day}\n\n"; + + fixedData.m_ulCharTimeGreaterThan = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulCharTimeGreaterThan: {fixedData.m_ulCharTimeGreaterThan}\n\n"; + + // Related and mutex tasks + fixedData.m_ulPremise_Cotask = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremise_Cotask: {fixedData.m_ulPremise_Cotask}\n\n"; + + fixedData.m_ulCoTaskCond = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulCoTaskCond: {fixedData.m_ulCoTaskCond}\n\n"; + + fixedData.m_ulMutexTaskCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulMutexTaskCount: {fixedData.m_ulMutexTaskCount}\n\n"; + + fixedData.m_ulMutexTasks = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_MUTEX_TASK_COUNT, ref readBytes); + logContent += $"m_ulMutexTasks[0..{TaskTemplConstants.MAX_MUTEX_TASK_COUNT - 1}] loaded\n\n"; + + // Living skills levels (C++ long -> 4 bytes). Read as int and widen to long + var skillLevelsInt = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_LIVING_SKILLS, ref readBytes); + fixedData.m_lSkillLev = Array.ConvertAll(skillLevelsInt, v => (long)v); + logContent += $"m_lSkillLev[0..{TaskTemplConstants.MAX_LIVING_SKILLS - 1}] loaded\n\n"; + + // Dynamic task type and special award + fixedData.m_DynTaskType = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_DynTaskType: {fixedData.m_DynTaskType}\n\n"; + + fixedData.m_ulSpecialAward = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulSpecialAward: {fixedData.m_ulSpecialAward}\n\n"; + + // Team information + fixedData.m_bTeamwork = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bTeamwork: {fixedData.m_bTeamwork}\n\n"; + + fixedData.m_bRcvByTeam = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bRcvByTeam: {fixedData.m_bRcvByTeam}\n\n"; + + fixedData.m_bSharedTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bSharedTask: {fixedData.m_bSharedTask}\n\n"; + + fixedData.m_bSharedAchieved = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bSharedAchieved: {fixedData.m_bSharedAchieved}\n\n"; + + fixedData.m_bCheckTeammate = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bCheckTeammate: {fixedData.m_bCheckTeammate}\n\n"; + + fixedData.m_fTeammateDist = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_fTeammateDist: {fixedData.m_fTeammateDist}\n\n"; + + fixedData.m_bAllFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bAllFail: {fixedData.m_bAllFail}\n\n"; + + fixedData.m_bCapFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bCapFail: {fixedData.m_bCapFail}\n\n"; + + fixedData.m_bCapSucc = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bCapSucc: {fixedData.m_bCapSucc}\n\n"; + + fixedData.m_fSuccDist = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_fSuccDist: {fixedData.m_fSuccDist}\n\n"; + + fixedData.m_bDismAsSelfFail = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bDismAsSelfFail: {fixedData.m_bDismAsSelfFail}\n\n"; + + fixedData.m_bRcvChckMem = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bRcvChckMem: {fixedData.m_bRcvChckMem}\n\n"; + + fixedData.m_fRcvMemDist = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_fRcvMemDist: {fixedData.m_fRcvMemDist}\n\n"; + + fixedData.m_bCntByMemPos = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bCntByMemPos: {fixedData.m_bCntByMemPos}\n\n"; + + fixedData.m_fCntMemDist = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_fCntMemDist: {fixedData.m_fCntMemDist}\n\n"; + + fixedData.m_bAllSucc = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bAllSucc: {fixedData.m_bAllSucc}\n\n"; + + fixedData.m_bCoupleOnly = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bCoupleOnly: {fixedData.m_bCoupleOnly}\n\n"; + + fixedData.m_bDistinguishedOcc = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bDistinguishedOcc: {fixedData.m_bDistinguishedOcc}\n\n"; + + fixedData.m_ulTeamMemsWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulTeamMemsWanted: {fixedData.m_ulTeamMemsWanted}\n\n"; + + // TEAM_MEM_WANTED pointer array + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_TeamMemsWanted: TEAM_MEM_WANTED[] pointer, skip 4 bytes \n\n"; + + fixedData.m_bShowByTeam = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByTeam: {fixedData.m_bShowByTeam}\n\n"; + + // Premise global key/value + fixedData.m_bPremNeedComp = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPremNeedComp: {fixedData.m_bPremNeedComp}\n\n"; + + fixedData.m_nPremExp1AndOrExp2 = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_nPremExp1AndOrExp2: {fixedData.m_nPremExp1AndOrExp2}\n\n"; + + fixedData.m_Prem1KeyValue = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_Prem1KeyValue loaded\n\n"; + + fixedData.m_Prem2KeyValue = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_Prem2KeyValue loaded\n\n"; + + // Force related + fixedData.m_bPremCheckForce = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPremCheckForce: {fixedData.m_bPremCheckForce}\n\n"; + + fixedData.m_iPremForce = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremForce: {fixedData.m_iPremForce}\n\n"; + + fixedData.m_bShowByForce = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByForce: {fixedData.m_bShowByForce}\n\n"; + + fixedData.m_iPremForceReputation = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremForceReputation: {fixedData.m_iPremForceReputation}\n\n"; + + fixedData.m_bShowByForceReputation = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByForceReputation: {fixedData.m_bShowByForceReputation}\n\n"; + + fixedData.m_iPremForceContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremForceContribution: {fixedData.m_iPremForceContribution}\n\n"; + + fixedData.m_bShowByForceContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByForceContribution: {fixedData.m_bShowByForceContribution}\n\n"; + + fixedData.m_iPremForceExp = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremForceExp: {fixedData.m_iPremForceExp}\n\n"; + + fixedData.m_bShowByForceExp = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByForceExp: {fixedData.m_bShowByForceExp}\n\n"; + + fixedData.m_iPremForceSP = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremForceSP: {fixedData.m_iPremForceSP}\n\n"; + + fixedData.m_bShowByForceSP = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByForceSP: {fixedData.m_bShowByForceSP}\n\n"; + + fixedData.m_iPremForceActivityLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremForceActivityLevel: {fixedData.m_iPremForceActivityLevel}\n\n"; + + fixedData.m_bShowByForceActivityLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByForceActivityLevel: {fixedData.m_bShowByForceActivityLevel}\n\n"; + + // King / Not in team / Titles + fixedData.m_bPremIsKing = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPremIsKing: {fixedData.m_bPremIsKing}\n\n"; + + fixedData.m_bShowByKing = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByKing: {fixedData.m_bShowByKing}\n\n"; + + fixedData.m_bPremNotInTeam = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bPremNotInTeam: {fixedData.m_bPremNotInTeam}\n\n"; + + fixedData.m_bShowByNotInTeam = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByNotInTeam: {fixedData.m_bShowByNotInTeam}\n\n"; + + fixedData.m_iPremTitleNumTotal = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremTitleNumTotal: {fixedData.m_iPremTitleNumTotal}\n\n"; + + fixedData.m_iPremTitleNumRequired = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremTitleNumRequired: {fixedData.m_iPremTitleNumRequired}\n\n"; + + // PremTitles pointer (int[]) + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_PremTitles: int[] pointer, skip 4 bytes \n\n"; + + fixedData.m_bShowByTitle = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByTitle: {fixedData.m_bShowByTitle}\n\n"; + + var premHistoryIdx = AAssit.ReadArrayFromBinary(fp, 2, ref readBytes); + fixedData.m_iPremHistoryStageIndex = premHistoryIdx; + logContent += $"m_iPremHistoryStageIndex[0..1] loaded\n\n"; + + fixedData.m_bShowByHistoryStage = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByHistoryStage: {fixedData.m_bShowByHistoryStage}\n\n"; + + fixedData.m_ulPremGeneralCardCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremGeneralCardCount: {fixedData.m_ulPremGeneralCardCount}\n\n"; + + fixedData.m_bShowByGeneralCard = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByGeneralCard: {fixedData.m_bShowByGeneralCard}\n\n"; + + fixedData.m_iPremGeneralCardRank = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iPremGeneralCardRank: {fixedData.m_iPremGeneralCardRank}\n\n"; + + fixedData.m_ulPremGeneralCardRankCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPremGeneralCardRankCount: {fixedData.m_ulPremGeneralCardRankCount}\n\n"; + + fixedData.m_bShowByGeneralCardRank = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bShowByGeneralCardRank: {fixedData.m_bShowByGeneralCardRank}\n\n"; + + // Completion methods and conditions + fixedData.m_enumMethod = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_enumMethod: {fixedData.m_enumMethod}\n\n"; + + fixedData.m_enumFinishType = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_enumFinishType: {fixedData.m_enumFinishType}\n\n"; + + // Task methods + fixedData.m_ulPlayerWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPlayerWanted: {fixedData.m_ulPlayerWanted}\n\n"; + + // PLAYER_WANTED pointer + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_PlayerWanted: PLAYER_WANTED[] pointer, skip 4 bytes \n\n"; + + fixedData.m_ulMonsterWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulMonsterWanted: {fixedData.m_ulMonsterWanted}\n\n"; + + // MONSTER_WANTED pointer + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_MonsterWanted: MONSTER_WANTED[] pointer, skip 4 bytes \n\n"; + + fixedData.m_ulItemsWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulItemsWanted: {fixedData.m_ulItemsWanted}\n\n"; + + // ITEM_WANTED pointer + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_ItemsWanted: ITEM_WANTED[] pointer, skip 4 bytes \n\n"; + + fixedData.m_ulGoldWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulGoldWanted: {fixedData.m_ulGoldWanted}\n\n"; + + fixedData.m_iFactionContribWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iFactionContribWanted: {fixedData.m_iFactionContribWanted}\n\n"; + + fixedData.m_iFactionExpContribWanted = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iFactionExpContribWanted: {fixedData.m_iFactionExpContribWanted}\n\n"; + + fixedData.m_ulNPCToProtect = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulNPCToProtect: {fixedData.m_ulNPCToProtect}\n\n"; + + fixedData.m_ulProtectTimeLen = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulProtectTimeLen: {fixedData.m_ulProtectTimeLen}\n\n"; + + fixedData.m_ulNPCMoving = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulNPCMoving: {fixedData.m_ulNPCMoving}\n\n"; + + fixedData.m_ulNPCDestSite = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulNPCDestSite: {fixedData.m_ulNPCDestSite}\n\n"; + + // Reach site pointer and counts + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pReachSite: Task_Region[] pointer, skip 4 bytes \n\n"; + + fixedData.m_ulReachSiteCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulReachSiteCnt: {fixedData.m_ulReachSiteCnt}\n\n"; + + fixedData.m_ulReachSiteId = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulReachSiteId: {fixedData.m_ulReachSiteId}\n\n"; + + fixedData.m_ulWaitTime = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulWaitTime: {fixedData.m_ulWaitTime}\n\n"; + + // Treasure map (TREA) + fixedData.m_TreasureStartZone = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_TreasureStartZone: ({fixedData.m_TreasureStartZone.x}, {fixedData.m_TreasureStartZone.y}, {fixedData.m_TreasureStartZone.z})\n\n"; + + fixedData.m_ucZonesNumX = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ucZonesNumX: {fixedData.m_ucZonesNumX}\n\n"; + + fixedData.m_ucZonesNumZ = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ucZonesNumZ: {fixedData.m_ucZonesNumZ}\n\n"; + + fixedData.m_ucZoneSide = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ucZoneSide: {fixedData.m_ucZoneSide}\n\n"; + + // Leave site pointer and counts + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pLeaveSite: Task_Region[] pointer, skip 4 bytes \n\n"; + + fixedData.m_ulLeaveSiteCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulLeaveSiteCnt: {fixedData.m_ulLeaveSiteCnt}\n\n"; + + fixedData.m_ulLeaveSiteId = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulLeaveSiteId: {fixedData.m_ulLeaveSiteId}\n\n"; + + // Finish global key/value + fixedData.m_bFinNeedComp = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bFinNeedComp: {fixedData.m_bFinNeedComp}\n\n"; + + fixedData.m_nFinExp1AndOrExp2 = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_nFinExp1AndOrExp2: {fixedData.m_nFinExp1AndOrExp2}\n\n"; + + fixedData.m_Fin1KeyValue = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_Fin1KeyValue loaded\n\n"; + + fixedData.m_Fin2KeyValue = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_Fin2KeyValue loaded\n\n"; + + // Expressions to display + fixedData.m_ulExpCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulExpCnt: {fixedData.m_ulExpCnt}\n\n"; + + // Pointers for expression storage + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pszExp: byte[,] pointer, skip 4 bytes \n\n"; + + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pExpArr: TASK_EXPRESSION[,] pointer, skip 4 bytes \n\n"; + + // Task char prompts + fixedData.m_ulTaskCharCnt = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulTaskCharCnt: {fixedData.m_ulTaskCharCnt}\n\n"; + + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_pTaskChar: ushort[,] pointer, skip 4 bytes \n\n"; + + // Transformation state + fixedData.m_ucTransformedForm = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ucTransformedForm: {fixedData.m_ucTransformedForm}\n\n"; + + // Level/Reincarnation/Realm + fixedData.m_ulReachLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulReachLevel: {fixedData.m_ulReachLevel}\n\n"; + + fixedData.m_ulReachReincarnationCount = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulReachReincarnationCount: {fixedData.m_ulReachReincarnationCount}\n\n"; + + fixedData.m_ulReachRealmLevel = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulReachRealmLevel: {fixedData.m_ulReachRealmLevel}\n\n"; + + fixedData.m_uiEmotion = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_uiEmotion: {fixedData.m_uiEmotion}\n\n"; + + // Award types and pointers + fixedData.m_ulAwardType_S = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulAwardType_S: {fixedData.m_ulAwardType_S}\n\n"; + + fixedData.m_ulAwardType_F = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulAwardType_F: {fixedData.m_ulAwardType_F}\n\n"; + + // AWARD_DATA pointers + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_Award_S_ptr: AWARD_DATA* pointer, skip 4 bytes \n\n"; + + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_Award_F_ptr: AWARD_DATA* pointer, skip 4 bytes \n\n"; + + // Ratio and items scale pointers + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_AwByRatio_S_ptr: AWARD_RATIO_SCALE* pointer, skip 4 bytes \n\n"; + + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_AwByRatio_F_ptr: AWARD_RATIO_SCALE* pointer, skip 4 bytes \n\n"; + + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_AwByItems_S_ptr: AWARD_ITEMS_SCALE* pointer, skip 4 bytes \n\n"; + + fp.Seek(4, SeekOrigin.Current); + logContent += $"m_AwByItems_F_ptr: AWARD_ITEMS_SCALE* pointer, skip 4 bytes \n\n"; + + // Hierarchy + fixedData.m_ulParent = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulParent: {fixedData.m_ulParent}\n\n"; + + fixedData.m_ulPrevSibling = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulPrevSibling: {fixedData.m_ulPrevSibling}\n\n"; + + fixedData.m_ulNextSibling = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulNextSibling: {fixedData.m_ulNextSibling}\n\n"; + + fixedData.m_ulFirstChild = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_ulFirstChild: {fixedData.m_ulFirstChild}\n\n"; + + // Library tasks + fixedData.m_bIsLibraryTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bIsLibraryTask: {fixedData.m_bIsLibraryTask}\n\n"; + + fixedData.m_fLibraryTasksProbability = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_fLibraryTasksProbability: {fixedData.m_fLibraryTasksProbability}\n\n"; + + fixedData.m_bIsUniqueStorageTask = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + logContent += $"m_bIsUniqueStorageTask: {fixedData.m_bIsUniqueStorageTask}\n\n"; + + fixedData.m_iWorldContribution = AAssit.ReadFromBinaryOf(fp, ref readBytes); + logContent += $"m_iWorldContribution: {fixedData.m_iWorldContribution}\n\n"; + + pointerLog += $" After read Raw of FixedData: {fp.Position} \n"; + + + BMLogger.LogError($" === Task Data {fixedData.m_ID} loaded === \n {logContent} "); + + ConvertPointersOfFixedData(fp, ref fixedData, ref readBytes); + + //fp.Seek(originalPos, SeekOrigin.Begin); + + m_FixedData = fixedData; + return; + } + + private void ConvertPointersOfFixedData(FileStream fp, ref ATaskTemplFixedData fixedData, ref long readBytes) + { + string logContent = ""; + + // C++ pointer: task_char* m_pszSignature; + /*if (m_bHasSign) + { + m_pszSignature = new task_char[MAX_TASK_NAME_LEN]; + g_ulNewCount++; + fread(m_pszSignature, sizeof(task_char), MAX_TASK_NAME_LEN, fp); + convert_txt(m_pszSignature, MAX_TASK_NAME_LEN, (namechar)m_ID); + }*/ + if (fixedData.m_bHasSign) + { + fixedData.m_pszSignature = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TASK_NAME_LEN, ref readBytes); //64 + convert_txt(fixedData.m_pszSignature, TaskTemplConstants.MAX_TASK_NAME_LEN, (char)(fixedData.m_ID)); + logContent += $"m_pszSignature: {ByteToStringUtils.UshortArrayToUnicodeString(fixedData.m_pszSignature)}\n"; //68 + } + else + { + logContent += $"m_pszSignature: {fixedData.m_pszSignature}\n"; + } + + // C++ struct: task_tm* m_tmStart; task_tm* m_tmEnd; + /*if (m_ulTimetable) + { + m_tmStart = new task_tm[m_ulTimetable]; + g_ulNewCount++; + m_tmEnd = new task_tm[m_ulTimetable]; + g_ulNewCount++; + } + + for (i = 0; i < m_ulTimetable; i++) + { + fread(&m_tmStart[i], sizeof(task_tm), 1, fp); + fread(&m_tmEnd[i], sizeof(task_tm), 1, fp); + }*/ + if (fixedData.m_ulTimetable > 0) + { + fixedData.m_tmStart = new task_tm[fixedData.m_ulTimetable]; + fixedData.m_tmEnd = new task_tm[fixedData.m_ulTimetable]; + + string tmStartLog = ""; + string tmEndLog = ""; + + for (int i=0; i < fixedData.m_ulTimetable; i++) + { + fixedData.m_tmStart[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + fixedData.m_tmEnd[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + + tmStartLog += $"{i} = {fixedData.m_tmStart[i].GetLog()} || "; + tmEndLog += $"{i} = {fixedData.m_tmEnd[i].GetLog()} || "; + } + + logContent += $"m_tmStart: {tmStartLog} \n"; + logContent += $"m_tmEnd: {tmEndLog} \n"; + } + + // C++ pointer arrays: long* m_plChangeKey; long* m_plChangeKeyValue; bool* m_pbChangeType; + /*if (m_ulChangeKeyCnt) + { + m_plChangeKey = new long[m_ulChangeKeyCnt]; + m_plChangeKeyValue = new long[m_ulChangeKeyCnt]; + m_pbChangeType = new bool[m_ulChangeKeyCnt]; + } + + for (i=0; i 0) + { + fixedData.m_plChangeKey = new int[fixedData.m_ulChangeKeyCnt]; + fixedData.m_plChangeKeyValue = new int[fixedData.m_ulChangeKeyCnt]; + fixedData.m_pbChangeType = new bool[fixedData.m_ulChangeKeyCnt]; + + string changeKeyLog = ""; + string changeKeyValueLog = ""; + string changeTypeLog = ""; + + for (int i=0; i < fixedData.m_ulChangeKeyCnt; i++) + { + fixedData.m_plChangeKey[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + fixedData.m_plChangeKeyValue[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + fixedData.m_pbChangeType[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes) > 0; + + changeKeyLog += $"{i} = {fixedData.m_plChangeKey[i]} || "; + changeKeyValueLog += $"{i} = {fixedData.m_plChangeKeyValue[i]} || "; + changeTypeLog += $"{i} = {fixedData.m_pbChangeType[i]} || "; + } + + logContent += $"m_plChangeKey: {changeKeyLog} \n"; + logContent += $"m_plChangeKeyValue: {changeKeyValueLog} \n"; + logContent += $"m_pbChangeType: {changeTypeLog} \n"; + } + else + { + logContent += $"m_plChangeKey: {fixedData.m_plChangeKey}\n"; + logContent += $"m_plChangeKeyValue: {fixedData.m_plChangeKeyValue}\n"; + logContent += $"m_pbChangeType: {fixedData.m_pbChangeType}\n"; + } + + + /*if (m_ulPQExpCnt) + { + m_pszPQExp = new char[m_ulPQExpCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN]; + memset(m_pszPQExp, 0, m_ulPQExpCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN); + + m_pPQExpArr = new TASK_EXPRESSION[m_ulPQExpCnt][TASK_AWARD_MAX_DISPLAY_CHAR_LEN]; + memset(m_pPQExpArr, 0, sizeof(TASK_EXPRESSION)*m_ulPQExpCnt*TASK_AWARD_MAX_DISPLAY_CHAR_LEN); + + for (i=0; i 0) + { + int rowCount = (int)fixedData.m_ulPQExpCnt; + int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; + + fixedData.m_pszPQExp = new byte[rowCount, colCount]; + fixedData.m_pPQExpArr = new TASK_EXPRESSION[rowCount, colCount]; + + for (int i = 0; i < rowCount; i++) + { + // Read PQ expression display bytes (length TASK_AWARD_MAX_DISPLAY_CHAR_LEN) + byte[] expBytes = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); + for (int j = 0; j < colCount; j++) + { + fixedData.m_pszPQExp[i, j] = expBytes[j]; + } + + // Read TASK_EXPRESSION array (length TASK_AWARD_MAX_DISPLAY_CHAR_LEN) + for (int j = 0; j < colCount; j++) + { + fixedData.m_pPQExpArr[i, j] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + } + } + + logContent += $"m_pszPQExp and m_pPQExpArr loaded, count: {fixedData.m_ulPQExpCnt} (each {TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN})\n"; + } + else + { + logContent += $"m_pszPQExp: {fixedData.m_pszPQExp}\n"; + logContent += $"m_pPQExpArr: {fixedData.m_pPQExpArr}\n"; + } + + // Convert C++ lines 3866-3896 + if (fixedData.m_ulMonsterContribCnt > 0) + { + fixedData.m_MonstersContrib = new MONSTERS_CONTRIB[fixedData.m_ulMonsterContribCnt]; + string mcLog = ""; + for (int i = 0; i < fixedData.m_ulMonsterContribCnt; i++) + { + fixedData.m_MonstersContrib[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + mcLog += $"{i} = (MonsterId:{fixedData.m_MonstersContrib[i].m_ulMonsterTemplId}) || "; + } + logContent += $"m_MonstersContrib: {mcLog}\n"; + } + else + { + logContent += $"m_MonstersContrib: {fixedData.m_MonstersContrib}\n"; + } + + // C++ lines 3879 - 3890 + if (fixedData.m_ulDelvRegionCnt > 0) + { + fixedData.m_pDelvRegion = new Task_Region[fixedData.m_ulDelvRegionCnt]; + string dLog = ""; + for (int i = 0; i < fixedData.m_ulDelvRegionCnt; i++) + { + fixedData.m_pDelvRegion[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + dLog += $" {i} = (RegionId:{fixedData.m_pDelvRegion[i].GetLog()}) || "; + } + logContent += $"m_pDelvRegion: {dLog}\n"; + } + else + { + fixedData.m_pDelvRegion = null; + logContent += $"m_pDelvRegion: {fixedData.m_pDelvRegion}\n"; + } + + // C++ lines 3891-3902: enter regions + if (fixedData.m_ulEnterRegionCnt > 0) + { + fixedData.m_pEnterRegion = new Task_Region[fixedData.m_ulEnterRegionCnt]; + string eLog = ""; + for (int i = 0; i < fixedData.m_ulEnterRegionCnt; i++) + { + fixedData.m_pEnterRegion[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + eLog += $" {i} = (RegionId:{fixedData.m_pEnterRegion[i].GetLog()}) || "; + } + + logContent += $"m_pEnterRegion: {eLog}\n"; + } + else + { + fixedData.m_pEnterRegion = null; + logContent += $"m_pEnterRegion: {fixedData.m_pEnterRegion}\n"; + } + + // C++ lines 3903-3914: leave regions + if (fixedData.m_ulLeaveRegionCnt > 0) + { + fixedData.m_pLeaveRegion = new Task_Region[fixedData.m_ulLeaveRegionCnt]; + string lLog = ""; + for (int i = 0; i < fixedData.m_ulLeaveRegionCnt; i++) + { + fixedData.m_pLeaveRegion[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + lLog += $" {i} = (RegionId:{fixedData.m_pLeaveRegion[i].GetLog()}) || "; + } + logContent += $"m_pLeaveRegion: {lLog}\n"; + } + else + { + fixedData.m_pLeaveRegion = null; + logContent += $"m_pLeaveRegion: {fixedData.m_pLeaveRegion}\n"; + } + + // C++ lines 3916-3927: premise items + if (fixedData.m_ulPremItems > 0) + { + fixedData.m_PremItems = new ITEM_WANTED[fixedData.m_ulPremItems]; + string premLog = ""; + for (int i = 0; i < fixedData.m_ulPremItems; i++) + { + fixedData.m_PremItems[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + premLog += $" {i} = (Item:{fixedData.m_PremItems[i].m_ulItemTemplId}, Cmn:{fixedData.m_PremItems[i].m_bCommonItem}, Num:{fixedData.m_PremItems[i].m_ulItemNum}) || "; + } + logContent += $"m_PremItems: {premLog}\n"; + } + else + { + fixedData.m_PremItems = null; + logContent += $"m_PremItems: {fixedData.m_PremItems}\n"; + } + + // C++ lines 3929-3945: given items and counts + fixedData.m_ulGivenCmnCount = 0; + fixedData.m_ulGivenTskCount = 0; + if (fixedData.m_ulGivenItems > 0) + { + fixedData.m_GivenItems = new ITEM_WANTED[fixedData.m_ulGivenItems]; + string givenLog = ""; + for (int i = 0; i < fixedData.m_ulGivenItems; i++) + { + fixedData.m_GivenItems[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + if (fixedData.m_GivenItems[i].m_bCommonItem) fixedData.m_ulGivenCmnCount++; + else fixedData.m_ulGivenTskCount++; + givenLog += $" {i} = (Item:{fixedData.m_GivenItems[i].m_ulItemTemplId}, Cmn:{fixedData.m_GivenItems[i].m_bCommonItem}, Num:{fixedData.m_GivenItems[i].m_ulItemNum}) || "; + } + logContent += $"m_GivenItems: {givenLog}\n"; + logContent += $"m_ulGivenCmnCount: {fixedData.m_ulGivenCmnCount}, m_ulGivenTskCount: {fixedData.m_ulGivenTskCount}\n"; + } + else + { + fixedData.m_GivenItems = null; + logContent += $"m_GivenItems: {fixedData.m_GivenItems}\n"; + } + + // C++ lines 3947-3960: team members wanted + if (fixedData.m_bTeamwork) + { + if (fixedData.m_ulTeamMemsWanted > 0) + { + fixedData.m_TeamMemsWanted = new TEAM_MEM_WANTED[fixedData.m_ulTeamMemsWanted]; + string tmwLog = ""; + for (int i = 0; i < fixedData.m_ulTeamMemsWanted; i++) + { + fixedData.m_TeamMemsWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + var v = fixedData.m_TeamMemsWanted[i]; + tmwLog += $" {i} = (Lvl:{v.m_ulLevelMin}-{v.m_ulLevelMax}, Race:{v.m_ulRace}, Occup:{v.m_ulOccupation}, Gender:{v.m_ulGender}, Cnt:{v.m_ulMinCount}-{v.m_ulMaxCount}, Task:{v.m_ulTask}, Force:{v.m_iForce}) || "; + } + logContent += $"m_TeamMemsWanted: {tmwLog}\n"; + } + else + { + fixedData.m_TeamMemsWanted = null; + logContent += $"m_TeamMemsWanted: {fixedData.m_TeamMemsWanted}\n"; + } + } + + // C++ lines 3961-3969: premise titles + if (fixedData.m_iPremTitleNumTotal > 0) + { + fixedData.m_PremTitles = new int[fixedData.m_iPremTitleNumTotal]; + string ptLog = ""; + for (int i = 0; i < fixedData.m_iPremTitleNumTotal; i++) + { + fixedData.m_PremTitles[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + ptLog += $" {i} = {fixedData.m_PremTitles[i]} || "; + } + logContent += $"m_PremTitles: {ptLog}\n"; + } + else + { + fixedData.m_PremTitles = null; + logContent += $"m_PremTitles: {fixedData.m_PremTitles}\n"; + } + + // C++ lines 3973-3983: monster wanted + if (fixedData.m_ulMonsterWanted > 0) + { + fixedData.m_MonsterWanted = new MONSTER_WANTED[fixedData.m_ulMonsterWanted]; + string mwLog = ""; + for (int i = 0; i < fixedData.m_ulMonsterWanted; i++) + { + fixedData.m_MonsterWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + mwLog += $" {i} = (Monster:{fixedData.m_MonsterWanted[i].m_ulMonsterTemplId}, Num:{fixedData.m_MonsterWanted[i].m_ulMonsterNum}) || "; + } + logContent += $"m_MonsterWanted: {mwLog}\n"; + } + else + { + fixedData.m_MonsterWanted = null; + logContent += $"m_MonsterWanted: {fixedData.m_MonsterWanted}\n"; + } + + // C++ lines 3985-3994: player wanted + if (fixedData.m_ulPlayerWanted > 0) + { + fixedData.m_PlayerWanted = new PLAYER_WANTED[fixedData.m_ulPlayerWanted]; + string pwLog = ""; + for (int i = 0; i < fixedData.m_ulPlayerWanted; i++) + { + fixedData.m_PlayerWanted[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + pwLog += $" {i} = (Tpl:{fixedData.m_PlayerWanted[i].m_ulTemplID}, Cnt:{fixedData.m_PlayerWanted[i].m_ulCount}, Lev:{fixedData.m_PlayerWanted[i].m_ulLevel}) || "; + } + 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 = AAssit.ReadArrayFromBinary(fp,TaskTemplConstants.MAX_AWARD_SCALES, ref readBytes); + + // pointerLog += $" After read ad.m_Ratios: {fp.Position} +x: {x} \n"; + + // LOG_DELETE_ARR(ad.m_Awards); + // ad.m_Awards = NULL; + + if (ad.m_ulScales > 0) + { + ad.m_Awards = new AWARD_DATA[ad.m_ulScales]; + for (int i = 0; i < ad.m_ulScales; i++) + { + LoadAwardDataBin(fp, ref ad.m_Awards[i], ulVersion, ref readBytes); + } + //g_ulNewCount++; + } + return true; } - string ConvertTxt(string str, char code) + private bool LoadAwardDataBin(FileStream fp, ref AWARD_DATA ad, uint ulVersion, ref long readBytes) { - char[] chars = str.ToCharArray(); - for (int i = 0; i < chars.Length; i++) + 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) { - chars[i] = (char)(chars[i] ^ code); + 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); + } } - return new string(chars); + 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"; + + ad.m_pTitleAward = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulTitleNum,ref readBytes); + logContent += $" AWARD_DATA.m_pTitleAward : {ad.m_ulTitleNum} elements / {fp.Position} \n"; + + if (ad.m_ulChangeKeyCnt > 0) + { + ad.m_plChangeKey = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulChangeKeyCnt,ref readBytes); + + ad.m_plChangeKeyValue = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulChangeKeyCnt,ref readBytes); + + ad.m_pbChangeType = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulChangeKeyCnt,ref readBytes); + } + logContent += $" AWARD_DATA.m_plChangeKey : {ad.m_ulChangeKeyCnt} elements / {fp.Position} \n"; + logContent += $" AWARD_DATA.m_plChangeKeyValue : {ad.m_ulChangeKeyCnt} elements / {fp.Position} \n"; + logContent += $" AWARD_DATA.m_pbChangeType : {ad.m_ulChangeKeyCnt} elements / {fp.Position} \n"; + + if (ad.m_ulHistoryChangeCnt > 0) + { + //fread(&ad.m_plHistoryChangeKey[i], sizeof(long), 1, fp); + ad.m_plHistoryChangeKey = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulHistoryChangeCnt, ref readBytes); + + //fread(&ad.m_plHistoryChangeKeyValue[i], sizeof(long), 1, fp); + ad.m_plHistoryChangeKeyValue = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulHistoryChangeCnt, ref readBytes); + + //fread(&ad.m_pbHistoryChangeType[i], sizeof(bool), 1, fp); + ad.m_pbHistoryChangeType = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulHistoryChangeCnt,ref readBytes); + } + logContent += $" AWARD_DATA.m_plHistoryChangeKey : {ad.m_ulHistoryChangeCnt} elements / {fp.Position} \n"; + logContent += $" AWARD_DATA.m_plHistoryChangeKeyValue : {ad.m_ulHistoryChangeCnt} elements / {fp.Position} \n"; + logContent += $" AWARD_DATA.m_pbHistoryChangeType : {ad.m_ulHistoryChangeCnt} elements / {fp.Position} \n"; + + ad.m_plDisplayKey = AAssit.ReadArrayFromBinary(fp, (int)ad.m_ulDisplayKeyCnt, ref readBytes); + logContent += $" AWARD_DATA.m_plDisplayKey : {ad.m_ulDisplayKeyCnt} elements / {fp.Position} \n"; + + if (ad.m_ulExpCnt > 0) + { + int rowCount = (int)ad.m_ulExpCnt; + int colCount = TaskTemplConstants.TASK_AWARD_MAX_DISPLAY_CHAR_LEN; + + // 显示全局变量表达式显示字节 // Display bytes for global variable expressions + ad.m_pszExp = new byte[rowCount * colCount]; + ad.m_pExpArr = new TASK_EXPRESSION[rowCount * colCount]; + + for (int row = 0; row < rowCount; row++) + { + byte[] expBytesRow = AAssit.ReadArrayFromBinary(fp, colCount, ref readBytes); + Buffer.BlockCopy(expBytesRow, 0, ad.m_pszExp, row * colCount, colCount); + for (int col = 0; col < colCount; col++) + { + ad.m_pExpArr[row * colCount + col] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + } + } + } + logContent += $" AWARD_DATA.m_pszExp and m_pExpArr : {ad.m_ulExpCnt} rows / {fp.Position} \n"; + + 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; } - public void IncValidCount() { m_uValidCount++; } + 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}"); + // return true; + + if (ic.m_ulAwardItems > 0) + { + ic.m_AwardItems = new ITEM_WANTED[ic.m_ulAwardItems]; + for (int i = 0; i < ic.m_ulAwardItems; i++) + { + ic.m_AwardItems[i] = AAssit.ReadFromBinaryOf(fp, ref readBytes); + ITEM_WANTED iw = ic.m_AwardItems[i]; + + if (iw.m_bCommonItem) ic.m_ulAwardCmnItems++; + else ic.m_ulAwardTskItems++; + + valueLog += $" {i} = (Item:{iw.m_ulItemTemplId}, Cmn:{iw.m_bCommonItem}, Num:{iw.m_ulItemNum}) || "; + } + } + else ic.m_AwardItems = null; + + pointerLog += $" After Read m_ulAwardItems : {fp.Position}\n"; + + //BMLogger.Log($"AWARD_ITEMS_CAND.m_AwardItems[] : {valueLog}" ); + + return true; + } + + private bool LoadAwardMonstersBin(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); + + // for (i=0; i < ms.m_ulMonsterNum; i++) + // { + // MONSTERS_SUMMONED& monster = ms.m_Monsters[i]; + // fread(&monster, sizeof(monster), 1, fp); + // } + ms.m_Monsters = AAssit.ReadArrayFromBinary(fp, (int)ms.m_ulMonsterNum, ref readBytes); + + return true; + } + + private bool LoadAwardPQRankingBin(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 = AAssit.ReadArrayFromBinary(fp, (int)pr.m_ulRankingAwardNum, ref readBytes); + + return true; + } + + #endregion + + // 加载任务描述与确认/拒绝文本 // Load task description and OK/No texts + private bool LoadDescriptionBin(FileStream fp) + { + long readBytes = 0; + string valueLog = ""; + + // Debug.Log($"Id= {m_FixedData.m_ID}"); + + // 读取长度(C++: size_t) // Read length (C++: size_t) + uint len = AAssit.ReadFromBinaryOf(fp, ref readBytes); + // 描述文本(task_char*) // Description text (task_char*) + m_pwstrDescript = new ushort[len + 1]; + m_pwstrDescript[len] = 0; + if (len > 0) + { + // ushort[] tmp = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + // System.Buffer.BlockCopy(tmp, 0, m_pwstrDescript, 0, (int)len * 2); + m_pwstrDescript = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + convert_txt(m_pwstrDescript, (int)len, (char)m_FixedData.m_ID); + } + + valueLog += $" m_pwstrDescript : len = {len} / " + + $"{ ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrDescript) } / " + + $" Pointer = {fp.Position} \n"; + + // OK 文本 // OK text + len = AAssit.ReadFromBinaryOf(fp, ref readBytes); + m_pwstrOkText = new ushort[len + 1]; + m_pwstrOkText[len] = 0; + if (len > 0) + { + // ushort[] tmp = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + // System.Buffer.BlockCopy(tmp, 0, m_pwstrOkText, 0, (int)len * 2); + m_pwstrOkText = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + convert_txt(m_pwstrOkText, (int)len, (char)m_FixedData.m_ID); + } + + + valueLog += $" m_pwstrOkText : { ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrOkText) } \n"; + + // NO 文本 // No text + len = AAssit.ReadFromBinaryOf(fp, ref readBytes); + m_pwstrNoText = new ushort[len + 1]; + m_pwstrNoText[len] = 0; + if (len > 0) + { + // ushort[] tmp = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + // System.Buffer.BlockCopy(tmp, 0, m_pwstrNoText, 0, (int)len * 2); + m_pwstrNoText = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + convert_txt(m_pwstrNoText, (int)len, (char)m_FixedData.m_ID); + } + + + valueLog += $" m_pwstrNoText : { ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrNoText) } \n"; + + BMLogger.LogError( $" ---- Data of Task Description ---- \n {valueLog} " ); + + return true; + } + + private bool LoadTributeBin(FileStream fp) + { + long readBytes = 0; + + // size_t len; + // len = 0; + // fread(&len, sizeof(len), 1, fp); + uint len = AAssit.ReadFromBinaryOf(fp, ref readBytes); + + // m_FixedData.m_pwstrTribute = new task_char[len+1]; + // m_pwstrTribute[len] = L'\0'; + m_pwstrTribute = new ushort[len + 1]; + m_pwstrTribute[len] = 0; + if (len > 0) + { + // fread(m_pwstrTribute, sizeof(task_char), len, fp); + // convert_txt(m_pwstrTribute, len, (namechar)m_ID); + + m_pwstrTribute = AAssit.ReadArrayFromBinary(fp, (int)len, ref readBytes); + convert_txt(m_pwstrTribute, (int)len, (char)m_FixedData.m_ID); + } + + BMLogger.Log($" --- m_pwstrTribute ---- \n " + + $" Len : {len} \n " + + $" content: {ByteToStringUtils.UshortArrayToUnicodeString(m_pwstrTribute)}"); + return true; + } + + #region convert from c++ to cs + + // private bool LoadFixedDataFromBinFile(FileStream fp) + // { + + // long readBytes = 0; + // BMLogger.Log($"LoadFixedDataFromBinFile: {fp.Length}"); + + // ATaskTemplFixedData fixedData; + + // // * Important Note: + // // + In C++: "unsigned long" → corresponds to "uint" in C# + // // + "bool" in C++ is 1 byte (while C# bool is also 1 byte in struct layout, but not in file IO) + // // + wchar_t on Windows = 2 bytes + // // + When reading binary data, we must match the original C++ memory layout exactly. + + + // // ------------------------------------------------------------ + // // Case 1: "Normal" value type variable + // // ------------------------------------------------------------ + // // These are directly stored scalar values (no arrays, no pointers, no user-defined struct). + // // Example: bool m_bHasSign; unsigned long m_ID; + // // Originally in C++: unsigned long m_ID; + // // → Read value and asign value to the field + // fixedData.m_ID = AAssist.ReadFromBinaryOf(fp, ref readBytes); + + + // // ------------------------------------------------------------ + // // Case 2: Fixed-size array (memory already allocated inline) + // // ------------------------------------------------------------ + // // These have a known constant size in C++, usually defined by a macro. + // // Example: task_char m_szName[MAX_TASK_NAME_LEN]; + // // char m_tmType[MAX_TIMETABLE_SIZE]; + // // → request write here + // // Example usage: + // //read array from binary to assign value to the field + // fixedData.m_tmStart = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes); + // fixedData.m_tmEnd = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TIMETABLE_SIZE, ref readBytes); + + + // // ------------------------------------------------------------ + // // Case 3: Pointer to user-defined type or string + // // ------------------------------------------------------------ + // // These fields in C++ store only the pointer address, not the actual object. + // // Example: task_char* m_pszSignature; + // // originally in C++: task_char* m_pszSignature; + // // → Skip pointer size, since the content is not inlined. + // // fp.Seek(IntPtr.Size, SeekOrigin.Current); + // fp.Seek(4, SeekOrigin.Current); + + // // ------------------------------------------------------------ + // // Case 4: User-defined struct (not pointer) + // // ------------------------------------------------------------ + // // Skip the full size of the struct in the binary stream. + // // **Important:** check the struct's internal members and padding + // // to calculate the correct size, do not rely on hardcoded numbers. + // // + // // Example: + // // task_tm m_tmAbsFailTime; // inline struct + // // → Skip sizeof(task_tm) bytes. + // fp.Seek(24, SeekOrigin.Current); // Example for Windows/MSVC + + // //case pointer không được define kích thước trước và là kiểu dữ liệu cơ bản => skip tùy theo kích thước của kiểu dữ liệu cơ bản + // // ví dụ: ushort* m_pszSignature => skip 2 bytes + // //request: hoàn thiện rule + + // // ------------------------------------------------------------ + // // Case 5: Pointer to basic type (size not predefined) + // // ------------------------------------------------------------ + // // If a field is a pointer to a basic type (e.g., ushort*, int*, float*), + // // the pointer itself is stored inline, but the pointed-to data is not. + // // When reading binary, skip the size of the basic type (not the pointer address). + // // + // // Example: + // // ushort* m_pszSignature; // skip 2 bytes (size of ushort) + // fp.Seek(2, SeekOrigin.Current); // skip 1 element of the basic type + + // return true; + // } + // this convert from c++ to cs + + //*important note: + // + in c++: unsigned long => will be uint in cs; + // + + // Case 1: convert from "normal" variable => asign value to the field + // Excample: bool *m_pbChangeType; unsigned long m_ID; + // originally this line in c++: unsigned long m_ID; + // fixedData.m_ID = AAssit.ReadFromBinaryOf(fp, ref readBytes); + + // Case 2: convert from variable what already defined size of memories => skip the size of the variable + // Excample: task_char m_szName[MAX_TASK_NAME_LEN]; char m_tmType[MAX_TIMETABLE_SIZE]; => in this example, MAX_TASK_NAME_LEN and MAX_TIMETABLE_SIZE are already defined size of memories. + // originally this line in c++: task_char m_szName[MAX_TASK_NAME_LEN]; + // fp.Seek(TaskTemplConstants.MAX_TASK_NAME_LEN, SeekOrigin.Current); + + // Case 3: convert from variable what is user defination and it is pointer => skip 2 bytes + // Excample: task_char* m_pszSignature; (task_char is defined by user) + // originally this line in c++: task_char* m_pszSignature; + // fp.Seek(2, SeekOrigin.Current); + + // Case 4: convert from variable what is user defination and it is pointer => skip 4 bytes + // Excample: task_char* m_pszSignature; (task_char is defined by user) + // originally this line in c++: task_char* m_pszSignature; + // fp.Seek(4, SeekOrigin.Current); + + // fixedData.m_ID = AAssit.ReadFromBinaryOf(fp, ref readBytes); + // fixedData.m_szName = AAssit.ReadArrayFromBinary(fp, TaskTemplConstants.MAX_TASK_NAME_LEN, ref readBytes); + // TaskTemplUtils.convert_txt(ref fixedData.m_szName, TaskTemplConstants.MAX_TASK_NAME_LEN, TaskTemplUtils.uint_to_ushort(fixedData.m_ID)); + // BMLogger.Log($"LoadFixedDataFromBinFile: ID {fixedData.m_ID} Name {ByteToStringUtils.UshortArrayToCP936String(fixedData.m_szName)}"); + // fixedData.m_bHasSign = AAssit.ReadFromBinaryOf(fp, ref readBytes); + + + + // ATaskTemplFixedData fixedData = AAssit.ReadFromBinaryOf(fp, ref readBytes); + + //convert_txt(m_szName, MAX_TASK_NAME_LEN, (namechar)m_ID); + + // m_Award_S = new AWARD_DATA; + // g_ulNewCount++; + // m_Award_F = new AWARD_DATA; + // g_ulNewCount++; + // m_AwByRatio_S = new AWARD_RATIO_SCALE; + // g_ulNewCount++; + // m_AwByRatio_F = new AWARD_RATIO_SCALE; + // g_ulNewCount++; + // m_AwByItems_S = new AWARD_ITEMS_SCALE; + // g_ulNewCount++; + // m_AwByItems_F = new AWARD_ITEMS_SCALE; + // g_ulNewCount++; + // m_tmStart = NULL; + // m_tmEnd = NULL; + // m_plChangeKey = NULL; + // m_plChangeKeyValue = NULL; + // m_pbChangeType = NULL; + // m_PremItems = NULL; + // m_GivenItems = NULL; + // m_TeamMemsWanted= NULL; + // m_ItemsWanted = NULL; + // m_PlayerWanted = NULL; + // m_MonsterWanted = NULL; + // m_pszSignature = NULL; + // m_pszExp = NULL; + // m_pExpArr = NULL; + // m_pTaskChar = NULL; + // m_pszPQExp = NULL; + // m_pPQExpArr = NULL; + // m_MonstersContrib = NULL; + // m_PremTitles = NULL; + + // if (m_bHasSign) + // { + // m_pszSignature = new task_char[MAX_TASK_NAME_LEN]; + // g_ulNewCount++; + // fread(m_pszSignature, sizeof(task_char), MAX_TASK_NAME_LEN, fp); + // convert_txt(m_pszSignature, MAX_TASK_NAME_LEN, (namechar)m_ID); + // } + + // if (m_ulTimetable) + // { + // m_tmStart = new task_tm[m_ulTimetable]; + // g_ulNewCount++; + // m_tmEnd = new task_tm[m_ulTimetable]; + // g_ulNewCount++; + // } + + // for (i = 0; i < m_ulTimetable; i++) + // { + // fread(&m_tmStart[i], sizeof(task_tm), 1, fp); + // fread(&m_tmEnd[i], sizeof(task_tm), 1, fp); + // } + + // if (m_ulChangeKeyCnt) + // { + // m_plChangeKey = new long[m_ulChangeKeyCnt]; + // m_plChangeKeyValue = new long[m_ulChangeKeyCnt]; + // m_pbChangeType = new bool[m_ulChangeKeyCnt]; + // } + + // for (i=0; i0) + // { + // m_pDelvRegion = new Task_Region[m_ulDelvRegionCnt]; + // g_ulNewCount++; + // } + // else m_pDelvRegion = NULL; + + // for (i=0;i0) + // { + // m_pEnterRegion = new Task_Region[m_ulEnterRegionCnt]; + // g_ulNewCount++; + // } + // else m_pEnterRegion = NULL; + + // for (i=0;i0) + // { + // m_pLeaveRegion = new Task_Region[m_ulLeaveRegionCnt]; + // g_ulNewCount++; + // } + // else m_pLeaveRegion = NULL; + + // for (i=0;i0) + // { + // m_pReachSite = new Task_Region[m_ulReachSiteCnt]; + // g_ulNewCount++; + // } + // else m_pReachSite = NULL; + + // for (i=0;i0) + // { + // m_pLeaveSite = new Task_Region[m_ulLeaveSiteCnt]; + // g_ulNewCount++; + // } + // else m_pLeaveSite = NULL; + + // for (i=0;i ushort[64] + if (talk.text != null) + { + convert_txt(talk.text, talk.text.Length, code); + } + + if (talk.windows == null) return; + + for (int i = 0; i < talk.num_window && i < talk.windows.Length; i++) + { + var win = talk.windows[i]; + if (win.talk_text != null && win.talk_text_len > 0) + { + int len = Math.Min(win.talk_text_len, win.talk_text.Length); + convert_txt(win.talk_text, len, code); + } + + if (win.options == null) continue; + + for (int j = 0; j < win.num_option && j < win.options.Length; j++) + { + var o = win.options[j]; + if (o.text != null) + { + convert_txt(o.text, o.text.Length, code); + } + } + } + } + + + private void CheckMask() + { + // 根据完成方式设置掩码 // Set mask according to completion method + uint method = m_FixedData.m_enumMethod; + + if (method == (uint)TaskMethod.enumTMKillNumMonster) + m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_KILL_MONSTER; + else if (method == (uint)TaskMethod.enumTMCollectNumArticle) + m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_COLLECT_ITEM; + else if (method == (uint)TaskMethod.enumTMTalkToNPC) + m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_TALK_TO_NPC; + else if (method == (uint)TaskMethod.enumTMKillPlayer) + m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_KILL_PLAYER; + + // PQ子任务使用对应掩码 // PQ subtask uses corresponding mask + if (m_FixedData.m_bPQSubTask) + m_ulMask = (uint)TaskInterfaceConstants.TASK_MASK_KILL_PQ_MONSTER; + } + + // 同步任务类型 // Sync task type + private ATaskTempl GetTopTask() + { + ATaskTempl pTop = this; + while (pTop.m_pParent != null) + { + pTop = pTop.m_pParent; + } + return pTop; + } + + // 同步任务类型 // Sync task type + private void SyncTaskType() + { + ATaskTempl pTop = GetTopTask(); + if (pTop != null && !ReferenceEquals(pTop, this)) + { + m_FixedData.m_ulType = pTop.m_FixedData.m_ulType; + } + } + + // 同步层级ID // Synchronize hierarchy IDs + private void SynchID() + { + m_FixedData.m_ulParent = (m_pParent != null) ? m_pParent.m_FixedData.m_ID : 0u; + m_FixedData.m_ulNextSibling = (m_pNextSibling != null) ? m_pNextSibling.m_FixedData.m_ID : 0u; + m_FixedData.m_ulPrevSibling = (m_pPrevSibling != null) ? m_pPrevSibling.m_FixedData.m_ID : 0u; + m_FixedData.m_ulFirstChild = (m_pFirstChild != null) ? m_pFirstChild.m_FixedData.m_ID : 0u; + if (m_pFirstChild != null) m_FixedData.m_enumMethod = (uint)TaskMethod.enumTMNone; + } + + // 添加子任务到层级结构 // Add sub task to hierarchy + private void AddSubTaskTempl(ATaskTempl pSub) + { + if (pSub == null) return; + pSub.m_pParent = this; + if (m_pFirstChild == null) + { + m_pFirstChild = pSub; + return; + } + + // 追加到兄弟链表末尾 // Append to end of sibling list + var last = m_pFirstChild; + while (last.m_pNextSibling != null) + { + last = last.m_pNextSibling; + } + last.m_pNextSibling = pSub; + pSub.m_pPrevSibling = last; + } + + // 检查并累加深度 // Check and accumulate depth + private void CheckDepth() + { + ATaskTempl pChild = m_pFirstChild; + byte uDepthLocal = 0; + bool bMaxChildDepth = m_FixedData.m_bExeChildInOrder || m_FixedData.m_bChooseOne || m_FixedData.m_bRandOne; + + while (pChild != null) + { + pChild.CheckDepth(); + + if (bMaxChildDepth) + { + if (uDepthLocal < pChild.m_uDepth) + uDepthLocal = pChild.m_uDepth; + } + else + { + unchecked { uDepthLocal += pChild.m_uDepth; } + } + + pChild = pChild.m_pNextSibling; + } + + unchecked { m_uDepth += uDepthLocal; } + } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Task/TaskTest.cs b/Assets/PerfectWorld/Scripts/Task/TaskTest.cs index a8af4ffd46..3d5c6f4f34 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskTest.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskTest.cs @@ -1,4 +1,9 @@ +using BrewMonster; +using System; using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using PerfectWorld.Scripts.Task; using UnityEngine; @@ -19,6 +24,80 @@ namespace BrewMonster.Scripts.Task string path = Path.Combine(Application.streamingAssetsPath, "data/tasks.data"); m_pTaskMan.LoadTasksFromPack(path, true); } + + [ContextMenu("Test Size")] + void TestSize() + { + var size = Marshal.SizeOf(typeof(ATaskTemplFixedData)); + BMLogger.Log("Size of ATaskTemplFixedData: " + size); + } + [ContextMenu("🧾 Log Struct Field Sizes (ATaskTemplFixedData)")] + private void LogStructFieldSizes() + { + Type structType = typeof(ATaskTemplFixedData); + FieldInfo[] fields = structType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + Debug.Log($"===== Struct: {structType.Name} ====="); + + foreach (var field in fields) + { + string name = field.Name; + Type fieldType = field.FieldType; + + int sizeInBytes = -1; + string note = ""; + + // 🟢 1. Nếu field có [MarshalAs], lấy SizeConst + var marshalAttr = field.GetCustomAttribute(); + if (marshalAttr != null && marshalAttr.SizeConst > 0) + { + int elemSize = GetElementSize(fieldType); + sizeInBytes = elemSize * marshalAttr.SizeConst; + note = $"(ByValArray × {marshalAttr.SizeConst})"; + } + else + { + try + { + sizeInBytes = Marshal.SizeOf(fieldType); + } + catch + { + note = "(reference type / variable size)"; + } + } + + string sizeText = sizeInBytes >= 0 ? $"{sizeInBytes} bytes" : "unknown size"; + Debug.Log($"{name,-40} | {fieldType.Name,-25} | {sizeText} {note}"); + } + + try + { + int total = Marshal.SizeOf(structType); + Debug.Log($"===== Total Struct Size: {total} bytes ====="); + } + catch + { + Debug.Log($"⚠️ Struct {structType.Name} contains non-blittable fields; total size unknown."); + } + } + + /// + /// Tính kích thước phần tử cơ bản của mảng blittable + /// + private int GetElementSize(Type type) + { + if (type.IsArray) + { + Type elemType = type.GetElementType(); + if (elemType != null) + { + try { return Marshal.SizeOf(elemType); } + catch { return 1; } // fallback + } + } + return Marshal.SizeOf(type); + } } } diff --git a/Assets/StreamingAssets/data.meta b/Assets/StreamingAssets/data.meta new file mode 100644 index 0000000000..e576ab595d --- /dev/null +++ b/Assets/StreamingAssets/data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed55b9311227c0f488154c01c55301d8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/aipolicy.data b/Assets/StreamingAssets/data/aipolicy.data new file mode 100644 index 0000000000..53c5fee591 Binary files /dev/null and b/Assets/StreamingAssets/data/aipolicy.data differ diff --git a/Assets/StreamingAssets/data/aipolicy.data.meta b/Assets/StreamingAssets/data/aipolicy.data.meta new file mode 100644 index 0000000000..7053335aaa --- /dev/null +++ b/Assets/StreamingAssets/data/aipolicy.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c0d05d66676da0c4d96f2bcba83c7cc8 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/domain.data b/Assets/StreamingAssets/data/domain.data new file mode 100644 index 0000000000..8c198d1eea Binary files /dev/null and b/Assets/StreamingAssets/data/domain.data differ diff --git a/Assets/StreamingAssets/data/domain.data.meta b/Assets/StreamingAssets/data/domain.data.meta new file mode 100644 index 0000000000..fa669cfb67 --- /dev/null +++ b/Assets/StreamingAssets/data/domain.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 090accfe9d104324c82102bc78156457 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/domain2.data b/Assets/StreamingAssets/data/domain2.data new file mode 100644 index 0000000000..edd7dd09a2 Binary files /dev/null and b/Assets/StreamingAssets/data/domain2.data differ diff --git a/Assets/StreamingAssets/data/domain2.data.meta b/Assets/StreamingAssets/data/domain2.data.meta new file mode 100644 index 0000000000..2adde45a24 --- /dev/null +++ b/Assets/StreamingAssets/data/domain2.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: eb7ac5cca9fce714d99986697f9a5b31 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/domain2_cross.data b/Assets/StreamingAssets/data/domain2_cross.data new file mode 100644 index 0000000000..481f5db38a Binary files /dev/null and b/Assets/StreamingAssets/data/domain2_cross.data differ diff --git a/Assets/StreamingAssets/data/domain2_cross.data.meta b/Assets/StreamingAssets/data/domain2_cross.data.meta new file mode 100644 index 0000000000..2d01f1bd87 --- /dev/null +++ b/Assets/StreamingAssets/data/domain2_cross.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0ef53828160078e4fbe4bcc8fe77f9ff +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/dyn_tasks.data b/Assets/StreamingAssets/data/dyn_tasks.data new file mode 100644 index 0000000000..8b77f2e1b2 Binary files /dev/null and b/Assets/StreamingAssets/data/dyn_tasks.data differ diff --git a/Assets/StreamingAssets/data/dyn_tasks.data.meta b/Assets/StreamingAssets/data/dyn_tasks.data.meta new file mode 100644 index 0000000000..b127f01047 --- /dev/null +++ b/Assets/StreamingAssets/data/dyn_tasks.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 501d4db75e7e5b14194d3d712461efdd +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/elements.data b/Assets/StreamingAssets/data/elements.data new file mode 100644 index 0000000000..abd564ec7f Binary files /dev/null and b/Assets/StreamingAssets/data/elements.data differ diff --git a/Assets/StreamingAssets/data/elements.data.meta b/Assets/StreamingAssets/data/elements.data.meta new file mode 100644 index 0000000000..cea5df7483 --- /dev/null +++ b/Assets/StreamingAssets/data/elements.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7d85d3a0fdd9b40439507c98ed85c88e +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/fzl2jw.ttf b/Assets/StreamingAssets/data/fzl2jw.ttf new file mode 100644 index 0000000000..a70bf25548 Binary files /dev/null and b/Assets/StreamingAssets/data/fzl2jw.ttf differ diff --git a/Assets/StreamingAssets/data/fzl2jw.ttf.meta b/Assets/StreamingAssets/data/fzl2jw.ttf.meta new file mode 100644 index 0000000000..731470314a --- /dev/null +++ b/Assets/StreamingAssets/data/fzl2jw.ttf.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c63d659da0623e748b4291c3e691009c +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/fzxh1jw.ttf b/Assets/StreamingAssets/data/fzxh1jw.ttf new file mode 100644 index 0000000000..bfcf72d338 Binary files /dev/null and b/Assets/StreamingAssets/data/fzxh1jw.ttf differ diff --git a/Assets/StreamingAssets/data/fzxh1jw.ttf.meta b/Assets/StreamingAssets/data/fzxh1jw.ttf.meta new file mode 100644 index 0000000000..8e64da111f --- /dev/null +++ b/Assets/StreamingAssets/data/fzxh1jw.ttf.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f846a8291c9575f47bed980f961d1c5c +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/gshop.data b/Assets/StreamingAssets/data/gshop.data new file mode 100644 index 0000000000..60cdbd69ae Binary files /dev/null and b/Assets/StreamingAssets/data/gshop.data differ diff --git a/Assets/StreamingAssets/data/gshop.data.meta b/Assets/StreamingAssets/data/gshop.data.meta new file mode 100644 index 0000000000..81900dc602 --- /dev/null +++ b/Assets/StreamingAssets/data/gshop.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8952f1d047c4925478f53c8b82bdf7c7 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/gshop1.data b/Assets/StreamingAssets/data/gshop1.data new file mode 100644 index 0000000000..3e74172f6d Binary files /dev/null and b/Assets/StreamingAssets/data/gshop1.data differ diff --git a/Assets/StreamingAssets/data/gshop1.data.meta b/Assets/StreamingAssets/data/gshop1.data.meta new file mode 100644 index 0000000000..3765800498 --- /dev/null +++ b/Assets/StreamingAssets/data/gshop1.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 85941260470904640bac2e0775f84e28 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/gshopsev.data b/Assets/StreamingAssets/data/gshopsev.data new file mode 100644 index 0000000000..ced1a4870d Binary files /dev/null and b/Assets/StreamingAssets/data/gshopsev.data differ diff --git a/Assets/StreamingAssets/data/gshopsev.data.meta b/Assets/StreamingAssets/data/gshopsev.data.meta new file mode 100644 index 0000000000..b079212942 --- /dev/null +++ b/Assets/StreamingAssets/data/gshopsev.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 49850d1c835347848a91823adea32d70 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/task_npc.data b/Assets/StreamingAssets/data/task_npc.data new file mode 100644 index 0000000000..7f7fb3acc2 Binary files /dev/null and b/Assets/StreamingAssets/data/task_npc.data differ diff --git a/Assets/StreamingAssets/data/task_npc.data.meta b/Assets/StreamingAssets/data/task_npc.data.meta new file mode 100644 index 0000000000..f7736a4195 --- /dev/null +++ b/Assets/StreamingAssets/data/task_npc.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b620c7abd86f50146a7d78b114523e21 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/data/tasks.data b/Assets/StreamingAssets/data/tasks.data new file mode 100644 index 0000000000..3f947657ac Binary files /dev/null and b/Assets/StreamingAssets/data/tasks.data differ diff --git a/Assets/StreamingAssets/data/tasks.data.meta b/Assets/StreamingAssets/data/tasks.data.meta new file mode 100644 index 0000000000..067dca99dd --- /dev/null +++ b/Assets/StreamingAssets/data/tasks.data.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a582d9e37cad02e42892490b875bc744 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: