summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2026-05-15 20:05:21 -0400
committerAndrew Opalach <andrew@akon.city> 2026-05-15 20:20:25 -0400
commit97847d638b7ba7d26f66f7c7b49e3c711d889e67 (patch)
tree4380242432a2e91d2facee81d3ab58f6f5662165
parentda824e8b778a0c2d1d167c3cde8022f62616f95b (diff)
downloadNewCamera-97847d638b7ba7d26f66f7c7b49e3c711d889e67.tar.gz
NewCamera-97847d638b7ba7d26f66f7c7b49e3c711d889e67.tar.bz2
NewCamera-97847d638b7ba7d26f66f7c7b49e3c711d889e67.zip
Automatic save slot fallback
Signed-off-by: Andrew Opalach <andrew@akon.city>
-rwxr-xr-xPlugin.cs211
1 files 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>? underwaterCheck;
+ private Hook<UnderwaterCheck>? 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<nint, nint> getSaveSlotGuiAddr;
+ private NativeFunction<nint, nint> getPlayerSettingsAddr;
+ private nint getPlayerSettings()
+ {
+ nint rcx = MemoryUtil.Read<nint>(0x145013950);
+ if (saveSlotIndex >= 0)
+ {
+ nint rax = saveSlotIndex * 0x26CC00;
+ rax += MemoryUtil.Read<nint>(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<ChangeEquipment>? changeEquipmentHook;
+ private NativeFunction<nint, int, nint> 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>? refreshEntityParams;
+ private Hook<RefreshEntityParams>? 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<UnderwaterCheck>(0x1412AD500, UnderwaterCheckHook); // nint
+ underwaterCheckHook = Hook.Create<UnderwaterCheck>(0x1412AD500, UnderwaterCheckHook); // nint
+
+ getSaveSlotGuiAddr = new NativeFunction<nint, nint>(0x141AC0B60);
+ getPlayerSettingsAddr = new NativeFunction<nint, nint>(0x141B8DBB0);
+
+ changeEquipmentHook = Hook.Create<ChangeEquipment>(0x141DDEF80, ChangeEquipmentHook); // nint, int
+ newEquipmentPointer = new NativeFunction<nint, int, nint>(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<RefreshEntityParams>(0x141F605F0, RefreshEntityParamsHook); // nint, nint
+ refreshEntityParamsHook = Hook.Create<RefreshEntityParams>(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<nint>(0x1451C42B8));
+ if (guiAddr == 0x0)
+ {
+ saveSlotIndex = -1;
+ return null;
+ }
+ saveSlotIndex = MemoryUtil.Read<int>(guiAddr + 0x334);
+ nint offset = (sPlayer.Instance + 0x40) + (0x740 * saveSlotIndex);
nint playerAddr = MemoryUtil.Read<nint>(offset);
if (playerAddr != 0x1433FE588)
{
return null;
}
- offset += 0x18;
- playerAddr = MemoryUtil.Read<nint>(offset);
+ playerAddr = MemoryUtil.Read<nint>(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<nint>(player.Instance + 0x76B0);
- MemoryUtil.WriteBytes(baseAddr + 0x1A98, [0x1]);
- int weaponParts = MemoryUtil.Read<int>(baseAddr + 0x2250);
- for (int i = 0; i < weaponParts; i++)
+ if (baseAddr != 0x0)
{
- nint partAddr = MemoryUtil.Read<nint>(baseAddr + ((i + 0x16B) * 24));
- if (partAddr != 0x0)
+ MemoryUtil.WriteBytes(baseAddr + 0x1A98, [0x1]);
+ int weaponParts = MemoryUtil.Read<int>(baseAddr + 0x2250);
+ for (int i = 0; i < weaponParts; i++)
{
- MemoryUtil.WriteBytes(partAddr + 0x1A98, [0x1]);
+ nint partAddr = MemoryUtil.Read<nint>(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<float>(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<float>(sMain.Instance + 0xA4) = freezeGame ? 0.0f : 1.0f;
+ nint rax = MemoryUtil.Read<nint>(unknownPtr + 0x2968);
+ nint r9 = MemoryUtil.Read<nint>(unknownPtr + 0x2950);
+ int esi = MemoryUtil.Read<int>(rax + 0x240);
+ esi *= MemoryUtil.Read<int>(r9 + 0x1D8);
+ esi += unknownInt;
+ nint newEquipment = newEquipmentPointer.Invoke(unknownPtr, esi);
+ lastEquipedId = MemoryUtil.Read<int>(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<int>(player.Instance + 0x1373C):X}");
+ ImGui.Text($"Body: {MemoryUtil.Read<int>(player.Instance + 0x13740):X}");
+ ImGui.Text($"Arms: {MemoryUtil.Read<int>(player.Instance + 0x13744):X}");
+ ImGui.Text($"Waist: {MemoryUtil.Read<int>(player.Instance + 0x13748):X}");
+ ImGui.Text($"Legs: {MemoryUtil.Read<int>(player.Instance + 0x1374C):X}");
+ ImGui.Text($"Slinger: {MemoryUtil.Read<int>(player.Instance + 0x13D8C):X}_{MemoryUtil.Read<int>(player.Instance + 0x13D90):X}");
+ ImGui.Text($"Last Equipped: {lastEquipedId:X}");
+
+ ref byte showHeadArmor = ref MemoryUtil.GetRef<byte>(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<nint>(player.Instance + 0x7690);
+ nint next = MemoryUtil.Read<nint>(combineArmorList + 0x20);
+ while (next != 0x0)
+ {
+ next = MemoryUtil.Read<nint>(next + 0x20);
+ }
+ }
+ */
nint bodyArmor = MemoryUtil.Read<nint>(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);