From 4bc1b337dc7688d470aff128f9c03ee9d359600d Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sun, 20 Sep 2026 17:21:13 -0400 Subject: Add joint position offsets Signed-off-by: Andrew Opalach --- Plugin.cs | 197 ++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 141 insertions(+), 56 deletions(-) (limited to 'Plugin.cs') diff --git a/Plugin.cs b/Plugin.cs index ee9580f..132611c 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -517,13 +517,16 @@ namespace NewCamera private nint[] playerJoints = new nint[0xFF]; private delegate void UpdateJoints(nint obj); - private Hook? updateJointsHook; + private Hook? updateJointRotationHook; + private Hook? updateJointPositionHook; private List bodyJoints = new List(); private List ignoredJoints = new List(); private Dictionary> bodyRotations = new Dictionary>(); + private Dictionary> bodyOffsets = new Dictionary>(); private List faceJoints = new List(); private Dictionary> faceRotations = new Dictionary>(); + private Dictionary> faceOffsets = new Dictionary>(); #if QUARANTINED_FEATURES private delegate void UpdateIK(nint superOfChild, nint joint, nint obj); @@ -877,7 +880,8 @@ namespace NewCamera forceDisableIK = new Patch(lton(0x14031FD40), [0xC6, 0x81, 0x81, 0x01, 0x00, 0x00, 0x00, 0xC3]); // Alt: 0x141FBC7A0 (model - 0x958) - updateJointsHook = Hook.Create(0x14223BA30, UpdateJointsHook); + updateJointRotationHook = Hook.Create(0x14223BA30, UpdateJointRotationHook); + updateJointPositionHook = Hook.Create(0x142228F50, UpdateJointPositionHook); #if QUARANTINED_FEATURES updateIKHook = Hook.Create(0x142472C00, UpdateIKHook); @@ -2728,6 +2732,10 @@ namespace NewCamera { bodyRotations.Remove(joint); } + foreach (nint joint in bodyOffsets.Where(e => !bodyJoints.Contains(e.Key)).Select(e => e.Key).ToList()) + { + bodyOffsets.Remove(joint); + } #if QUARANTINED_FEATURES foreach (nint joint in ikOffsets.Where(e => !bodyJoints.Contains(e.Key)).Select(e => e.Key).ToList()) { @@ -2735,47 +2743,86 @@ namespace NewCamera } #endif } + else if (part == Armor.Face) + { + foreach (nint joint in faceRotations.Where(e => !faceJoints.Contains(e.Key)).Select(e => e.Key).ToList()) + { + faceRotations.Remove(joint); + } + foreach (nint joint in faceOffsets.Where(e => !faceJoints.Contains(e.Key)).Select(e => e.Key).ToList()) + { + faceOffsets.Remove(joint); + } + } } - private void drawJoint(nint jointAddr, Dictionary> rotations) + private void drawJoint(nint jointAddr, Dictionary> rotations, Dictionary> offsets) { if (jointAddr == 0x0) return; ImGui.PushID(jointAddr); - ImGui.DragFloat4("Position", ref MemoryUtil.GetRef(jointAddr + 0x50), 0.005f); - bool ikJoint = false; + bool hasRotation = rotations.ContainsKey(jointAddr); + bool hasOffset = offsets.ContainsKey(jointAddr); #if QUARANTINED_FEATURES - if (ikJoints.Contains(jointAddr)) + bool hasIkOffset = ikOffsets.ContainsKey(jointAddr); +#endif + ImGui.DragFloat4("Rotation", ref MemoryUtil.GetRef(jointAddr + 0x70), 0.005f); + if (hasRotation) { - if (!ikOffsets.ContainsKey(jointAddr)) + ImGui.PushID("Rotation"); + bool doRemove = ImGui.Button("X"); + ImGui.SameLine(); + if (ImGui.Button("Reset")) { - if (ImGui.Button("Add IK Offset")) - { - ikOffsets.Add(jointAddr, new List() - { - new Vector3() - }); - } + rotations[jointAddr][0] = default; } - else + ImGui.SameLine(); + Vector3 v = rotations[jointAddr][0]; + if (ImGui.DragFloat3($"##Rotation Offset", ref v, 0.005f)) { - bool doRemove = ImGui.Button("X"); - ImGui.SameLine(); - Vector3 v = ikOffsets[jointAddr][0]; - if (ImGui.DragFloat3($"Offset", ref v, 0.025f)) - { - ikOffsets[jointAddr][0] = v; - } - if (doRemove) ikOffsets.Remove(jointAddr); + rotations[jointAddr][0] = v; } - //ikJoint = true; + if (doRemove) rotations.Remove(jointAddr); + ImGui.PopID(); } -#endif - ImGui.DragFloat4("Rotation", ref MemoryUtil.GetRef(jointAddr + 0x70), 0.005f); - if (ikJoint) + ImGui.DragFloat4("Position", ref MemoryUtil.GetRef(jointAddr + 0x50), 0.005f); + if (hasOffset) { - ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); + ImGui.PushID("Position"); + bool doRemove = ImGui.Button("X"); + ImGui.SameLine(); + if (ImGui.Button("Reset")) + { + offsets[jointAddr][0] = default; + } + ImGui.SameLine(); + Vector3 v = offsets[jointAddr][0]; + if (ImGui.DragFloat3($"##Position Offset", ref v, 0.005f)) + { + offsets[jointAddr][0] = v; + } + if (doRemove) offsets.Remove(jointAddr); + ImGui.PopID(); } - bool hasRotation = rotations.ContainsKey(jointAddr); +#if QUARANTINED_FEATURES + if (hasIkOffset) + { + ImGui.PushID("IK"); + bool doRemove = ImGui.Button("X"); + ImGui.SameLine(); + if (ImGui.Button("Reset")) + { + ikOffsets[jointAddr][0] = default; + } + ImGui.SameLine(); + Vector3 v = ikOffsets[jointAddr][0]; + if (ImGui.DragFloat3($"##IK Offset", ref v, 0.025f)) + { + ikOffsets[jointAddr][0] = v; + } + if (doRemove) ikOffsets.Remove(jointAddr); + ImGui.PopID(); + } +#endif if (!hasRotation) { if (ImGui.Button("Add Rotation")) @@ -2785,41 +2832,46 @@ namespace NewCamera new Vector3() }); } - if (ikJoint) + } + if (!hasOffset) + { + if (!hasRotation) { ImGui.SameLine(); } + if (ImGui.Button("Add Offset")) + { + offsets.Add(jointAddr, new List() + { + new Vector3() + }); + } } - if (ikJoint) - { - ImGui.Text("(Enforced by Inverse Kinematics)"); - ImGui.PopStyleVar(); - } - if (hasRotation) +#if QUARANTINED_FEATURES + if (ikJoints.Contains(jointAddr) && !hasIkOffset) { - bool doRemove = ImGui.Button("X"); - ImGui.SameLine(); - if (ImGui.Button("Reset")) + if (!hasOffset) { - rotations[jointAddr][0] = new Vector3(); + ImGui.SameLine(); } - ImGui.SameLine(); - Vector3 v = rotations[jointAddr][0]; - if (ImGui.DragFloat3($"Rotation", ref v, 0.005f)) + if (ImGui.Button("Add IK Offset")) { - rotations[jointAddr][0] = v; + ikOffsets.Add(jointAddr, new List() + { + new Vector3() + }); } - if (doRemove) rotations.Remove(jointAddr); } +#endif ImGui.PopID(); } private void drawJoint(nint jointAddr) { - drawJoint(jointAddr, bodyRotations); + drawJoint(jointAddr, bodyRotations, bodyOffsets); } - private void drawJointLeaf(ref List joints, int i, Dictionary> rotations) + private void drawJointLeaf(ref List joints, int i, Dictionary> rotations, Dictionary> offsets) { if (i >= joints.Count) return; nint jointAddr = joints[i]; @@ -2827,10 +2879,10 @@ namespace NewCamera ImGui.PushID(jointAddr); if (ImGui.CollapsingHeader($"Joint #{i} (0x{jointAddr:X}, id: 0x{id:X})")) { - drawJoint(jointAddr, rotations); + drawJoint(jointAddr, rotations, offsets); } ImGui.PopID(); - drawJointLeaf(ref joints, i + 1, rotations); + drawJointLeaf(ref joints, i + 1, rotations, offsets); } private void drawJoints(float width) @@ -3263,11 +3315,11 @@ namespace NewCamera ImGui.Separator(); if (ImGui.CollapsingHeader("Body Joints")) { - drawJointLeaf(ref bodyJoints, 0, bodyRotations); + drawJointLeaf(ref bodyJoints, 0, bodyRotations, bodyOffsets); } if (ImGui.CollapsingHeader("Face Joints")) { - drawJointLeaf(ref faceJoints, 0, faceRotations); + drawJointLeaf(ref faceJoints, 0, faceRotations, faceOffsets); } ImGui.PopItemWidth(); } @@ -3363,7 +3415,9 @@ namespace NewCamera private void dropJointOffsets() { bodyRotations.Clear(); + bodyOffsets.Clear(); faceRotations.Clear(); + faceOffsets.Clear(); #if QUARANTINED_FEATURES ikOffsets.Clear(); #endif @@ -3451,6 +3505,10 @@ namespace NewCamera collectArmorParts(armorAddr, partsAddr); } } + if (!playerArmor.Where(p => (p == 0x0)).Any()) + { + break; + } } return true; } @@ -3466,10 +3524,11 @@ namespace NewCamera private bool usingArmorState() { - return (bodyRotations.Count > 0 || faceRotations.Count > 0) || (hideKnife || checkKnifeHidden) || (enableFreeCamera && orbitPlayer && orbitJoint >= 0); + return (bodyRotations.Count > 0 || bodyOffsets.Count > 0 || faceRotations.Count > 0 || faceOffsets.Count > 0) || + (hideKnife || checkKnifeHidden) || (enableFreeCamera && orbitPlayer && orbitJoint >= 0); } - private void UpdateJointsHook(nint model) + private void UpdateJointRotationHook(nint model) { if (!disableMod && usingArmorState()) { @@ -3494,9 +3553,35 @@ namespace NewCamera { MemoryUtil.GetRef(addr + 0x70) *= Quaternion.CreateFromYawPitchRoll(rotations[0].X, rotations[0].Y, rotations[0].Z); } + + } + } + updateJointRotationHook!.Original(model); + } + + private void UpdateJointPositionHook(nint model) + { + updateJointPositionHook!.Original(model); + if (!disableMod && usingArmorState()) + { + Player? player = getPlayerWithFallback(); + if (player != null && model == player.Instance) + { + refreshArmorState(player); + foreach ((nint addr, List offsets) in bodyOffsets) + { + MemoryUtil.GetRef(addr + 0x50) += offsets[0]; + } + } + else if (player != null && model == playerArmor[Armor.Face]) + { + refreshArmorState(player); + foreach ((nint addr, List offsets) in faceOffsets) + { + MemoryUtil.GetRef(addr + 0x50) += offsets[0]; + } } } - updateJointsHook!.Original(model); } #if QUARANTINED_FEATURES @@ -4087,9 +4172,9 @@ namespace NewCamera } ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f)); #if QUARANTINED_FEATURES - ImGui.Text($"Joint Rotations: {bodyRotations.Count + faceRotations.Count}, IK Offsets: {ikOffsets.Count}"); + ImGui.Text($"Joint Rotations: {bodyRotations.Count + faceRotations.Count}, Joint Offsets: {bodyOffsets.Count + faceOffsets.Count}, IK Offsets: {ikOffsets.Count}"); #else - ImGui.Text($"Joint Rotations: {bodyRotations.Count + faceRotations.Count}"); + ImGui.Text($"Joint Rotations: {bodyRotations.Count + faceRotations.Count}, Joint Offsets: {bodyOffsets.Count + faceOffsets.Count}"); #endif ImGui.SameLine(); ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); -- cgit v1.2.3-101-g0448