summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2026-09-20 17:21:13 -0400
committerAndrew Opalach <andrew@akon.city> 2026-09-20 17:21:13 -0400
commit4bc1b337dc7688d470aff128f9c03ee9d359600d (patch)
tree011afcaad82842391480a26097ce210e4d73c166
parent9a6fdac7b40ba3eba601d545d28350d4c53d3a3d (diff)
downloadNewCamera-4bc1b337dc7688d470aff128f9c03ee9d359600d.tar.gz
NewCamera-4bc1b337dc7688d470aff128f9c03ee9d359600d.tar.bz2
NewCamera-4bc1b337dc7688d470aff128f9c03ee9d359600d.zip
Add joint position offsets
Signed-off-by: Andrew Opalach <andrew@akon.city>
-rwxr-xr-xPlugin.cs197
1 files changed, 141 insertions, 56 deletions
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<UpdateJoints>? updateJointsHook;
+ private Hook<UpdateJoints>? updateJointRotationHook;
+ private Hook<UpdateJoints>? updateJointPositionHook;
private List<nint> bodyJoints = new List<nint>();
private List<nint> ignoredJoints = new List<nint>();
private Dictionary<nint, List<Vector3>> bodyRotations = new Dictionary<nint, List<Vector3>>();
+ private Dictionary<nint, List<Vector3>> bodyOffsets = new Dictionary<nint, List<Vector3>>();
private List<nint> faceJoints = new List<nint>();
private Dictionary<nint, List<Vector3>> faceRotations = new Dictionary<nint, List<Vector3>>();
+ private Dictionary<nint, List<Vector3>> faceOffsets = new Dictionary<nint, List<Vector3>>();
#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<UpdateJoints>(0x14223BA30, UpdateJointsHook);
+ updateJointRotationHook = Hook.Create<UpdateJoints>(0x14223BA30, UpdateJointRotationHook);
+ updateJointPositionHook = Hook.Create<UpdateJoints>(0x142228F50, UpdateJointPositionHook);
#if QUARANTINED_FEATURES
updateIKHook = Hook.Create<UpdateIK>(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<nint, List<Vector3>> rotations)
+ private void drawJoint(nint jointAddr, Dictionary<nint, List<Vector3>> rotations, Dictionary<nint, List<Vector3>> offsets)
{
if (jointAddr == 0x0) return;
ImGui.PushID(jointAddr);
- ImGui.DragFloat4("Position", ref MemoryUtil.GetRef<Vector4>(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<Vector4>(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<Vector3>()
- {
- 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<Vector4>(jointAddr + 0x70), 0.005f);
- if (ikJoint)
+ ImGui.DragFloat4("Position", ref MemoryUtil.GetRef<Vector4>(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<Vector3>()
+ {
+ 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<Vector3>()
+ {
+ 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<nint> joints, int i, Dictionary<nint, List<Vector3>> rotations)
+ private void drawJointLeaf(ref List<nint> joints, int i, Dictionary<nint, List<Vector3>> rotations, Dictionary<nint, List<Vector3>> 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<Quaternion>(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<Vector3> offsets) in bodyOffsets)
+ {
+ MemoryUtil.GetRef<Vector3>(addr + 0x50) += offsets[0];
+ }
+ }
+ else if (player != null && model == playerArmor[Armor.Face])
+ {
+ refreshArmorState(player);
+ foreach ((nint addr, List<Vector3> offsets) in faceOffsets)
+ {
+ MemoryUtil.GetRef<Vector3>(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));