From 97847d638b7ba7d26f66f7c7b49e3c711d889e67 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Fri, 15 May 2026 20:05:21 -0400 Subject: Automatic save slot fallback Signed-off-by: Andrew Opalach --- Plugin.cs | 211 ++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 138 insertions(+), 73 deletions(-) diff --git a/Plugin.cs b/Plugin.cs index a260bd3..55a83ec 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -324,7 +324,7 @@ namespace NewCamera private Patch nullifyDofCoc; private bool cameraIsUnderwater = false; private delegate void UnderwaterCheck(nint unknownPtr); - private Hook? underwaterCheck; + private Hook? underwaterCheckHook; private void underwaterCameraEnable() { @@ -345,12 +345,29 @@ namespace NewCamera } private static readonly MtObject sPlayer = SingletonManager.GetSingleton("sPlayer")!; - private bool saveSlotFallback = false; - private int saveSlotIndex = 0; + private int saveSlotIndex = -1; + private NativeFunction getSaveSlotGuiAddr; + private NativeFunction getPlayerSettingsAddr; + private nint getPlayerSettings() + { + nint rcx = MemoryUtil.Read(0x145013950); + if (saveSlotIndex >= 0) + { + nint rax = saveSlotIndex * 0x26CC00; + rax += MemoryUtil.Read(rcx + 0xA8); + return rax; + } + return getPlayerSettingsAddr.Invoke(rcx); + } private bool hideWeapon = false; private bool hideKnife = false; private bool hideSlinger = false; + private delegate void ChangeEquipment(nint unknownPtr, int unknownInt); + private Hook? changeEquipmentHook; + private NativeFunction newEquipmentPointer; + private int lastEquipedId = 0; + private bool disableCollision = false; private bool disableExtraCollision = false; private bool disableGravity = false; @@ -446,7 +463,7 @@ namespace NewCamera private float playerOpacityOverride = 1.0f; private delegate void RefreshEntityParams(nint entity, nint unknownPtr2); - private Hook? refreshEntityParams; + private Hook? refreshEntityParamsHook; private bool overridePlayerWetness = false; private Patch noopPlayerWetnessUpdate; @@ -690,13 +707,19 @@ namespace NewCamera underwaterCamera4 = new Patch(new IntPtr(0x141FA5BA0), [0x40, 0x84, 0xF6, 0x90, 0x74]); // jae -> je. underwaterCamera5 = new Patch(new IntPtr(0x141FA5A74), [0x0F, 0x57, 0xF6, 0x31, 0xD2, 0x48, 0x8D, 0x4D, 0x80, 0xE8, 0x9E, 0x41, 0x38, 0xFE, 0xC1, 0xE8, 0x14, 0x66, 0x25, 0xD8, 0x03, 0xFF, 0xC8, 0x66, 0x3D, 0x48, 0x00, 0x77]); nullifyDofCoc = new Patch(new IntPtr(0x1424236DD), [0x0F, 0x57, 0xF6, 0x90, 0x90, 0x90, 0x90]); - underwaterCheck = Hook.Create(0x1412AD500, UnderwaterCheckHook); // nint + underwaterCheckHook = Hook.Create(0x1412AD500, UnderwaterCheckHook); // nint + + getSaveSlotGuiAddr = new NativeFunction(0x141AC0B60); + getPlayerSettingsAddr = new NativeFunction(0x141B8DBB0); + + changeEquipmentHook = Hook.Create(0x141DDEF80, ChangeEquipmentHook); // nint, int + newEquipmentPointer = new NativeFunction(0x141DE56A0); // Player + ECCC = How far underwater is the player. jmpOverHotSpringsEval = new Patch(new IntPtr(0x1417C1B03), [0xEB]); jmpOverHotSpringsSteam = new Patch(new IntPtr(0x14203A494), [0xE9, 0x8D, 0x00, 0x00, 0x00, 0x90]); - refreshEntityParams = Hook.Create(0x141F605F0, RefreshEntityParamsHook); // nint, nint + refreshEntityParamsHook = Hook.Create(0x141F605F0, RefreshEntityParamsHook); // nint, nint noopPlayerWetnessUpdate = new Patch(new IntPtr(0x14203E893), [0x90, 0x90, 0x90, 0x90, 0x90]); jmpOverChangeEquipmentWetnessUpdate_1 = new Patch(new IntPtr(0x14203E310), [0xEB]); // je -> jmp. @@ -850,16 +873,22 @@ namespace NewCamera } } - private Player? getPlayerFromSaveSlot(int index) + private Player? getPlayerFromSaveSlot() { - nint offset = (sPlayer.Instance + 0x40) + (0x740 * index); + nint guiAddr = getSaveSlotGuiAddr.Invoke(MemoryUtil.Read(0x1451C42B8)); + if (guiAddr == 0x0) + { + saveSlotIndex = -1; + return null; + } + saveSlotIndex = MemoryUtil.Read(guiAddr + 0x334); + nint offset = (sPlayer.Instance + 0x40) + (0x740 * saveSlotIndex); nint playerAddr = MemoryUtil.Read(offset); if (playerAddr != 0x1433FE588) { return null; } - offset += 0x18; - playerAddr = MemoryUtil.Read(offset); + playerAddr = MemoryUtil.Read(offset + 0x18); if (playerAddr == 0x0) { return null; @@ -1028,23 +1057,26 @@ namespace NewCamera } player = Player.MainPlayer; - if (player == null && saveSlotFallback) + if (player == null) { - player = getPlayerFromSaveSlot(saveSlotIndex); + player = getPlayerFromSaveSlot(); } if (player != null) { if (hideWeapon) { nint baseAddr = MemoryUtil.Read(player.Instance + 0x76B0); - MemoryUtil.WriteBytes(baseAddr + 0x1A98, [0x1]); - int weaponParts = MemoryUtil.Read(baseAddr + 0x2250); - for (int i = 0; i < weaponParts; i++) + if (baseAddr != 0x0) { - nint partAddr = MemoryUtil.Read(baseAddr + ((i + 0x16B) * 24)); - if (partAddr != 0x0) + MemoryUtil.WriteBytes(baseAddr + 0x1A98, [0x1]); + int weaponParts = MemoryUtil.Read(baseAddr + 0x2250); + for (int i = 0; i < weaponParts; i++) { - MemoryUtil.WriteBytes(partAddr + 0x1A98, [0x1]); + nint partAddr = MemoryUtil.Read(baseAddr + ((i + 0x16B) * 24)); + if (partAddr != 0x0) + { + MemoryUtil.WriteBytes(partAddr + 0x1A98, [0x1]); + } } } } @@ -1852,6 +1884,29 @@ namespace NewCamera } */ + private void toggleFreezeGame() + { + freezeGame = !freezeGame; + if (freezeGame) + { + decoupleDtFromGameTime = true; + if (forceOffMotionBlurOverride == 0) + { + forceOffMotionBlurOverride = tuningTool.AddOverride("Shutter Speed", new Vector4(0.0f), 0); + } + } + else + { + decoupleDtFromGameTime = false; + if (forceOffMotionBlurOverride != 0) + { + tuningTool.RemoveOverride(forceOffMotionBlurOverride); + forceOffMotionBlurOverride = 0; + } + } + MemoryUtil.GetRef(sMain.Instance + 0xA4) = freezeGame ? 0.0f : 1.0f; + } + private bool playerInMenu() { // https://github.com/HunterPie/HunterPie/blob/fa73f81ed0cdc921a6cf63f96c0fcff3688d88c2/HunterPie.Integrations/Datasources/MonsterHunterWorld/Entity/Game/MHWGame.cs#L74 @@ -2332,7 +2387,7 @@ namespace NewCamera private void RefreshEntityParamsHook(nint entity, nint unknownPtr2) { - refreshEntityParams!.Original(entity, unknownPtr2); + refreshEntityParamsHook!.Original(entity, unknownPtr2); if (disableMod) { @@ -2347,32 +2402,21 @@ namespace NewCamera } } - private void toggleFreezeGame() + private void ChangeEquipmentHook(nint unknownPtr, int unknownInt) { - freezeGame = !freezeGame; - if (freezeGame) - { - decoupleDtFromGameTime = true; - if (forceOffMotionBlurOverride == 0) - { - forceOffMotionBlurOverride = tuningTool.AddOverride("Shutter Speed", new Vector4(0.0f), 0); - } - } - else - { - decoupleDtFromGameTime = false; - if (forceOffMotionBlurOverride != 0) - { - tuningTool.RemoveOverride(forceOffMotionBlurOverride); - forceOffMotionBlurOverride = 0; - } - } - MemoryUtil.GetRef(sMain.Instance + 0xA4) = freezeGame ? 0.0f : 1.0f; + nint rax = MemoryUtil.Read(unknownPtr + 0x2968); + nint r9 = MemoryUtil.Read(unknownPtr + 0x2950); + int esi = MemoryUtil.Read(rax + 0x240); + esi *= MemoryUtil.Read(r9 + 0x1D8); + esi += unknownInt; + nint newEquipment = newEquipmentPointer.Invoke(unknownPtr, esi); + lastEquipedId = MemoryUtil.Read(newEquipment + 0x24); + changeEquipmentHook!.Original(unknownPtr, unknownInt); } private void UnderwaterCheckHook(nint unknownPtr) { - underwaterCheck!.Original(unknownPtr); + underwaterCheckHook!.Original(unknownPtr); if (disableMod || !enableUnderwaterCamera) { @@ -2853,12 +2897,52 @@ namespace NewCamera private void drawPlayerInfo(Player player, float width) { + nint playerSettings = getPlayerSettings(); + + ImGui.Text($"{Marshal.PtrToStringAnsi(playerSettings + 0x50)}"); + ImGui.Text($"Settings: {playerSettings:X}"); + ImGui.Checkbox("Hide Weapon", ref hideWeapon); ImGui.Checkbox("Hide Knife", ref hideKnife); ImGui.Checkbox("Hide Slinger", ref hideSlinger); + ImGui.Text($"Head: {MemoryUtil.Read(player.Instance + 0x1373C):X}"); + ImGui.Text($"Body: {MemoryUtil.Read(player.Instance + 0x13740):X}"); + ImGui.Text($"Arms: {MemoryUtil.Read(player.Instance + 0x13744):X}"); + ImGui.Text($"Waist: {MemoryUtil.Read(player.Instance + 0x13748):X}"); + ImGui.Text($"Legs: {MemoryUtil.Read(player.Instance + 0x1374C):X}"); + ImGui.Text($"Slinger: {MemoryUtil.Read(player.Instance + 0x13D8C):X}_{MemoryUtil.Read(player.Instance + 0x13D90):X}"); + ImGui.Text($"Last Equipped: {lastEquipedId:X}"); + + ref byte showHeadArmor = ref MemoryUtil.GetRef(playerSettings + 0x1403E1); + int showHeadArmorInt = showHeadArmor; + if (ImGui.RadioButton("Show", ref showHeadArmorInt, 0)) + { + showHeadArmor = (byte)showHeadArmorInt; + } + ImGui.SameLine(); + if (ImGui.RadioButton("Hide", ref showHeadArmorInt, 1)) + { + showHeadArmor = (byte)showHeadArmorInt; + } + ImGui.SameLine(); + if (ImGui.RadioButton("Hide in Cutscenes", ref showHeadArmorInt, 2)) + { + showHeadArmor = (byte)showHeadArmorInt; + } + if (ImGui.CollapsingHeader("Armor Parts")) { + /* + { + nint combineArmorList = MemoryUtil.Read(player.Instance + 0x7690); + nint next = MemoryUtil.Read(combineArmorList + 0x20); + while (next != 0x0) + { + next = MemoryUtil.Read(next + 0x20); + } + } + */ nint bodyArmor = MemoryUtil.Read(player.Instance + 0x2A0); if (bodyArmor != 0x0) { @@ -2914,10 +2998,19 @@ namespace NewCamera (bEnabled, bSub) = (bSub, bEnabled); } bool isVisible = bEnabled != 0x0; - if (ImGui.Checkbox($"Part #{i}", ref isVisible)) + if (ImGui.Checkbox($"##Part #{i}", ref isVisible)) { (bEnabled, bSub) = (bSub, bEnabled); } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text($"Part #{i}"); + ImGui.EndTooltip(); + } + if (i % 8 != 7 && i != parts - 1) + { + ImGui.SameLine(); + } } ImGui.Separator(); } @@ -3984,46 +4077,18 @@ namespace NewCamera } ImGui.PopID(); - bool playerFallback = player == null; - if (!playerFallback) + if (player == null) { - saveSlotFallback = false; + player = getPlayerFromSaveSlot(); } - else if (saveSlotFallback) + else { - player = getPlayerFromSaveSlot(saveSlotIndex); + saveSlotIndex = -1; } ImGui.PushID("Player"); if (ImGui.CollapsingHeader("Player")) { - if (playerFallback) - { - bool updateFallback = ImGui.Checkbox("Save Slot Fallback", ref saveSlotFallback); - if (saveSlotFallback) - { - int saveSlot = saveSlotIndex; - ImGui.SetNextItemWidth(width * 0.2f); - if (ImGui.InputInt("Save Slot Index", ref saveSlot, 1, 0, ImGuiInputTextFlags.EnterReturnsTrue)) - { - saveSlotIndex = Math.Clamp(saveSlot, 0, 2); - } - } - if (updateFallback) - { - if (saveSlotFallback) - { - if (player == null) - { - player = getPlayerFromSaveSlot(saveSlotIndex); - } - } - else - { - player = checkPlayerChange(); - } - } - } if (player != null) { drawPlayerInfo(player, width); -- cgit v1.2.3-101-g0448