/// <summary> /// /// </summary> internal void UpdatePointers() { PointerEventActionType.UpdatePointers(); PointerIsMotionPlay.UpdatePointers(); PointerEventActionTask.UpdatePointers(); PointerPlayerStatus.UpdatePointers(); PointerPlayerHP.UpdatePointers(); PointerPlayerPosition.UpdatePointers(); PointerRankManager.UpdatePointers(); PointerInventory.UpdatePointers(); try { PointerEnemyCount.UpdatePointers(); PointerEnemyEntryList.UpdatePointers(); GenerateEnemyEntries(); PointerInventoryCount.UpdatePointers(); PointerInventoryEntryList.UpdatePointers(); GenerateItemEntries(); } catch { // May fail in main menu } }
/// <summary> /// Dereferences a 4-byte signed integer via the PointerEnemyEntryCount pointer to detect how large the enemy pointer table is and then create the pointer table entries if required. /// </summary> private unsafe void GenerateEnemyEntries() { bool success; fixed(int *p = &EnemyTableCount) success = PointerEnemyCount.TryDerefInt(0x1C, p); PointerEnemyEntries = new MultilevelPointer[MAX_ENTITIES]; // Create a new enemy pointer table array with the detected size. // Skip the first 28 bytes and read the rest as a byte array // This can be done because the pointers are stored sequentially in an array byte[] entityPtrByteArr = PointerEnemyEntryList.DerefByteArray(0x28, MAX_ENTITIES * sizeof(IntPtr)); // Do a block copy to convert the byte array to an IntPtr array IntPtr[] entityPtrArr = new IntPtr[MAX_ENTITIES]; Buffer.BlockCopy(entityPtrByteArr, 0, entityPtrArr, 0, entityPtrByteArr.Length); // The pointers we read are already the address of the entity, so make sure we add the first offset here for (int i = 0; i < PointerEnemyEntries.Length; ++i) // Loop through and create all of the pointers for the table. { PointerEnemyEntries[i] = new MultilevelPointer(memoryAccess, IntPtr.Add(entityPtrArr[i], 0x228), 0x18L, 0x48L, 0x48L); } }