From 513f05695545b8eceec1085f741862ec3a7bf3b5 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sat, 23 May 2026 16:42:05 -0400 Subject: Progress on joints stuff Signed-off-by: Andrew Opalach --- Plugin.cs | 939 ++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 609 insertions(+), 330 deletions(-) diff --git a/Plugin.cs b/Plugin.cs index 79b0606..01f7ab7 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -88,8 +88,8 @@ using WorldTuningTool; // the tent the game freezes/uses the wrong camera. // Steam proton launch command: -// env DOTNET_ROOT= WINEDLLOVERRIDES="ucrtbase,dinput8=n,b" %command% -// export CMD=$(echo -n "%command%" | sed "s/\/MonsterHunterWorld.exe/\/launcher.exe/") && DOTNET_ROOT= WINEDLLOVERRIDES="winmm,dinput8=n,b" eval proton-env $CMD MonsterHunterWorld.exe winmm.dll +// env WINEDLLOVERRIDES="ucrtbase,dinput8=n,b" %command% +// export CMD=$(echo -n "%command%" | sed "s/\/MonsterHunterWorld.exe/\/SPLLauncher.exe/") && WINEDLLOVERRIDES="winmm,dinput8=n,b" eval proton-env $CMD // Test cases: // Offset Perspective: @@ -188,6 +188,7 @@ namespace NewCamera private bool freeCamera = false; private bool freeCameraFromViewMode = false; private bool freeCameraFallback = false; + private bool freeCameraNoMenu = false; private Camera? vCamera = null; private int vCameraViewportIndex = -1; private float? restoreFov = null; @@ -203,7 +204,6 @@ namespace NewCamera private bool lockVerticalToggled = false; private NativeFunction getViewParamOffset; - private NativeFunction calcOffsetSettingAddr; private bool orbitPlayer = false; private bool orbitIgnoreCamera = false; @@ -361,32 +361,113 @@ namespace NewCamera rax += MemoryUtil.Read(rcx + 0xA8); return rax; } + // MonsterHunterWorld.exe+1B8DBB0 - movsxd rax,dword ptr [rcx+000000A0] return getPlayerSettingsAddr.Invoke(rcx); } private bool hideWeapon = false; private bool hideKnife = false; private bool hideSlinger = false; + // List of Joints: + // Hip (1_0) + // Right Leg (2_0) + // Left Leg (2_1) + // Lower Back (2_2) + // Left Knee (3_1) + // Right Knee (3_2) + // Upper Back (3_4) + // Lower Neck (4_0) + // Right Ankle (4_1) + // Left Ankle (4_5) + // Left Shoulder (4_7) + // Right Shoulder (4_8) + // Left Toes (5_2) + // Right Shoulder2 (5_3) + // Upper Neck (5_4) + // Left Shoulder2 (5_5) + // Right Toes (5_6) + // Right Elbow (6_4) + // Left Elbow (6_5) + // Left Wrist (7_1) + // Right Wrist (7_4) + // Left Palm (8_0) + // Left Middle (8_2) + // Left Index (8_3) + // Right Palm (8_4) + // Left Thumb (8_5) + // Right Thumb (8_7) + // Right Index (8_11) + // Right Middle (8_12) + // Right Index T (9_0) + // Left Pinky T (9_1) + // Left Thumb T (9_2) + // Left Index T (9_3) + // Left Middle T (9_4) + // Left Ring T (9_5) + // Right Middle T (9_6) + // Right Thumb T (9_7) + // Right Ring T (9_8) + // Right Pinky T (9_9) + // Right Index P (A_0) + // Right Thumb P (A_1) + // Left Pinky P (A_2) + // Left Ring P (A_3) + // Left Middle P (A_4) + // Right Ring P (A_5) + // Left Index P (A_6) + // Left Thumb P (A_7) + // Right Middle P (A_8) + // Right Pinky P (A_9) + // Left Pinky D (B_0) + // Right Pinky D (B_1) + // Left Ring D (B_2) + // Right Ring D (B_3) + + private struct Armor + { + public const int Body = 0; + public const int Helmet = 1; + public const int Arm = 2; + public const int Waist = 3; + public const int Leg = 4; + public const int Face = 5; + }; + + private nint[] playerArmor = new nint[6] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + private List bodyJoints = new List(); + //private List faceJoints = new List(); + private List jiggleBones = new List(); + private List ikJoints = new List(); private bool attachToChest = false; private bool swapChestSides = false; private float chestMoveScale = 0.25f; private nint chestBone1 = 0x0; private nint chestBone2 = 0x0; + /* private bool overrideFacePose; private Patch noopFacePose; private Patch noopFacePoseUpdate; + */ - private delegate void CheckJointRotation(nint entity, nint joint); - private Hook? checkJointRotationHook; - + private bool ikForcedOff = false; + private Patch forceDisableIK; + private delegate void UpdateJoints(nint obj, nint unknownPtr, int unknownInt, int unknownInt2); + private Hook? updateJointsHook; + private delegate void UpdateJointChild(nint child, nint joint, nint obj); private Dictionary> jointOffsets = new Dictionary>(); private bool didJointOffset = false; + private delegate void UpdateIK(nint superOfChild, nint joint, nint obj); + private Hook? updateIKHook; + private Dictionary> ikOffsets = new Dictionary>(); + + /* 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; @@ -580,7 +661,6 @@ namespace NewCamera Animal.Initialize(); getViewParamOffset = new NativeFunction(0x14136E6C0); - calcOffsetSettingAddr = new NativeFunction(0x141B8DBB0); #if QUARANTINED_FEATURES // MonsterHunterWorld.exe+20354F7 - call MonsterHunterWorld.exe+1F73850 @@ -588,10 +668,10 @@ namespace NewCamera setPlayerController1 = new NativeAction(0x141F73850); setPlayerController5 = new NativeAction(0x14118DDC0); setZoneStateHook = Hook.Create(0x142035020, SetZoneStateHook); // nint, int - zoneStateForcePassive1 = new Patch(new IntPtr(0x140256A3F) + 0x6, [0x1]); - zoneStateForcePassive2 = new Patch(new IntPtr(0x141AC2865) + 0x6, [0x1]); - zoneStateForceCombat1 = new Patch(new IntPtr(0x141AC2938) + 0x6, [0x0]); - zoneStateForceCombat2 = new Patch(new IntPtr(0x141AC28EC) + 0x6, [0x0]); + zoneStateForcePassive1 = new Patch(new nint(0x140256A3F) + 0x6, [0x1]); + zoneStateForcePassive2 = new Patch(new nint(0x141AC2865) + 0x6, [0x1]); + zoneStateForceCombat1 = new Patch(new nint(0x141AC2938) + 0x6, [0x0]); + zoneStateForceCombat2 = new Patch(new nint(0x141AC28EC) + 0x6, [0x0]); #endif procEnvironmentCollision = new NativeAction(0x141F737D0); @@ -721,34 +801,37 @@ namespace NewCamera noopCharacterFade.Enable(); } - underwaterCamera1 = new Patch(new IntPtr(0x1412AD54D), [0x90, 0x90, 0x90, 0x90, 0x90, 0x90]); // Nop "Is diving" check. - underwaterCamera2 = new Patch(new IntPtr(0x1412AD571), [0xB1, 0x01, 0x28, 0xC1, 0x90, 0x90, 0x90]); // Make cl the inverse of al. - underwaterCamera3 = new Patch(new IntPtr(0x141FA5A7E), [0x90, 0x90]); // Nop check. - 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]); + underwaterCamera1 = new Patch(new nint(0x1412AD54D), [0x90, 0x90, 0x90, 0x90, 0x90, 0x90]); // Nop "Is diving" check. + underwaterCamera2 = new Patch(new nint(0x1412AD571), [0xB1, 0x01, 0x28, 0xC1, 0x90, 0x90, 0x90]); // Make cl the inverse of al. + underwaterCamera3 = new Patch(new nint(0x141FA5A7E), [0x90, 0x90]); // Nop check. + underwaterCamera4 = new Patch(new nint(0x141FA5BA0), [0x40, 0x84, 0xF6, 0x90, 0x74]); // jae -> je. + underwaterCamera5 = new Patch(new nint(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 nint(0x1424236DD), [0x0F, 0x57, 0xF6, 0x90, 0x90, 0x90, 0x90]); underwaterCheckHook = Hook.Create(0x1412AD500, UnderwaterCheckHook); // nint getSaveSlotGuiAddr = new NativeFunction(0x141AC0B60); getPlayerSettingsAddr = new NativeFunction(0x141B8DBB0); - noopFacePose = new Patch(new IntPtr(0x14237B093), [0x90, 0x90, 0x90, 0x90, 0x90]); - noopFacePoseUpdate = new Patch(new IntPtr(0x14223BAAB), [0x90, 0x90, 0x90, 0x90, 0x90]); + //noopFacePose = new Patch(new nint(0x14237B093), [0x90, 0x90, 0x90, 0x90, 0x90]); + //noopFacePoseUpdate = new Patch(new nint(0x14223BAAB), [0x90, 0x90, 0x90, 0x90, 0x90]); + + forceDisableIK = new Patch(new nint(0x14031FD40), [0xC6, 0x81, 0x81, 0x01, 0x00, 0x00, 0x00, 0xC3]); - checkJointRotationHook = Hook.Create(0x1422395C0, CheckJointRotationHook); + updateJointsHook = Hook.Create(0x14223B870, UpdateJointsHook); + updateIKHook = Hook.Create(0x142472C00, UpdateIKHook); - changeEquipmentHook = Hook.Create(0x141DDEF80, ChangeEquipmentHook); // nint, int - newEquipmentPointer = new NativeFunction(0x141DE56A0); + //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]); + jmpOverHotSpringsEval = new Patch(new nint(0x1417C1B03), [0xEB]); + jmpOverHotSpringsSteam = new Patch(new nint(0x14203A494), [0xE9, 0x8D, 0x00, 0x00, 0x00, 0x90]); 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. - jmpOverChangeEquipmentWetnessUpdate_2 = new Patch(new IntPtr(0x14203E397), [0xE9, 0xB9, 0x00, 0x00, 0x00, 0x90]); // je -> jmp. + noopPlayerWetnessUpdate = new Patch(new nint(0x14203E893), [0x90, 0x90, 0x90, 0x90, 0x90]); + jmpOverChangeEquipmentWetnessUpdate_1 = new Patch(new nint(0x14203E310), [0xEB]); // je -> jmp. + jmpOverChangeEquipmentWetnessUpdate_2 = new Patch(new nint(0x14203E397), [0xE9, 0xB9, 0x00, 0x00, 0x00, 0x90]); // je -> jmp. // Noop collision checks. addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 11 06 F3 0F 10 48 04 F3 0F 58 4E 04 F3 0F 11 4E 04 F3 0F 10 40 08 F3 0F 58 46 08 F3 0F 11 46 08 44 8B AF E0 0B 00 00")); @@ -1079,6 +1162,15 @@ namespace NewCamera } if (Input.IsPressed(Key.NumPadSlash)) { + if (disableNearDofOverride != 0) + { + tuningTool.RemoveOverride(disableNearDofOverride); + disableNearDofOverride = 0; + } + else + { + disableNearDofOverride = tuningTool.AddOverride("Near Enable", new Vector4(), 0); + } } } #endif @@ -1112,6 +1204,7 @@ namespace NewCamera } } freeCameraFallback = true; + freeCameraNoMenu = false; ref float gameSpeed = ref MemoryUtil.GetRef(sMain.Instance + 0xA4); if (freezeGame && gameSpeed != 0.0f) @@ -1141,10 +1234,10 @@ namespace NewCamera int weaponParts = MemoryUtil.Read(baseAddr + 0x2250); for (int i = 0; i < weaponParts; i++) { - nint partAddr = MemoryUtil.Read(baseAddr + ((i + 0x16B) * 24)); - if (partAddr != 0x0) + nint partsAddr = MemoryUtil.Read(baseAddr + ((i + 0x16B) * 24)); + if (partsAddr != 0x0) { - MemoryUtil.WriteBytes(partAddr + 0x1A98, [0x1]); + MemoryUtil.WriteBytes(partsAddr + 0x1A98, [0x1]); } } } @@ -1912,6 +2005,7 @@ namespace NewCamera } freeCameraFallback = false; + freeCameraNoMenu = true; } /* @@ -1957,7 +2051,9 @@ namespace NewCamera private bool playerInMenu() { - return MemoryUtil.GetRef(Gui.SingletonInstance.Instance + 0x147A8) == 0x1; + // This doesn't align with in-game mouse controls. This can be observed when closing the pause + // menu and there is a brief moment where the camera moves -> freezes again -> then starts normally. + return !freeCameraNoMenu && MemoryUtil.GetRef(Gui.SingletonInstance.Instance + 0x147A8) == 0x1; } // This can undoubtedly be simplified. @@ -2407,17 +2503,409 @@ namespace NewCamera } } - private void CheckJointRotationHook(nint entity, nint joint) + private string parsePartName(string fullString) + { + string partName = ""; + if (fullString.StartsWith("pl\\f_equip")) + { + partName = fullString.Split('\\')[3]; + } + else if (fullString.StartsWith("pl\\hair")) + { + partName = fullString.Split('\\')[1]; + } + else if (fullString.StartsWith("pl\\f_face")) + { + partName = fullString.Split('\\')[2]; + } + else if (fullString.StartsWith("wp\\slg")) + { + partName = "slinger"; + } + else if (fullString.StartsWith("accessory\\acc")) + { + partName = fullString.Split('\\')[1]; + } + else if (fullString.StartsWith("npc\\npc")) + { + partName = "npc"; + } + return partName; + } + + private void collectArmorParts(nint baseAddr, nint addr) + { + string partName = parsePartName(Marshal.PtrToStringAnsi(addr + 0xC)!); + if (partName == "body") + { + playerArmor[Armor.Body] = baseAddr; + chestBone1 = 0x0; + chestBone2 = 0x0; + } + else if (partName == "helm") + { + playerArmor[Armor.Helmet] = baseAddr; + } + else if (partName == "arm") + { + playerArmor[Armor.Arm] = baseAddr; + } + else if (partName == "wst") + { + playerArmor[Armor.Waist] = baseAddr; + } + else if (partName == "leg") + { + playerArmor[Armor.Leg] = baseAddr; + } + else if (partName == "face000") + { + playerArmor[Armor.Face] = baseAddr; + } + + int jointCount = MemoryUtil.Read(baseAddr + 0x4A0); + nint jointAddr = MemoryUtil.Read(baseAddr + 0x4A8); + for (int i = 0; i < jointCount; i++) + { + if (partName == "body") + { + bodyJoints.Add(jointAddr); + } + /* + else if (partName == "face000") + { + faceJoints.Add(jointAddr); + } + */ + nint childAddr = MemoryUtil.Read(jointAddr + 0x8); + if (childAddr != 0x0 && MemoryUtil.Read(childAddr) == 0x142F21A90) + { + childAddr = MemoryUtil.Read(childAddr + 0x8); + if (childAddr != 0x0) + { + nint childVtable = MemoryUtil.Read(childAddr); + if (childVtable == 0x143524BD8) + { + childAddr = MemoryUtil.Read(childAddr + 0x188); + if (childAddr != 0x0 && MemoryUtil.Read(childAddr) == 0x143519530) + { + nint jiggleData = MemoryUtil.Read(MemoryUtil.Read(childAddr + 0xA0)); + if (MemoryUtil.Read(jiggleData) == 0x143519508) + { + if (!jiggleBones.Contains(jiggleData)) + { + jiggleBones.Add(jiggleData); + if (partName == "body") + { + if (chestBone1 == 0x0) + { + chestBone1 = jiggleData; + } + else + { + if (chestBone2 != 0x0) + { + chestBone2 = chestBone1; + chestBone1 = jiggleData; + } + else + { + chestBone2 = jiggleData; + } + } + } + } + } + } + } + else if (childVtable == 0x143249170) + { + childAddr = MemoryUtil.Read(childAddr + 0x188); + if (childAddr != 0x0 && MemoryUtil.Read(childAddr) == 0x1432492F0) + { + if (!ikJoints.Contains(jointAddr)) + { + ikJoints.Add(jointAddr); + } + } + } + } + } + jointAddr += 0xC0; + } + if (partName == "body") + { + bodyJoints.Sort(delegate(nint x, nint y) + { + return MemoryUtil.Read(x + 0x14) - MemoryUtil.Read(y + 0x14); + }); + for (int i = jointOffsets.Count - 1; i >= 0; i--) + { + jointAddr = jointOffsets.Keys.ElementAt(i); + if (!bodyJoints.Contains(jointAddr)) + { + jointOffsets.Remove(jointAddr); + } + } + for (int i = ikOffsets.Count - 1; i >= 0; i--) + { + jointAddr = ikOffsets.Keys.ElementAt(i); + if (!bodyJoints.Contains(jointAddr)) + { + ikOffsets.Remove(jointAddr); + } + } + } + } + + private void drawArmorParts(nint armorAddr) + { + ImGui.PushID(armorAddr); + nint partsAddr = MemoryUtil.Read(armorAddr + 0x2A0); + string fullString = Marshal.PtrToStringAnsi(partsAddr + 0xC)!; + string partName = parsePartName(fullString); + ImGui.Text($"{partName} ({partsAddr:X}, {fullString} @ {armorAddr:X}):"); + int numParts = MemoryUtil.Read(partsAddr + 0x54C); + nint baseInner = MemoryUtil.Read(partsAddr + 0xC8); + nint offset = MemoryUtil.Read(partsAddr + 0x408); + bool toggleAll = ImGui.Button("Toggle All"); + for (int i = 0; i < numParts; i++) + { + nint baseOffset = offset + (i * 0x4) + (numParts * 0x4); + ref byte bIndex = ref MemoryUtil.GetRef(baseOffset); + baseOffset = baseInner + ((bIndex + (bIndex * 4)) << 4); + ref byte bEnabled = ref MemoryUtil.GetRef(baseOffset); + ref byte bSub = ref MemoryUtil.GetRef(baseOffset + 0xB); + if (toggleAll) + { + (bEnabled, bSub) = (bSub, bEnabled); + } + bool isVisible = bEnabled != 0x0; + if (ImGui.Checkbox($"##Part #{i}", ref isVisible)) + { + (bEnabled, bSub) = (bSub, bEnabled); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text($"Part #{i}"); + ImGui.EndTooltip(); + } + if (i % 10 != 9 && i != numParts - 1) + { + ImGui.SameLine(); + } + } + if (ImGui.CollapsingHeader("Joints")) + { + if (partName == "body") + { + ImGui.Checkbox("Attach to Chest", ref attachToChest); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("While in Free Camera, hold LT + RT and move your joysticks (armor has to have jiggle physics)."); + ImGui.EndTooltip(); + } + ImGui.Checkbox("Swap Sides", ref swapChestSides); + ImGui.DragFloat("Scale", ref chestMoveScale); + if (ImGui.CollapsingHeader("Jiggle Bones")) + { + for (int i = 0; i < jiggleBones.Count; i++) + { + nint jiggleData = jiggleBones[i]; + if (ImGui.CollapsingHeader($"Jiggle Bones #{i} ({jiggleData:X})")) + { + ImGui.DragFloat3("Position", ref MemoryUtil.GetRef(jiggleData + 0xD0)); + } + } + foreach (nint jiggleData in jiggleBones) + { + + } + } + ImGui.Separator(); + for (int i = 0; i < bodyJoints.Count; i++) + { + nint jointAddr = bodyJoints[i]; + ImGui.PushID(jointAddr); + byte jointGroup = MemoryUtil.Read(jointAddr + 0x14); + if (ImGui.CollapsingHeader($"Joint #{i} ({jointAddr:X}, {jointGroup:X})")) + { + ImGui.DragFloat4("Rotation", ref MemoryUtil.GetRef(jointAddr + 0x70), 0.005f); + if (partName != "face000") + { + if (!jointOffsets.ContainsKey(jointAddr)) + { + if (ImGui.Button("Add Offset")) + { + jointOffsets.Add(jointAddr, new List() + { + new Vector3() + }); + } + } + else + { + bool doRemove = ImGui.Button("X"); + ImGui.SameLine(); + Vector3 v = jointOffsets[jointAddr][0]; + if (ImGui.DragFloat3($"Rotation Offset", ref v, 0.005f)) + { + jointOffsets[jointAddr][0] = v; + } + if (doRemove) jointOffsets.Remove(jointAddr); + } + if (ikJoints.Contains(jointAddr)) + { + if (!ikOffsets.ContainsKey(jointAddr)) + { + if (ImGui.Button("Add IK Offset")) + { + ikOffsets.Add(jointAddr, new List() + { + new Vector3() + }); + } + } + else + { + bool doRemove = ImGui.Button("X"); + ImGui.SameLine(); + Vector3 v = ikOffsets[jointAddr][0]; + if (ImGui.DragFloat3($"Position Offset", ref v, 0.025f)) + { + ikOffsets[jointAddr][0] = v; + } + if (doRemove) ikOffsets.Remove(jointAddr); + } + } + } + } + ImGui.PopID(); + } + } + /* + else if (partName == "face000") + { + if (ImGui.Checkbox("Override Pose", ref overrideFacePose)) + { + if (overrideFacePose) + { + noopFacePose.Enable(); + noopFacePoseUpdate.Enable(); + } + else + { + noopFacePose.Disable(); + noopFacePoseUpdate.Disable(); + } + } + for (int i = 0; i < faceJoints.Count; i++) + { + nint jointAddr = faceJoints[i]; + ImGui.PushID(jointAddr); + if (ImGui.CollapsingHeader($"Joint #{i} ({jointAddr:X})")) + { + ImGui.DragFloat4("Position", ref MemoryUtil.GetRef(jointAddr + 0x50), 0.005f); + ImGui.DragFloat4("Rotation", ref MemoryUtil.GetRef(jointAddr + 0x70), 0.005f); + } + ImGui.PopID(); + } + } + */ + } + ImGui.PopID(); + } + + private void dropArmorState() + { + Array.Clear(playerArmor, 0, playerArmor.Length); + bodyJoints.Clear(); + //faceJoints.Clear(); + jiggleBones.Clear(); + } + + private void dropJointOffsets() + { + jointOffsets.Clear(); + ikOffsets.Clear(); + } + + private bool collectArmorAndJoints(Player player) + { + nint bodyArmorParts = MemoryUtil.Read(player.Instance + 0x2A0); + if (bodyArmorParts == 0x0) + { + return false; + } + // MonsterHunterWorld.exe+203E8A2 - mov rax,[rbx+000126C8] + nint combineArmorList = MemoryUtil.Read(player.Instance + 0x126C8); + if (combineArmorList == 0x0) + { + return false; + } + collectArmorParts(player.Instance, bodyArmorParts); + combineArmorList = MemoryUtil.Read(combineArmorList + 0x70); + nint next = combineArmorList; + while (next != 0x0) + { + nint armorAddr = next; + next = MemoryUtil.Read(armorAddr + 0x30); + nint vtable = MemoryUtil.Read(armorAddr); + // uWeaponParts: 0x1434D2400, uWeaponEmblem: 0x1434D1D58 + if (vtable == 0x1434A7560) // uPlCombineArmor + { + nint partsAddr = 0x0; + nint childAddr = MemoryUtil.Read(armorAddr + 0x548); + if (childAddr != 0x0) + { + if (MemoryUtil.Read(childAddr) == 0x143451520) + { + nint ownerAddr = MemoryUtil.Read(childAddr + 0x998); + if (playerArmor[Armor.Face] != 0x0 || ownerAddr != player.Instance) + { + continue; + } + partsAddr = MemoryUtil.Read(childAddr + 0x2A0); + if (partsAddr != 0x0) + { + collectArmorParts(childAddr, partsAddr); + } + } + else if (childAddr != player.Instance) + { + continue; + } + } + partsAddr = MemoryUtil.Read(armorAddr + 0x2A0); + if (partsAddr != 0x0) + { + collectArmorParts(armorAddr, partsAddr); + } + } + } + return true; + } + + private void UpdateJointsHook(nint obj, nint unknownPtr, int unknownInt, int unknownInt2) { - if (!didJointOffset) + if (jointOffsets.Count > 0 && !didJointOffset) { Player? player = Player.MainPlayer; if (player == null) { player = getPlayerFromSaveSlot(); } - if (player != null && entity == player.Instance) + if (player != null && obj == player.Instance) { + dropArmorState(); + if (!collectArmorAndJoints(player)) + { + dropJointOffsets(); + } + if (playerArmor[Armor.Waist] != 0x0) + { + MemoryUtil.GetRef(playerArmor[Armor.Waist] + 0x2D0) = hideKnife ? (byte)0xFD : (byte)0xFF; + } foreach ((nint addr, List offsets) in jointOffsets) { MemoryUtil.GetRef(addr + 0x70) *= Quaternion.CreateFromYawPitchRoll(offsets[0].X, offsets[0].Y, offsets[0].Z); @@ -2425,9 +2913,20 @@ namespace NewCamera didJointOffset = true; } } - checkJointRotationHook!.Original(entity, joint); + updateJointsHook!.Original(obj, unknownPtr, unknownInt, unknownInt2); } + private void UpdateIKHook(nint superOfChild, nint joint, nint obj) + { + if (ikOffsets.ContainsKey(joint)) + { + Vector3 offset = ikOffsets[joint][0]; + MemoryUtil.GetRef(superOfChild + 0x1380) += offset; + } + updateIKHook!.Original(superOfChild, joint, obj); + } + + /* private void ChangeEquipmentHook(nint unknownPtr, int unknownInt) { nint rax = MemoryUtil.Read(unknownPtr + 0x2968); @@ -2439,6 +2938,7 @@ namespace NewCamera lastEquipedId = MemoryUtil.Read(newEquipment + 0x24); changeEquipmentHook!.Original(unknownPtr, unknownInt); } + */ private void UnderwaterCheckHook(nint unknownPtr) { @@ -2546,22 +3046,26 @@ namespace NewCamera // MonsterHunterWorld.exe+12A9AEC - mov rcx,[rdi+00001E90] // MonsterHunterWorld.exe+11A9AB9 - add rcx,00001410 // MonsterHunterWorld.exe+12A9AE0 - mov rcx,[MonsterHunterWorld.exe+5013950] + ImGui.Text("Camera Distance"); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); nint playerCameraAddr = MemoryUtil.Read(player.Instance + 0x14F8); playerCameraAddr = MemoryUtil.Read(playerCameraAddr + 0x1410 + 0x1E90); - nint baseSettingAddr = MemoryUtil.Read(0x145013950); - baseSettingAddr = calcOffsetSettingAddr.Invoke(baseSettingAddr); - ref byte settingB = ref MemoryUtil.GetRef(baseSettingAddr + 0x1403FD); + ref byte settingB = ref MemoryUtil.GetRef(getPlayerSettings() + 0x1403FD); int settingI = settingB; + ImGui.SameLine(); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); if (ImGui.RadioButton("Close", ref settingI, 0)) { settingB = (byte)settingI; } ImGui.SameLine(); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); if (ImGui.RadioButton("Default", ref settingI, 1)) { settingB = (byte)settingI; } ImGui.SameLine(); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); if (ImGui.RadioButton("Far", ref settingI, 2)) { settingB = (byte)settingI; @@ -2798,6 +3302,7 @@ namespace NewCamera animationLayer.Paused = animationPaused; } ImGui.SameLine(); + /* float? lockedSpeed = animationLayer.LockedSpeed; bool animationLocked = lockedSpeed != null; if (ImGui.Checkbox("Set", ref animationLocked)) @@ -2814,18 +3319,12 @@ namespace NewCamera } ImGui.SameLine(); ImGui.PushItemWidth(width * 0.35f); - if (animationLocked) + float speed = animationLocked ? (float)lockedSpeed! : animationLayer.Speed; + if (ImGui.DragFloat($"Speed", ref speed, 0.01f, 0.0f, 0.0f, "%.3f")) { - float requestSpeed = (float)lockedSpeed!; - if (ImGui.DragFloat($"Speed", ref requestSpeed, 0.01f, 0.0f, 0.0f, "%.3f")) - { - animationLayer.LockSpeed(requestSpeed); - } - } - else - { - ImGui.DragFloat($"Speed", ref animationLayer.Speed, 0.01f, 0.0f, 0.0f, "%.3f"); + if (animationLocked) animationLayer.LockSpeed(speed); } + */ ImGui.PopItemWidth(); } } @@ -2921,192 +3420,6 @@ namespace NewCamera } } - void drawArmorParts(nint baseAddr, nint addr) - { - ImGui.PushID(addr); - string fullString = Marshal.PtrToStringAnsi(addr + 0xC)!; - string partName = ""; - if (fullString.StartsWith("pl\\f_equip")) - { - partName = fullString.Split('\\')[3]; - } - else if (fullString.StartsWith("pl\\hair")) - { - partName = fullString.Split('\\')[1]; - } - else if (fullString.StartsWith("pl\\f_face")) - { - partName = fullString.Split('\\')[2]; - } - else if (fullString.StartsWith("wp\\slg")) - { - partName = "slinger"; - } - else if (fullString.StartsWith("accessory\\acc")) - { - partName = fullString.Split('\\')[1]; - } - else if (fullString.StartsWith("npc\\npc")) - { - partName = "npc"; - } - if (partName == "body") - { - chestBone1 = 0x0; - chestBone2 = 0x0; - } - /* - if (partName == "wst") - { - //MemoryUtil.GetRef(next + 0x2D0) = hideKnife ? (byte)0xFD : (byte)0xFF; - } - */ - ImGui.Text($"{partName} ({baseAddr:X}, {fullString} @ {addr:X}):"); - int parts = MemoryUtil.Read(addr + 0x54C); - nint baseInner = MemoryUtil.Read(addr + 0xC8); - nint offset = MemoryUtil.Read(addr + 0x408); - bool toggleAll = ImGui.Button("Toggle All"); - for (int i = 0; i < parts; i++) - { - nint baseOffset = offset + (i * 0x4) + (parts * 0x4); - ref byte bIndex = ref MemoryUtil.GetRef(baseOffset); - baseOffset = baseInner + ((bIndex + (bIndex * 4)) << 4); - ref byte bEnabled = ref MemoryUtil.GetRef(baseOffset); - ref byte bSub = ref MemoryUtil.GetRef(baseOffset + 0xB); - if (toggleAll) - { - (bEnabled, bSub) = (bSub, bEnabled); - } - bool isVisible = bEnabled != 0x0; - 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(); - } - } - if (ImGui.CollapsingHeader("Joints")) - { - if (partName == "body") - { - ImGui.Checkbox("Attach to Chest", ref attachToChest); - ImGui.Checkbox("Swap Sides", ref swapChestSides); - ImGui.DragFloat("Scale", ref chestMoveScale); - } - else if (partName == "face000") - { - if (ImGui.Checkbox("Override Pose", ref overrideFacePose)) - { - if (overrideFacePose) - { - noopFacePose.Enable(); - noopFacePoseUpdate.Enable(); - } - else - { - noopFacePose.Disable(); - noopFacePoseUpdate.Disable(); - } - } - } - int jointCount = MemoryUtil.Read(baseAddr + 0x4A0); - nint jointsAddr = MemoryUtil.Read(baseAddr + 0x4A8); - ImGui.Text($"Count: {jointCount}"); - List seenJiggleBones = new List(); - for (int i = 0; i < jointCount; i++) - { - ImGui.PushID(i); - if (ImGui.CollapsingHeader($"Joint #{i} ({jointsAddr:X})")) - { - ImGui.DragFloat4("Rotation", ref MemoryUtil.GetRef(jointsAddr + 0x70), 0.005f); - if (partName != "face000") - { - if (!jointOffsets.ContainsKey(jointsAddr)) - { - jointOffsets.Add(jointsAddr, new List() - { - new Vector3() - }); - } - Vector3 v = jointOffsets[jointsAddr][0]; - ImGui.DragFloat3($"Rotation Offset", ref v, 0.005f); - jointOffsets[jointsAddr][0] = v; - } - } - /* - // MonsterHunterWorld.exe+223B9C3 - test byte ptr [rbx+000000A8],20 - if (MemoryUtil.Read(jointsAddr + 0xA8) == 0x20) - { - jointsAddr += 0xC0; - continue; - } - */ - nint childAddr = MemoryUtil.Read(jointsAddr + 0x8); - if (childAddr != 0x0 && MemoryUtil.Read(childAddr) == 0x142F21A90) - { - childAddr = MemoryUtil.Read(childAddr + 0x8); - if (childAddr != 0x0 && MemoryUtil.Read(childAddr) == 0x143524BD8) - { - childAddr = MemoryUtil.Read(childAddr + 0x188); - if (childAddr != 0x0) - { - nint childVtable = MemoryUtil.Read(childAddr); - if (childVtable == 0x143519530) - { - nint jiggleData = MemoryUtil.Read(MemoryUtil.Read(childAddr + 0xA0)); - if (!seenJiggleBones.Contains(jiggleData) && MemoryUtil.Read(jiggleData) == 0x143519508) - { - seenJiggleBones.Add(jiggleData); - if (partName == "body") - { - if (chestBone1 == 0x0) - { - chestBone1 = jiggleData; - } - else - { - if (chestBone2 != 0x0) - { - chestBone2 = chestBone1; - chestBone1 = jiggleData; - } - else - { - chestBone2 = jiggleData; - } - } - } - if (ImGui.CollapsingHeader($"Jiggle Bones ({jiggleData:X})")) - { - ImGui.DragFloat4("Position", ref MemoryUtil.GetRef(jiggleData + 0xD0)); - } - } - } - /* - else - { - if (ImGui.CollapsingHeader($"Unknown Child {childAddr:X}")) - { - } - } - */ - } - } - } - ImGui.PopID(); - jointsAddr += 0xC0; - } - } - ImGui.PopID(); - } - private void drawPlayerInfo(Player player, float width) { nint playerSettings = getPlayerSettings(); @@ -3117,118 +3430,92 @@ namespace NewCamera 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}"); - + ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f)); + ImGui.Text("Head Armor Display"); // MonsterHunterWorld.exe+11A2967 - cmp byte ptr [rax+001403E1],01 ref byte showHeadArmor = ref MemoryUtil.GetRef(playerSettings + 0x1403E1); int showHeadArmorInt = showHeadArmor; + ImGui.SameLine(); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); if (ImGui.RadioButton("Show", ref showHeadArmorInt, 0)) { showHeadArmor = (byte)showHeadArmorInt; } ImGui.SameLine(); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); if (ImGui.RadioButton("Hide", ref showHeadArmorInt, 1)) { showHeadArmor = (byte)showHeadArmorInt; } ImGui.SameLine(); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); if (ImGui.RadioButton("Hide in Cutscenes", ref showHeadArmorInt, 2)) { showHeadArmor = (byte)showHeadArmorInt; } + ImGui.Separator(); + + ref byte ikDisabledB = ref MemoryUtil.GetRef(MemoryUtil.Read(player.Instance + 0x990) + 0x5C); + bool ikDisabled = ikDisabledB == 0x0; + if (ImGui.Checkbox("Disable IK", ref ikDisabled)) + { + ikDisabledB = ByteFlag(!ikDisabled); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Mostly disable inverse kinematics on your player. To rotate ankles, you need to use Force Disable IK."); + ImGui.EndTooltip(); + } + ImGui.SameLine(); + if (ImGui.Checkbox("Force Disable IK", ref ikForcedOff)) + { + if (ikForcedOff) + { + forceDisableIK.Enable(); + } + else + { + forceDisableIK.Disable(); + } + } + if (ImGui.CollapsingHeader("Armor Parts")) { - nint bodyArmor = MemoryUtil.Read(player.Instance + 0x2A0); - if (bodyArmor != 0x0) + dropArmorState(); + if (!collectArmorAndJoints(player)) { - drawArmorParts(player.Instance, bodyArmor); + dropJointOffsets(); } - // MonsterHunterWorld.exe+203E8A2 - mov rax,[rbx+000126C8] - nint combineArmorList = MemoryUtil.Read(player.Instance + 0x126C8); - if (combineArmorList != 0x0) + ImGui.Text($"Offset Count: {jointOffsets.Count}, IK Offset Count: {ikOffsets.Count}"); + if (ImGui.CollapsingHeader($"Body (id: 0x{MemoryUtil.Read(player.Instance + 0x13740):X})")) { - combineArmorList = MemoryUtil.Read(combineArmorList + 0x70); + drawArmorParts(playerArmor[Armor.Body]); } - nint next = combineArmorList; - while (next != 0x0) + if (ImGui.CollapsingHeader($"Helmet (id: 0x{MemoryUtil.Read(player.Instance + 0x1373C):X})")) { - ImGui.PushID(next); - nint vtable = MemoryUtil.Read(next); - if ((vtable == 0x1434A7560) // uPlCombineArmor - //(vtable == 0x1434D2400) || // uWeaponParts - //(vtable == 0x1434D1D58) // uWeaponEmblem - ) - { - ImGui.Separator(); - nint partAddr = MemoryUtil.Read(next + 0x2A0); - if (partAddr != 0x0) - { - drawArmorParts(next, partAddr); - } - nint childAddr = MemoryUtil.Read(next + 0x548); - if (childAddr != 0x0) - { - if (childAddr == player.Instance) - { - // Owned by - } - if (MemoryUtil.Read(childAddr) == 0x143451520) - { - partAddr = MemoryUtil.Read(childAddr + 0x2A0); - if (partAddr != 0x0) - { - drawArmorParts(childAddr, partAddr); - } - childAddr = MemoryUtil.Read(childAddr + 0x998); - if (childAddr == player.Instance) - { - // Owned by - } - } - } - } - ImGui.PopID(); - next = MemoryUtil.Read(next + 0x30); + drawArmorParts(playerArmor[Armor.Helmet]); + } + if (ImGui.CollapsingHeader($"Arms (id: 0x{MemoryUtil.Read(player.Instance + 0x13744):X})")) + { + drawArmorParts(playerArmor[Armor.Arm]); + } + if (ImGui.CollapsingHeader($"Waist (id: 0x{MemoryUtil.Read(player.Instance + 0x13748):X})")) + { + drawArmorParts(playerArmor[Armor.Waist]); + } + if (ImGui.CollapsingHeader($"Legs (id: 0x{MemoryUtil.Read(player.Instance + 0x1374C):X})")) + { + drawArmorParts(playerArmor[Armor.Leg]); } + ImGui.Text($"Slinger: {MemoryUtil.Read(player.Instance + 0x13D8C):X}_{MemoryUtil.Read(player.Instance + 0x13D90):X}"); /* - nint bodyArmor = MemoryUtil.Read(player.Instance + 0x2A0); - if (bodyArmor != 0x0) + ImGui.Text($"Last Equipped: {lastEquipedId:X}"); + */ + /* + if (ImGui.CollapsingHeader("Face")) { - nint next = bodyArmor - 0x40; - nint head = next; - nint prev = MemoryUtil.Read(next + 0x10); - for (;next != 0x0;) - { - ImGui.PushID(next); - nint partAddr = next + 0x40; - nint vtable = MemoryUtil.Read(partAddr); - if (vtable == 0x143507A18) - { - drawArmorParts(partAddr); - } - ImGui.PopID(); - if (head == prev) - { - next = MemoryUtil.Read(next + 0x10); - } - else - { - next = MemoryUtil.Read(next + 0x18); - if (next == 0x0) - { - head = prev; - next = prev; - } - } - } + drawArmorParts(playerArmor[Armor.Face]); } */ } @@ -3262,9 +3549,7 @@ namespace NewCamera setPlayerController5.Invoke(controlsAddr); } int zoneStateInt = (int)forceZoneState; - Vector2 pos = ImGui.GetCursorPos(); - pos.Y += 6; - ImGui.SetCursorPos(pos); + ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f)); ImGui.Text($"Force Zone State (Current: {((MemoryUtil.GetRef(zoneStateAddr + 0xD2EA) == 0x1) ? "Hub" : "Combat")})"); if (ImGui.BeginItemTooltip()) { @@ -3272,19 +3557,13 @@ namespace NewCamera ImGui.EndTooltip(); } ImGui.SameLine(); - pos = ImGui.GetCursorPos(); - pos.Y -= 6; - ImGui.SetCursorPos(pos); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); ImGui.RadioButton("Off", ref zoneStateInt, 0); ImGui.SameLine(); - pos = ImGui.GetCursorPos(); - pos.Y -= 6; - ImGui.SetCursorPos(pos); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); ImGui.RadioButton("Hub", ref zoneStateInt, 1); ImGui.SameLine(); - pos = ImGui.GetCursorPos(); - pos.Y -= 6; - ImGui.SetCursorPos(pos); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); ImGui.RadioButton("Combat", ref zoneStateInt, 2); forceZoneState = (ZoneState)zoneStateInt; if (ImGui.Button("Run Change Zone State")) -- cgit v1.2.3-101-g0448