summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2026-10-09 13:13:59 -0400
committerAndrew Opalach <andrew@akon.city> 2026-10-09 13:13:59 -0400
commita66fbdfab71ece98223d257f3a6da7ab0339ee1f (patch)
tree5289018b0b7130d9509eff971b060d0699f71b92
parent8abc6082c701084d505fa4fdf391a8cbf69e4fec (diff)
downloadNewCamera-a66fbdfab71ece98223d257f3a6da7ab0339ee1f.tar.gz
NewCamera-a66fbdfab71ece98223d257f3a6da7ab0339ee1f.tar.bz2
NewCamera-a66fbdfab71ece98223d257f3a6da7ab0339ee1f.zip
Bunch of wip stuffHEADmaster
Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--Animal.cs162
-rwxr-xr-xConfig.cs14
-rw-r--r--Models.cs576
-rw-r--r--Player.cs1880
-rwxr-xr-xPlugin.cs1292
-rw-r--r--Poser.cs2320
6 files changed, 3919 insertions, 2325 deletions
diff --git a/Animal.cs b/Animal.cs
index 1d27650..0b0e754 100644
--- a/Animal.cs
+++ b/Animal.cs
@@ -5,18 +5,12 @@ namespace SharpPluginLoader.Core.Entities
public class Animal : Entity
{
/// <summary>
- /// The sAnimal singleton instance
- /// </summary>
- public static MtObject SingletonInstance => SingletonManager.GetSingleton("sAnimal")!;
-
- /// <summary>
/// Gets a list of all animals in the game
/// </summary>
/// <returns></returns>
public static Animal[] GetAllAnimals()
{
- lock (_animals)
- return _animals.ToArray();
+ lock (_animals) return _animals.ToArray();
}
/// <summary>
@@ -29,30 +23,156 @@ namespace SharpPluginLoader.Core.Entities
public int Id => Get<int>(0x1AF8); // +0x294
public int OtherId => Get<int>(0x1AF0);
- private static void AnimalAddHook(nint instance)
+ private static nint uGmAnimalCtorHook(nint unknownPtr, int unknownInt)
{
- var animal = new Animal(instance);
- lock (_animals) _animals.Add(animal);
- _animalAddHook.Original(instance);
+ nint animalObject = _uGmAnimalCtor.Original(unknownPtr, unknownInt);
+ lock (_animals) _animals.Add(new Animal(animalObject));
+ return animalObject;
}
- private static nint AnimalRemoveHook(nint instance)
+ private static nint uGmAnimalDestructorHook(nint animalObject)
{
- var animal = new Animal(instance);
- lock(_animals) _animals.Remove(animal);
- return _animalRemoveHook.Original(instance);
+ lock(_animals)
+ {
+ for (int i = 0; i < _animals.Count; i++)
+ {
+ if (_animals[i].Instance == animalObject)
+ {
+ _animals.RemoveAt(i);
+ break;
+ }
+ }
+ }
+ return _uGmAnimalDestructor.Original(animalObject);
}
internal static void Initialize()
{
- _animalAddHook = Hook.Create<AnimalAddDelegate>(0x141D2F610, AnimalAddHook);
- _animalRemoveHook = Hook.Create<AnimalRemoveDelegate>(0x141D289D0, AnimalRemoveHook);
+ _uGmAnimalCtor = Hook.Create<uGmAnimalCtor>(0x141D285C0, uGmAnimalCtorHook);
+ _uGmAnimalDestructor = Hook.Create<uGmAnimalDestructor>(0x141D289D0, uGmAnimalDestructorHook);
}
- private delegate void AnimalAddDelegate(nint instance);
- private delegate nint AnimalRemoveDelegate(nint instance);
- private static Hook<AnimalAddDelegate> _animalAddHook = null!;
- private static Hook<AnimalRemoveDelegate> _animalRemoveHook = null!;
+ private delegate nint uGmAnimalCtor(nint unknownPtr, int unknownInt);
+ private delegate nint uGmAnimalDestructor(nint animalObject);
+ private static Hook<uGmAnimalCtor> _uGmAnimalCtor = null!;
+ private static Hook<uGmAnimalDestructor> _uGmAnimalDestructor = null!;
private static readonly List<Animal> _animals = [];
}
+
+ /// <summary>
+ /// Represents an animal id
+ /// </summary>
+ public enum AnimalType : uint
+ {
+ /*
+ Shepherd Hare = 1,
+ Pilot Hare = 1,
+ Woodland Pteryx = 2,
+ Forest Pteryx = 2,
+ Cobalt Flutterfly = 3,
+ Phantom Flutterfly = 3,
+ Climbing Joyperch = 4,
+ Forest Gekko = 5,
+ Wildspire Gekko = 5,
+ Gloom Gekko = 5,
+ Moonlight Gekko = 5,
+ Vaporonid = 6,
+ Scavantula = 6,
+ Revolture = 7,
+ Blissbill = 7,
+ Stonebill = 7,
+ Omenfly = 8,
+ Augurfly = 8,
+ Scalebat = 9,
+ Gold Scalebat = 9,
+ Dung Beetle = 10,
+ Bomb Beetle = 10,
+ Rime Beetle = 10,
+ Pink Parexus = 11,
+ Great Pink Parexus = 11,
+ Burst Arowana = 12,
+ Bomb Arowana = 12,
+ Great Burst Arowana = 12,
+ Great Bomb Arowana = 12,
+ Elegant Coralbird = 13,
+ Dapper Coralbird = 13,
+ Andangler = 14,
+ Downy Crake = 15,
+ Bristly Crake = 15,
+ Hopguppy = 16,
+ Petricanths = 17,
+ Paratoad = 18,
+ Sleeptoad = 18,
+ Nitrotoad = 18,
+ Wiggler = 19,
+ Wiggler Queen = 19,
+ Vigorwasp = 20,
+ Giant Vigorwasp = 20,
+ Flying Meduso = 21,
+ Carrier Ant = 22,
+ Hercudrome = 23,
+ Gold Hercudrome = 23,
+ Prism Hercudrome = 23,
+ Emperor Hopper = 24,
+ Tyrant Hopper = 24,
+ Flashfly = 25,
+ 羽虫 = 26,
+ ハエ = 27,
+ ハチ = 28,
+ 蛍 = 29,
+ Grandfather Mantagrell = 30,
+ Iron Helmcrab = 31,
+ Soldier Helmcrab = 31,
+ Emerald Helmcrab = 31,
+ Gold Helmcrab = 31,
+ Shiny Gold Helmcrab = 31,
+ 苦蟲 = 32,
+ 光蟲 = 32,
+ 不死蟲 = 32,
+ 雷光蟲 = 32,
+ 佳餚蟲 = 32,
+ Whetfish = 33,
+ Great Whetfish = 33,
+ Gastronome Tuna = 34,
+ Great Gastronome Tuna = 34,
+ King Marlin = 35,
+ Great King Marlin = 35,
+ 楔虫 = 36,
+ Goldenfish = 37,
+ Platinumfish = 37,
+ Great Goldenfish = 37,
+ Great Platinumfish = 37,
+ Goldenfry = 38,
+ Great Goldenfry = 38,
+ Sushifish = 39,
+ Great Sushifish = 39,
+ Gunpowderfish = 40,
+ Great Gunpowderfish = 40,
+ Copper Calappa = 41,
+ Gold Calappa = 41,
+ Tsuchinoko = 42,
+ Cactuar = 43,
+ Cactuar Cutting = 43,
+ Flowering Cactuar Cutting = 43,
+ Nekker = 44,
+ Pearlspring Macaque = 50,
+ Goldspring Macaque = 50,
+ Crowned Prawn = 51,
+ Moon Slug = 52,
+ Duffel Penguin = 53,
+ Arrowhead Gekko = 54,
+ Blue Diva = 55,
+ Sealord's Crestfish = 56,
+ Glass Parexus = 57,
+ Great Glass Parexus = 57,
+ Wintermoon Nettle = 58,
+ Moly = 59,
+ Mossy Moly = 59,
+ Rocky Moly = 59,
+ Fluffy Moly = 59,
+ Spiny Moly = 59,
+ Rowdy Moly = 59,
+ Frosty Moly = 59
+ */
+ }
}
diff --git a/Config.cs b/Config.cs
index 3537a9f..fef8b98 100755
--- a/Config.cs
+++ b/Config.cs
@@ -1,6 +1,4 @@
-#define MOUSE_AND_KEYBOARD_LAYER
-
-using SharpPluginLoader.Core.Configuration;
+using SharpPluginLoader.Core.Configuration;
using SharpPluginLoader.Core.IO;
namespace NewCamera
@@ -49,24 +47,20 @@ namespace NewCamera
{
EnableCombo = true;
FreeCameraCombo = "RStick,LT";
- DisableComboButton1UnlessButton2Held = false;
-#if MOUSE_AND_KEYBOARD_LAYER
+ ComboButton1BlocksUnlessButton2Held = false;
EnableMouse = true;
MouseSensitivity = 0.0225f;
EnableKeyboard = true;
KeyboardLookSensitivity = 19750;
-#endif
}
public bool EnableCombo { get; set; }
public String FreeCameraCombo { get; set; }
- public bool DisableComboButton1UnlessButton2Held { get; set; }
-#if MOUSE_AND_KEYBOARD_LAYER
+ public bool ComboButton1BlocksUnlessButton2Held { get; set; }
public bool EnableMouse { get; set; }
public float MouseSensitivity { get; set; }
public bool EnableKeyboard { get; set; }
public int KeyboardLookSensitivity { get; set; }
-#endif
}
}
@@ -143,7 +137,7 @@ namespace NewCamera
public Settings Camera { get; set; } = new Settings();
public Settings.Binds Binds { get; set; } = new Settings.Binds();
- public bool PerspectiveCameraEnabled { get; set; } = false;
+ public bool CameraOffsetEnabled { get; set; } = false;
public Dictionary<String, Preset> Presets { get; set; } = new Dictionary<String, Preset>();
public String Selected { get; set; } = "";
diff --git a/Models.cs b/Models.cs
new file mode 100644
index 0000000..b0872d9
--- /dev/null
+++ b/Models.cs
@@ -0,0 +1,576 @@
+using System.Numerics;
+using System.Runtime.InteropServices;
+using System.Text.RegularExpressions;
+
+using ImGuiNET;
+using SharpPluginLoader.Core;
+using SharpPluginLoader.Core.Memory;
+using SharpPluginLoader.Core.Entities;
+using SharpPluginLoader.Core.Actions;
+using SharpPluginLoader.Core.Components;
+
+namespace NewCamera
+{
+ using static Plugin;
+
+ public unsafe class Models
+ {
+ private static string modelFilter = "";
+ private static bool modelFilterIsRegex = false;
+ private static Regex? modelRegex = null;
+ public static bool modelOnlyAddressLod0 = false;
+
+ private static string objectFilter = "";
+ private static bool sortObjectsByDistanceToPlayer = false;
+
+ private static int inputLmt = -1;
+ private static int inputAnimationId = -1;
+ private static int inputSet = -1;
+ private static int inputActionId = -1;
+
+ public static bool DrawRotate(string label, Vector4 rotation, out Vector4 result)
+ {
+ Vector3 offset = new Vector3();
+ if (ImGui.DragFloat3(label, ref offset, 0.0025f))
+ {
+ Quaternion rotationQ = new Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W);
+ rotationQ *= Quaternion.CreateFromYawPitchRoll(offset.X, offset.Y, offset.Z);
+ result = new Vector4(rotationQ.X, rotationQ.Y, rotationQ.Z, rotationQ.W);
+ return true;
+ }
+ result = new Vector4(-1.0f);
+ return false;
+ }
+
+ public static string extractPartName(string fullString)
+ {
+ string partName = "";
+ if (fullString.StartsWith("pl\\f_equip") || fullString.StartsWith("pl\\m_equip"))
+ {
+ partName = fullString.Split('\\')[3];
+ }
+ else if (fullString.StartsWith("wp\\"))
+ {
+ string[] split = fullString.Split('\\');
+ if (split[4] == "mod")
+ {
+ partName = split[5];
+ }
+ else
+ {
+ partName = split[4];
+ }
+ }
+ else if (fullString.StartsWith("pl\\hair"))
+ {
+ partName = fullString.Split('\\')[2];
+ }
+ else if (fullString.StartsWith("pl\\f_face") || fullString.StartsWith("pl\\m_face"))
+ {
+ partName = fullString.Split('\\')[4].Substring(2);
+ }
+ return partName;
+ }
+
+ public static void drawModelParts(nint armorAddr, nint partsAddr = 0x0, bool hideAll = false, bool showAll = false)
+ {
+ if (partsAddr == 0x0)
+ {
+ if (armorAddr == 0x0 || (partsAddr = MemoryUtil.Read<nint>(armorAddr + 0x2A0)) == 0x0)
+ {
+ return;
+ }
+ }
+ ImGui.PushID(partsAddr);
+ string fullString = Marshal.PtrToStringAnsi(partsAddr + 0xC)!;
+ if (armorAddr != 0x0)
+ {
+ string partName = extractPartName(fullString);
+ ImGui.Text($"{partName} (0x{armorAddr:X}, {fullString} @ 0x{partsAddr:X}):");
+ }
+ else
+ {
+ ImGui.Text($"{fullString} @ 0x{partsAddr:X}:");
+ }
+ // MonsterHunterWorld.exe+222E651 - mov rax,[r8+000000C8]
+ nint baseLod = MemoryUtil.Read<nint>(partsAddr + 0xC8);
+ nint baseOffset = MemoryUtil.Read<nint>(partsAddr + 0x408 + (0x8 * 0x1));
+ int numParts = MemoryUtil.Read<int>(partsAddr + 0x548 + (0x4 * 0x1));
+ // Setting lodCount to 0 is probably the best way to completely hide a model.
+ int lodCount = MemoryUtil.Read<int>(partsAddr + 0xD0);
+ const int lodStructSize = 0x50;
+ const int partsPerLine = 10;
+ bool allOn = ImGui.Button("Show All") || showAll;
+ ImGui.SameLine();
+ bool allOff = ImGui.Button("Hide All") || hideAll;
+ for (int i = 0; i < numParts; i++)
+ {
+ ref int lodOffset = ref MemoryUtil.GetRef<int>(baseOffset + (i * 0x4));
+ nint lod0 = baseLod + lodOffset * lodStructSize;
+ bool isVisible = MemoryUtil.GetRef<ushort>(lod0) != 0;
+ bool togglePart = ImGui.Checkbox($"##Part #{i}", ref isVisible);
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text($"Part #{i} (0x{lod0:X})");
+ ImGui.EndTooltip();
+ }
+ int lastLod = (i < numParts - 1) ? MemoryUtil.Read<int>(baseOffset + ((i + 1) * 0x4)) : lodCount;
+ int partLodCount = lastLod - lodOffset;
+ // This is not a "proper" way to hide a part. It abuses the fact that if the lower
+ // 16 bits (lodVisible) of these 4 bytes are 0, a check to skip rendering it will
+ // always pass. Also that +0xA appears to be unused/padding.
+ // MonsterHunterWorld.exe+222FCE3 - mov eax,[r8]
+ ushort lod0Visible = MemoryUtil.GetRef<ushort>(lod0);
+ for (int j = 0; j < partLodCount; j++)
+ {
+ if (togglePart || (lod0Visible != 0 && allOff) || (lod0Visible == 0 && allOn))
+ {
+ nint lod = lod0 + (j * lodStructSize);
+ ref ushort lodVisible = ref MemoryUtil.GetRef<ushort>(lod);
+ ref ushort padSub = ref MemoryUtil.GetRef<ushort>(lod + 0xA);
+ if (lod0Visible != 0) Assert(padSub == 0);
+ // Check against LOD0 to prevent an inconsistent state.
+ if ((lodVisible != 0) == (lod0Visible != 0))
+ {
+ (lodVisible, padSub) = (padSub, lodVisible);
+ }
+ }
+ if (modelOnlyAddressLod0) break;
+ }
+ if (i != numParts - 1 && i % partsPerLine != partsPerLine - 1)
+ {
+ ImGui.SameLine();
+ }
+ }
+ ImGui.PopID();
+ }
+
+ public static void drawAnimationInfo(Entity entity, float width, bool debug)
+ {
+ ActionController actionController = entity.ActionController;
+ ActionInfo currentActionInfo = actionController.CurrentAction;
+ SharpPluginLoader.Core.Actions.Action? currentAction = null;
+ if (currentActionInfo.ActionSet >= 0 && currentActionInfo.ActionSet <= 3)
+ {
+ ActionList actionList = actionController.GetActionList(currentActionInfo.ActionSet);
+ if (currentActionInfo.ActionId >= 0 && currentActionInfo.ActionId < actionList.Count)
+ {
+ currentAction = actionList[currentActionInfo.ActionId];
+ }
+ }
+ if (debug)
+ {
+ ImGui.Text($"ActionController: 0x{actionController.Instance:X}");
+ ImGui.Text($" Current: {currentAction} {currentActionInfo}");
+ if (currentAction != null)
+ {
+
+ ImGui.Text($" Active Time: {currentAction.ActiveTime}");
+ ImGui.Text($" Delta Sec: {currentAction.DeltaSec}");
+ }
+ }
+ AnimationId currentAnimation = entity.CurrentAnimation;
+ AnimationLayerComponent? animationLayer = entity.AnimationLayer;
+ if (animationLayer != null)
+ {
+ ImGui.Text(debug ? $"AnimationLayer: 0x{animationLayer.Instance:X}" : "Animation");
+
+ if (debug)
+ {
+ ImGui.Text($" Current: {currentAnimation}");
+ ImGui.Text($" Frame: {animationLayer.CurrentFrame:0.000}/{animationLayer.MaxFrame:0.000}");
+ }
+ else
+ {
+ ImGui.Text($" Current: {currentAnimation.Lmt}.{currentAnimation.Id}, {(currentAction != null ? currentAction.Name : "None")}");
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("{Lmt}.{Id}, {Action}");
+ ImGui.EndTooltip();
+ }
+ ImGui.SetNextItemWidth(width * 0.8f);
+ ImGui.SliderFloat("Frame", ref animationLayer.CurrentFrame, 0.0f, animationLayer.MaxFrame, "%.3f");
+ bool animationPaused = animationLayer.Paused;
+ if (ImGui.Checkbox("Paused", ref animationPaused))
+ {
+ animationLayer.Paused = animationPaused;
+ }
+ ImGui.SameLine();
+ float? lockedSpeed = animationLayer.LockedSpeed;
+ float speed = lockedSpeed ?? animationLayer.Speed;
+ bool animationLocked = lockedSpeed != null;
+ if (ImGui.Checkbox("Set", ref animationLocked))
+ {
+ if (animationLocked)
+ {
+ animationLayer.LockSpeed(speed);
+ }
+ else
+ {
+ animationLayer.UnlockSpeed();
+ }
+ }
+ ImGui.SameLine();
+ ImGui.SetNextItemWidth(width * 0.3f);
+ if (ImGui.DragFloat($"Speed", ref speed, 0.01f, 0.0f, 0.0f, "%.3f"))
+ {
+ if (animationLocked) animationLayer.LockSpeed(speed);
+ }
+ }
+
+ if (debug)
+ {
+ ImGui.PushItemWidth(width * 0.125f);
+ ImGui.PushID("Animation");
+ ImGui.InputInt("Lmt", ref inputLmt, 1);
+ ImGui.SameLine();
+ ImGui.InputInt("Animation Id", ref inputAnimationId, 1);
+ if (!(inputLmt >= 0 && inputAnimationId >= 0))
+ {
+ ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
+ }
+ bool doAnimation = ImGui.Button("Do");
+ if (!(inputLmt >= 0 && inputAnimationId >= 0))
+ {
+ ImGui.PopStyleVar();
+ ImGui.PopItemFlag();
+ }
+ ImGui.PopID();
+ ImGui.PushID("Action");
+ ImGui.InputInt("Set", ref inputSet, 1);
+ ImGui.SameLine();
+ ImGui.InputInt("Action Id", ref inputActionId, 1);
+ if (!(inputSet >= 0 && inputActionId >= 0))
+ {
+ ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
+ }
+ bool doAction = ImGui.Button("Do");
+ if (!(inputSet >= 0 && inputActionId >= 0))
+ {
+ ImGui.PopStyleVar();
+ ImGui.PopItemFlag();
+ }
+ ImGui.PopID();
+ if (ImGui.Button("Do Both"))
+ {
+ doAnimation = true;
+ doAction = true;
+ }
+ if (doAction)
+ {
+ MemoryUtil.WriteBytes(actionController.Instance + 0xC0, [(byte)inputActionId, 0x00, 0x00, 0x00]);
+ MemoryUtil.WriteBytes(actionController.Instance + 0xBC, [(byte)inputSet, 0x00, 0x00, 0x00]);
+ }
+ if (doAnimation)
+ {
+ animationLayer.DoAnimation(new AnimationId((uint)inputLmt, (uint)inputAnimationId));
+ }
+ ImGui.PopItemWidth();
+ }
+ }
+ }
+
+ private static void iterateList(nint baseAddr, Action<nint> func)
+ {
+ nint next = baseAddr;
+ nint head = next;
+ nint prev = MemoryUtil.Read<nint>(next + 0x10);
+ for (;next != 0x0;)
+ {
+ func(next + 0x40);
+ if (head == prev)
+ {
+ next = MemoryUtil.Read<nint>(next + 0x10);
+ }
+ else
+ {
+ next = MemoryUtil.Read<nint>(next + 0x18);
+ if (next == 0x0)
+ {
+ head = prev;
+ next = prev;
+ }
+ }
+ }
+ }
+
+ public static void DrawModelsList(float width, nint baseObject)
+ {
+ ImGui.PushID("Models");
+ ImGui.Checkbox("Only Toggle LOD 0", ref modelOnlyAddressLod0);
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text($"This can be used to check if a given model is showing LOD 0 or not.\nApplies when a part is toggled, meaning you should probably toggle all parts on before enabling this.");
+ ImGui.EndTooltip();
+ }
+ if (ImGui.CollapsingHeader("Loaded Models") && baseObject != 0x0)
+ {
+ ImGui.Text("Filter");
+ bool updateRegex = false;
+ bool invalidRegex = modelFilterIsRegex && modelFilter != "" && modelRegex == null;
+ if (invalidRegex)
+ {
+ ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0000FF);
+ }
+ ImGui.SetNextItemWidth(width * 0.55f);
+ if (ImGui.InputText("##Filter", ref modelFilter, 256))
+ {
+ if (modelFilterIsRegex)
+ {
+ updateRegex = true;
+ }
+ }
+ if (invalidRegex)
+ {
+ ImGui.PopStyleColor();
+ }
+ ImGui.SameLine();
+ if (ImGui.Button("Clear"))
+ {
+ modelFilter = "";
+ if (modelFilterIsRegex)
+ {
+ updateRegex = true;
+ }
+ }
+ ImGui.SameLine();
+ if (ImGui.Checkbox("Regex", ref modelFilterIsRegex))
+ {
+ if (modelFilterIsRegex)
+ {
+ updateRegex = true;
+ }
+ }
+ if (updateRegex)
+ {
+ if (String.IsNullOrEmpty(modelFilter))
+ {
+ modelRegex = null;
+ }
+ else
+ {
+ try
+ {
+ modelRegex = new Regex(modelFilter);
+ }
+ catch (ArgumentException)
+ {
+ modelRegex = null;
+ }
+ }
+ }
+ bool hideEverything = ImGui.Button("Hide Everything");
+ ImGui.SameLine();
+ bool showEverything = ImGui.Button("Show Everything");
+ nint bodyArmorParts = MemoryUtil.Read<nint>(baseObject + 0x2A0);
+ if (bodyArmorParts != 0x0)
+ {
+ iterateList(bodyArmorParts - 0x40, (partsAddr) =>
+ {
+ ImGui.PushID(partsAddr);
+ nint vTable = MemoryUtil.Read<nint>(partsAddr);
+ if (vTable == 0x143507A18)
+ {
+ string fullString = Marshal.PtrToStringAnsi(partsAddr + 0xC)!;
+ bool filterMatch = false;
+ if (modelFilterIsRegex)
+ {
+ filterMatch = modelRegex == null || modelRegex.Match(fullString).Success;
+ }
+ else
+ {
+ filterMatch = String.IsNullOrEmpty(modelFilter) || fullString.StartsWith(modelFilter);
+ }
+ if (filterMatch)
+ {
+ drawModelParts(0x0, partsAddr, hideEverything, showEverything);
+ }
+ }
+ ImGui.PopID();
+ });
+ }
+ }
+ ImGui.PopID();
+ }
+
+ private static void searchUnitList(nint addr, List<nint> objects)
+ {
+ nint baseAddr = MemoryUtil.Read<nint>(addr);
+ if (baseAddr == 0x0) return;
+ baseAddr = MemoryUtil.Read<nint>(baseAddr + 0xB8);
+ if (baseAddr == 0x0) return;
+ iterateList(baseAddr + 0x40, (objectAddr) =>
+ {
+ nint vTable = MemoryUtil.Read<nint>(objectAddr);
+ if (vTable == 0x14341F728 || vTable == 0x1434A9720) // Instanced Model || uScrMotionModel
+ {
+ objects.Add(objectAddr);
+ }
+ });
+ }
+
+ public static void DrawObjectList(float width, Player player)
+ {
+ List<nint> objects = new List<nint>();
+ unchecked
+ {
+ searchUnitList((nint)0x1450ECA20, objects);
+ searchUnitList((nint)0x1450EC980, objects);
+ }
+ /*
+ nint baseAddr = MemoryUtil.Read<nint>(0x14500DFC0);
+ baseAddr = MemoryUtil.Read<nint>(baseAddr + 0xA0 + 0x1490);
+ if (baseAddr == 0x0) return;
+ for (;;)
+ {
+ nint objectAddr = MemoryUtil.Read<nint>(baseAddr);
+ if (objectAddr == 0x0) break;
+ nint vTable = MemoryUtil.Read<nint>(objectAddr);
+ if (vTable == 0x1434A9720)
+ {
+ objects.Add(objectAddr);
+ }
+ baseAddr += 0x8;
+ }
+ */
+ ImGui.PushID("Objects");
+ ImGui.SetNextItemWidth(width * 0.55f);
+ if (ImGui.InputText("##Filter", ref objectFilter, 256))
+ {
+ }
+ ImGui.Checkbox("Sort By Distance To Player", ref sortObjectsByDistanceToPlayer);
+ IEnumerable<nint> enumerator = objects;
+ if (sortObjectsByDistanceToPlayer)
+ {
+ enumerator = Enumerable.OrderBy(objects, (x) => x, Comparer<nint>.Create((x, y) =>
+ {
+ Vector3 pos = player.Position;
+ Vector3 xPos = default, yPos = default;
+ nint vTableX = MemoryUtil.Read<nint>(x);
+ nint vTableY = MemoryUtil.Read<nint>(y);
+ if (vTableX == 0x1434A9720)
+ {
+ xPos = MemoryUtil.GetRef<Vector3>(x + 0x160);
+ }
+ else if (vTableX == 0x14341F728)
+ {
+ bool instanced = (MemoryUtil.GetRef<byte>(x + 0x2C8) & 0x10) != 0x10;
+ if (instanced)
+ {
+ xPos = MemoryUtil.GetRef<Vector3>(x + 0x500);
+ }
+ else
+ {
+ xPos = MemoryUtil.GetRef<Vector3>(x + 0x160);
+ }
+ }
+ if (vTableY == 0x1434A9720)
+ {
+ yPos = MemoryUtil.GetRef<Vector3>(y + 0x160);
+ }
+ else if (vTableY == 0x14341F728)
+ {
+ bool instanced = (MemoryUtil.GetRef<byte>(y + 0x2C8) & 0x10) != 0x10;
+ if (instanced)
+ {
+ yPos = MemoryUtil.GetRef<Vector3>(y + 0x500);
+ }
+ else
+ {
+ yPos = MemoryUtil.GetRef<Vector3>(y + 0x160);
+ }
+ }
+ float distX = Vector3.Distance(pos, xPos);
+ float distY = Vector3.Distance(pos, yPos);
+ if (distX < distY) return -1;
+ else if (distX > distY) return 1;
+ return 0;
+ }));
+ }
+ foreach (nint objectAddr in enumerator)
+ {
+ nint partsAddr = MemoryUtil.Read<nint>(objectAddr + 0x2A0);
+ string fullString = Marshal.PtrToStringAnsi(partsAddr + 0xC)!;
+ bool filterMatch = String.IsNullOrEmpty(objectFilter) || (!String.IsNullOrEmpty(fullString) && fullString.StartsWith(objectFilter));
+ if (!filterMatch)
+ {
+ continue;
+ }
+ ImGui.PushID(objectAddr);
+ if (ImGui.CollapsingHeader($"{fullString} @ 0x{objectAddr:X}"))
+ {
+ nint vTable = MemoryUtil.Read<nint>(objectAddr);
+ if (vTable == 0x1434A9720)
+ {
+ ImGui.DragFloat3("Position", ref MemoryUtil.GetRef<Vector3>(objectAddr + 0x160), 0.5f);
+ continue;
+ }
+ bool update = MemoryUtil.GetRef<byte>(objectAddr + 0x540) == 0x1;
+ if (ImGui.Checkbox("Update", ref update))
+ {
+ MemoryUtil.GetRef<byte>(objectAddr + 0x540) = ByteFlag(update);
+ }
+ ImGui.SameLine();
+ bool instanced = (MemoryUtil.GetRef<byte>(objectAddr + 0x2C8) & 0x10) == 0x10;
+ if (ImGui.Checkbox("Instanced", ref instanced))
+ {
+ if (instanced)
+ {
+ MemoryUtil.GetRef<byte>(objectAddr + 0x2C8) |= 0x10;
+ }
+ else
+ {
+ MemoryUtil.GetRef<byte>(objectAddr + 0x2C8) &= 0xF;
+ MemoryUtil.GetRef<Vector3>(objectAddr + 0x160) = MemoryUtil.GetRef<Vector3>(objectAddr + 0x500);
+ }
+ }
+ if (instanced)
+ {
+ ImGui.DragFloat3("Position", ref MemoryUtil.GetRef<Vector3>(objectAddr + 0x500), 0.5f);
+ int instanceCount = MemoryUtil.Read<int>(objectAddr + 0x4C0);
+ nint instances = MemoryUtil.Read<nint>(objectAddr + 0x4B8);
+ ImGui.Text($"Instances: {instanceCount} (0x{instances:X})");
+ for (int i = 0; i < instanceCount; i++)
+ {
+ ImGui.PushID(instances);
+ ref Vector3 position = ref MemoryUtil.GetRef<Vector3>(instances + 0xF0);
+ ref Vector4 rotation = ref MemoryUtil.GetRef<Vector4>(instances + 0x100);
+ ref Vector3 scale = ref MemoryUtil.GetRef<Vector3>(instances + 0x110);
+ ImGui.DragFloat3("Position", ref position, 0.5f);
+ ImGui.SliderFloat4("Rotation", ref rotation, -1.0f, 1.0f);
+ if (DrawRotate("Rotate", rotation, out Vector4 result))
+ {
+ rotation = result;
+ }
+ ImGui.DragFloat3("Scale", ref scale, 0.025f);
+ ImGui.Separator();
+ ImGui.PopID();
+ instances += 0x1D0;
+ }
+ }
+ else
+ {
+ ref Vector3 position = ref MemoryUtil.GetRef<Vector3>(objectAddr + 0x160);
+ ref Vector4 rotation = ref MemoryUtil.GetRef<Vector4>(objectAddr + 0x180);
+ ref Vector3 scale = ref MemoryUtil.GetRef<Vector3>(objectAddr + 0x170);
+ ImGui.DragFloat3("Position", ref position, 0.5f);
+ if (ImGui.Button("Move to Player"))
+ {
+ position = new Vector3(player.Position.X, player.Position.Y - 150.0f, player.Position.Z);
+ }
+ ImGui.SliderFloat4("Rotation", ref rotation, -1.0f, 1.0f);
+ if (DrawRotate("Rotate", rotation, out Vector4 result))
+ {
+ rotation = result;
+ }
+ ImGui.DragFloat3("Scale", ref scale, 0.025f);
+ }
+ }
+ ImGui.PopID();
+ }
+ ImGui.PopID();
+ }
+ }
+}
diff --git a/Player.cs b/Player.cs
index 85ba0a2..49c6fc8 100644
--- a/Player.cs
+++ b/Player.cs
@@ -17,9 +17,12 @@ namespace NewCamera
{
public static MtObject? sPlayer = null;
+ private static Player? lastPlayer = null;
+
private static int saveSlotIndex = -1;
private static NativeFunction<nint, nint> getSaveSlotGuiAddr;
private static NativeFunction<nint, nint> getPlayerSettingsAddr;
+
public static nint getPlayerSettings()
{
nint rcx = MemoryUtil.Read<nint>(0x145013950);
@@ -33,216 +36,198 @@ namespace NewCamera
// MonsterHunterWorld.exe+1B8DBB0 - movsxd rax,dword ptr [rcx+000000A0]
return getPlayerSettingsAddr.Invoke(rcx);
}
- private static bool hideWeapon = false;
- private static bool hideKnife = false;
-
- private delegate void CollisionCheckDelegate(nint unknownPtr, nint unknownPtr2);
- private static Hook<CollisionCheckDelegate>? collisionCheckHook;
- private static class Armor
+ public static Player? getPlayerFromSaveSlot()
{
- public const byte Body = 0;
- public const byte Helmet = 1;
- public const byte Arm = 2;
- public const byte Waist = 3;
- public const byte Leg = 4;
- public const byte Weapon = 5;
- public const byte Slinger = 6;
- public const byte Hair = 7;
- public const byte Face = 8;
- public const byte EyeLens = 9;
+ nint guiAddr = getSaveSlotGuiAddr.Invoke(MemoryUtil.Read<nint>(0x1451C42B8));
+ if (guiAddr == 0x0)
+ {
+ saveSlotIndex = -1;
+ return null;
+ }
+ int prevSaveSlotIndex = saveSlotIndex;
+ // MonsterHunterWorld.exe+ADC42F - movsxd rcx,dword ptr [rax+00000334]
+ saveSlotIndex = MemoryUtil.Read<int>(guiAddr + 0x334);
+ if (saveSlotIndex == -1)
+ {
+ return null;
+ }
+ // MonsterHunterWorld.exe+1B42047 - add r8,00000740
+ nint offset = (sPlayer!.Instance + 0x40) + (0x740 * saveSlotIndex);
+ nint playerAddr = 0x0;
+ if (offset != 0x0 && MemoryUtil.Read<nint>(offset) == 0x1433FE588 &&
+ ((playerAddr = MemoryUtil.Read<nint>(offset + 0x18)) != 0x0))
+ {
+ return new Player(playerAddr);
+ }
+ return null;
}
- private static class Joint
+ public static Player? getPlayer()
{
- public const byte Root = 0x0;
- public const byte Root2 = 0xD;
- public const byte LowerBack = 0x1;
- public const byte UpperBack = 0x2;
- public const byte LowerNeck = 0x3;
- public const byte LowerNeckNull = 0xFE;
- public const byte UpperNeck = 0x4;
- public const byte LeftCollarbone = 0x5;
- public const byte LeftShoulderNull = 0x46;
- public const byte LeftShoulder = 0x6;
- public const byte LeftElbow = 0x7;
- public const byte LeftWrist = 0x8;
- public const byte LeftWristNull = 0x1E;
- public const byte LeftThumbLow = 0x1F;
- public const byte LeftThumbMid = 0x20;
- public const byte LeftThumbHigh = 0x21;
- public const byte LeftIndexLow = 0x22;
- public const byte LeftIndexMid = 0x23;
- public const byte LeftIndexHigh = 0x24;
- public const byte LeftMiddleLow = 0x25;
- public const byte LeftMiddleMid = 0x26;
- public const byte LeftMiddleHigh = 0x27;
- public const byte LeftPalm = 0x28;
- public const byte LeftRingLow = 0x29;
- public const byte LeftRingMid = 0x2A;
- public const byte LeftRingHigh = 0x2B;
- public const byte LeftPinkyLow = 0x2C;
- public const byte LeftPinkyMid = 0x2D;
- public const byte LeftPinkyHigh = 0x2E;
- public const byte LeftArmUnk1 = 0x51;
- public const byte LeftArmUnk2 = 0x65;
- public const byte LeftArmUnk3 = 0x66;
- public const byte LeftArmUnk4 = 0x67;
- public const byte LeftArmUnk5 = 0x68;
- public const byte LeftArmUnk6 = 0x47;
- public const byte LeftArmUnk7 = 0x50;
- public const byte RightCollarbone = 0x9;
- public const byte RightShoulder = 0xA;
- public const byte RightElbow = 0xB;
- public const byte RightWrist = 0xC;
- public const byte RightWristNull = 0x2F;
- public const byte RightThumbLow = 0x30;
- public const byte RightThumbMid = 0x31;
- public const byte RightThumbHigh = 0x32;
- public const byte RightIndexLow = 0x33;
- public const byte RightIndexMid = 0x34;
- public const byte RightIndexHigh = 0x35;
- public const byte RightMiddleLow = 0x36;
- public const byte RightMiddleMid = 0x37;
- public const byte RightMiddleHigh = 0x38;
- public const byte RightPalm = 0x39;
- public const byte RightRingLow = 0x3A;
- public const byte RightRingMid = 0x3B;
- public const byte RightRingHigh = 0x3C;
- public const byte RightPinkyLow = 0x3D;
- public const byte RightPinkyMid = 0x3E;
- public const byte RightPinkyHigh = 0x3F;
- public const byte RightArmUnk1 = 0x53;
- public const byte RightArmUnk2 = 0x49;
- public const byte RightArmUnk3 = 0x52;
- public const byte RightArmUnk4 = 0x48;
- public const byte Unknown1 = 0xF7;
- public const byte Unknown2 = 0xF8;
- public const byte LeftHip = 0xE;
- public const byte LeftKnee = 0xF;
- public const byte LeftAnkle = 0x10;
- public const byte LeftToes = 0x11;
- public const byte LeftAnkleNull = 0x54;
- public const byte LeftKneeNull = 0x4B;
- public const byte LeftHipNull = 0x4A;
- public const byte Unknown3 = 0x40;
- public const byte Unknown4 = 0x42;
- public const byte RightHip = 0x12;
- public const byte RightKnee = 0x13;
- public const byte RightAnkle = 0x14;
- public const byte RightToes = 0x15;
- public const byte RightAnkleNull = 0x55;
- public const byte RightKneeNull = 0x4D;
- public const byte RightHipNull = 0x4C;
- public const byte Unknown5 = 0x43;
- public const byte Unknown6 = 0x45;
- public const byte Unknown7 = 0xF9;
- public const byte Unknown8 = 0xFA;
- public const byte Unknown9 = 0xFB;
- public const byte Unknown10 = 0xFC;
- public const byte Unknown11 = 0xFD;
+ Player? player = Player.MainPlayer;
+ if (player != lastPlayer)
+ {
+ Plugin.OnPlayerChange();
+ if (player != null)
+ {
+ saveSlotIndex = -1;
+ }
+ lastPlayer = player;
+ }
+ return player;
}
- private static nint[] playerArmor = new nint[10];
- private static nint[] playerJoints = new nint[0xFF];
- private static int lastArmorRefresh = -1;
-
- private delegate void UpdateJoints(nint obj);
- private static Hook<UpdateJoints>? updateJointRotationHook;
- private static Hook<UpdateJoints>? updateJointPositionHook;
- public static List<nint> bodyJoints = new List<nint>();
- private static List<nint> ignoredJoints = new List<nint>();
- private static Dictionary<nint, List<Vector3>> bodyRotations = new Dictionary<nint, List<Vector3>>();
- private static Dictionary<nint, List<Vector3>> bodyOffsets = new Dictionary<nint, List<Vector3>>();
-
- private static List<nint> faceJoints = new List<nint>();
- private static Dictionary<nint, List<Vector3>> faceRotations = new Dictionary<nint, List<Vector3>>();
- private static Dictionary<nint, List<Vector3>> faceOffsets = new Dictionary<nint, List<Vector3>>();
-
-#if QUARANTINED_FEATURES
- private delegate void UpdateIK(nint superOfChild, nint joint, nint obj);
- private static Hook<UpdateIK>? updateIKHook;
- private static Dictionary<nint, List<Vector3>> ikOffsets = new Dictionary<nint, List<Vector3>>();
- private static List<nint> ikJoints = new List<nint>();
-#endif
- private static bool ikForcedOff = false;
- private static Patch forceDisableIK;
-
- private static List<nint> jiggleBones = new List<nint>();
- private static bool attachToChest = false;
- public static bool toggleAttachToChest = false;
- private static bool swapChestSides = false;
- private static float chestMoveScale = 0.25f;
- private static bool setChestIndex = false;
- private static int chestBoneIndex1 = 0;
- private static int chestBoneIndex2 = 1;
- private static nint chestBone1 = 0x0;
- private static nint chestBone2 = 0x0;
-
- /*
- private delegate void ChangeEquipment(nint unknownPtr, int unknownInt);
- private Hook<ChangeEquipment>? changeEquipmentHook;
- private NativeFunction<nint, int, nint> newEquipmentPointer;
- private int lastEquipedId = 0;
- */
-
- private static bool disableCollision = false;
- private static bool disableExtraCollision = false;
- private static bool disableGravity = false;
- private static bool disableExtraGravity = false;
- private static Patch disableXCollision;
- private static Patch disableYCollision;
- private static Patch disableSecondaryYCollision;
- private static Patch disableZCollision;
- private static Patch disableExtraYCollision;
- private static Patch disableGravityYUpdate;
- private static Patch disableGravityXZUpdate;
- private static Patch disableGravityEval;
-
- private static void disableCollisionEnable()
+ public static Player? getLastPlayer()
{
- disableXCollision.Enable();
- disableYCollision.Enable();
- disableSecondaryYCollision.Enable();
- disableZCollision.Enable();
+ return lastPlayer;
}
- private static void disableCollisionDisable()
+ public static Player? getPlayerWithFallback()
{
- disableXCollision.Disable();
- disableYCollision.Disable();
- disableSecondaryYCollision.Disable();
- disableZCollision.Disable();
+ Player? player = getPlayer();
+ return player != null ? player : getPlayerFromSaveSlot();
}
- private static void disableExtraCollisionEnable()
- {
- disableExtraYCollision.Enable();
- }
+ private static bool hideWeapon = false;
+ private static NativeAction<nint, int> hideWeaponFunc;
+ private static bool hideKnife = false;
- private static void disableExtraCollisionDisable()
+ public static class Attach
{
- disableExtraYCollision.Disable();
- }
+ public static bool Enable = false;
+ public static bool Toggle = false;
+ public static bool SwapSides = false;
+ public static float Scale = 0.25f;
+ public static bool SetIndex = false;
+ public static int Index1 = 0;
+ public static int Index2 = 1;
+ public static nint Bone1 = 0x0;
+ public static nint Bone2 = 0x0;
- private static void disableGravityEnable()
- {
- disableGravityYUpdate.Enable();
- }
+ public static bool Available()
+ {
+ return Enable && Bone1 != 0x0 && Bone2 != 0x0;
+ }
- private static void disableGravityDisable()
- {
- disableGravityYUpdate.Disable();
- }
+ public static void DropState()
+ {
+ Bone1 = 0x0;
+ Bone2 = 0x0;
+ }
- private static void disableExtraGravityEnable()
- {
- disableGravityEval.Enable();
- }
+ public static void OnBone(nint jiggleData, int jiggleIndex, bool isBody)
+ {
+ if (SetIndex)
+ {
+ if (jiggleIndex == Index1)
+ {
+ Bone1 = jiggleData;
+ }
+ if (jiggleIndex == Index2)
+ {
+ Bone2 = jiggleData;
+ }
+ }
+ else if (isBody)
+ {
+ // Default to the last two jiggle bones on the body.
+ if (Bone1 == 0x0)
+ {
+ Bone1 = jiggleData;
+ Index1 = jiggleIndex;
+ }
+ else
+ {
+ if (Bone2 != 0x0)
+ {
+ Bone1 = Bone2;
+ Index1 = Index2;
+ }
+ Bone2 = jiggleData;
+ Index2 = jiggleIndex;
+ }
+ }
+ }
- private static void disableExtraGravityDisable()
- {
- disableGravityEval.Disable();
+ public static void Apply(Player player, float deltaTime, float PadRx, float PadRy, float PadLx, float PadLy)
+ {
+ Quaternion rotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W);
+ Vector3 up = Vector3.Transform(new Vector3(0.0f, 1.0f, 0.0f), rotation);
+ Vector3 right = Vector3.Transform(new Vector3(1.0f, 0.0f, 0.0f), rotation);
+ ref Vector3 jiggle1 = ref MemoryUtil.GetRef<Vector3>((SwapSides ? Bone2 : Bone1) + 0xD0);
+ ref Vector3 jiggle2 = ref MemoryUtil.GetRef<Vector3>((SwapSides ? Bone1 : Bone2) + 0xD0);
+ float scale = (Int16.MaxValue * deltaTime / Scale);
+ jiggle1 -= (right * (PadRx / scale)) + (up * (PadRy / scale));
+ jiggle2 -= (right * (PadLx / scale)) + (up * (PadLy / scale));
+ }
+
+ public static void Draw(float width)
+ {
+ if (ImGui.Checkbox("Attach to Chest", ref Enable))
+ {
+ if (!Enable)
+ {
+ Toggle = false;
+ }
+ }
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("While in Free Camera, hold LT + RT and move your joysticks (armor has to have jiggle physics).");
+ ImGui.EndTooltip();
+ }
+ if (!Enable)
+ {
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
+ }
+ ImGui.SameLine();
+ ImGui.Checkbox("Toggle", ref Toggle);
+ ImGui.SameLine();
+ ImGui.Checkbox("Swap Sides", ref SwapSides);
+ ImGui.SetNextItemWidth(width * 0.35f);
+ ImGui.DragFloat("Strength", ref Scale, 0.001f);
+ ImGui.Checkbox("Set Index", ref SetIndex);
+ ImGui.SameLine();
+ if (!SetIndex)
+ {
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
+ }
+ if (SetIndex && Bone1 == 0x0)
+ {
+ ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0000FF);
+ }
+ ImGui.SetNextItemWidth(width * 0.17f);
+ if (ImGui.InputInt("##Index 1", ref Index1, 1))
+ {
+ if (Index1 < 0) Index1 = 0;
+ }
+ if (SetIndex && Bone1 == 0x0)
+ {
+ ImGui.PopStyleColor();
+ }
+ ImGui.SameLine();
+ if (SetIndex && Bone2 == 0x0)
+ {
+ ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0000FF);
+ }
+ ImGui.SetNextItemWidth(width * 0.17f);
+ if (ImGui.InputInt("##Index 2", ref Index2, 1))
+ {
+ if (Index2 < 0) Index2 = 0;
+ }
+ if (SetIndex && Bone2 == 0x0)
+ {
+ ImGui.PopStyleColor();
+ }
+ if (!SetIndex)
+ {
+ ImGui.PopStyleVar();
+ }
+ if (!Enable)
+ {
+ ImGui.PopStyleVar();
+ }
+ }
}
private enum ZoneState : int
@@ -269,17 +254,19 @@ namespace NewCamera
private delegate void ZoneStateDelegate(nint player, int flags);
private static Hook<ZoneStateDelegate>? setZoneStateHook;
+ private static bool enableCrawl = false;
+ private static NativeAction<nint, nint> procEnvironmentCollision;
+ private static nint psuedoObject1;
+ private static nint psuedoObject2;
+ private delegate void CollisionCheckDelegate(nint unknownPtr, nint unknownPtr2);
+ private static Hook<CollisionCheckDelegate>? collisionCheckHook;
+
private static bool allowHotSpringsAnywhere = false;
private static Patch jmpOverHotSpringsEval;
private static bool disableHotSpringsSteam = false;
private static Patch jmpOverHotSpringsSteam;
- private static bool enableCrawl = false;
- private static NativeAction<nint, nint> procEnvironmentCollision;
- private static nint psuedoObject1;
- private static nint psuedoObject2;
-
private static float playerOpacityOverride = 1.0f;
private delegate void RefreshEntityParams(nint entity, nint unknownPtr2);
private static Hook<RefreshEntityParams>? refreshEntityParamsHook;
@@ -312,20 +299,98 @@ namespace NewCamera
MemoryUtil.GetRef<float>(wetnessAddr + 0x78) = wholeBodyWetness;
}
+ private static bool disableCollision = false;
+ private static bool disableExtraCollision = false;
+ private static bool disableGravity = false;
+ private static bool disableExtraGravity = false;
+ private static Patch disableXCollision;
+ private static Patch disableYCollision;
+ private static Patch disableSecondaryYCollision;
+ private static Patch disableZCollision;
+ private static Patch disableExtraYCollision;
+ private static Patch disableGravityYUpdate;
+ private static Patch disableGravityXZUpdate;
+ private static Patch disableGravityEval;
+
+ private static void disableCollisionEnable()
+ {
+ disableXCollision.Enable();
+ disableYCollision.Enable();
+ disableSecondaryYCollision.Enable();
+ disableZCollision.Enable();
+ }
+
+ private static void disableCollisionDisable()
+ {
+ disableXCollision.Disable();
+ disableYCollision.Disable();
+ disableSecondaryYCollision.Disable();
+ disableZCollision.Disable();
+ }
+
+ private static void disableExtraCollisionEnable()
+ {
+ disableExtraYCollision.Enable();
+ }
+
+ private static void disableExtraCollisionDisable()
+ {
+ disableExtraYCollision.Disable();
+ }
+
+ private static void disableGravityEnable()
+ {
+ disableGravityYUpdate.Enable();
+ }
+
+ private static void disableGravityDisable()
+ {
+ disableGravityYUpdate.Disable();
+ }
+
+ private static void disableExtraGravityEnable()
+ {
+ disableGravityEval.Enable();
+ }
+
+ private static void disableExtraGravityDisable()
+ {
+ disableGravityEval.Disable();
+ }
+
public static void Initialize()
{
+ getSaveSlotGuiAddr = new NativeFunction<nint, nint>(0x141AC0B60);
+ getPlayerSettingsAddr = new NativeFunction<nint, nint>(0x141B8DBB0);
- collisionCheckHook = Hook.Create<CollisionCheckDelegate>(0x1411C4E50, CollisionCheckHook); // nint, nint
+ /*
+ // MonsterHunterWorld.exe+1789ABA - mov rdi,[rcx+000076B0]
+ nint baseAddr = MemoryUtil.Read<nint>(player.Instance + 0x76B0);
+ if (baseAddr != 0x0)
+ {
+ MemoryUtil.WriteBytes(baseAddr + 0x1A98, [0x1]);
+ int weaponParts = MemoryUtil.Read<int>(baseAddr + 0x2250);
+ for (int i = 0; i < weaponParts; i++)
+ {
+ nint partsAddr = MemoryUtil.Read<nint>(baseAddr + ((i + 0x16B) * 24));
+ if (partsAddr != 0x0)
+ {
+ MemoryUtil.WriteBytes(partsAddr + 0x1A98, [0x1]);
+ }
+ }
+ }
+ */
+ hideWeaponFunc = new NativeAction<nint, int>(0x141789AB0);
#if QUARANTINED_FEATURES
// MonsterHunterWorld.exe+20354F7 - call MonsterHunterWorld.exe+1F73850
setZoneState = new NativeAction<nint, int>(0x142035020);
setPlayerController1 = new NativeAction<nint>(0x141F73850);
setPlayerController5 = new NativeAction<nint>(0x14118DDC0);
- zoneStateForcePassive1 = new Patch(lton(0x140256A3F) + 0x6, [0x1]);
- zoneStateForcePassive2 = new Patch(lton(0x141AC2865) + 0x6, [0x1]);
- zoneStateForceCombat1 = new Patch(lton(0x141AC2938) + 0x6, [0x0]);
- zoneStateForceCombat2 = new Patch(lton(0x141AC28EC) + 0x6, [0x0]);
+ zoneStateForcePassive1 = new Patch(0x140256A3F + 0x6, [0x1]);
+ zoneStateForcePassive2 = new Patch(0x141AC2865 + 0x6, [0x1]);
+ zoneStateForceCombat1 = new Patch(0x141AC2938 + 0x6, [0x0]);
+ zoneStateForceCombat2 = new Patch(0x141AC28EC + 0x6, [0x0]);
#endif
setZoneStateHook = Hook.Create<ZoneStateDelegate>(0x142035020, SetZoneStateHook); // nint, int
@@ -334,34 +399,17 @@ namespace NewCamera
MemoryUtil.WriteBytes(psuedoObject1 + 0x30, [0x03]);
psuedoObject2 = (nint)NativeMemory.AllocZeroed(0x7C);
MemoryUtil.WriteBytes(psuedoObject2 + 0x30, [0x08]);
-
- getSaveSlotGuiAddr = new NativeFunction<nint, nint>(0x141AC0B60);
- getPlayerSettingsAddr = new NativeFunction<nint, nint>(0x141B8DBB0);
-
- forceDisableIK = new Patch(lton(0x14031FD40), [0xC6, 0x81, 0x81, 0x01, 0x00, 0x00, 0x00, 0xC3]);
-
- // Alt: 0x141FBC7A0 (model - 0x958)
- updateJointRotationHook = Hook.Create<UpdateJoints>(0x14223BA30, UpdateJointRotationHook);
- updateJointPositionHook = Hook.Create<UpdateJoints>(0x142228F50, UpdateJointPositionHook);
-#if QUARANTINED_FEATURES
- updateIKHook = Hook.Create<UpdateIK>(0x142472C00, UpdateIKHook);
-#endif
-
- /*
- changeEquipmentHook = Hook.Create<ChangeEquipment>(0x141DDEF80, ChangeEquipmentHook); // nint, int
- newEquipmentPointer = new NativeFunction<nint, int, nint>(0x141DE56A0);
- */
+ collisionCheckHook = Hook.Create<CollisionCheckDelegate>(0x1411C4E50, CollisionCheckHook); // nint, nint
// Player + ECCC = How far underwater is the player.
- jmpOverHotSpringsEval = new Patch(lton(0x1417C1B03), [0xEB]);
- jmpOverHotSpringsSteam = new Patch(lton(0x14203A494), [0xE9, 0x8D, 0x00, 0x00, 0x00, 0x90]);
-
+ jmpOverHotSpringsEval = new Patch(0x1417C1B03, [0xEB]);
+ jmpOverHotSpringsSteam = new Patch(0x14203A494, [0xE9, 0x8D, 0x00, 0x00, 0x00, 0x90]);
refreshEntityParamsHook = Hook.Create<RefreshEntityParams>(0x141F605F0, RefreshEntityParamsHook); // nint, nint
- noopPlayerWetnessUpdate = new Patch(lton(0x14203E893), [0x90, 0x90, 0x90, 0x90, 0x90]);
- jmpOverChangeEquipmentWetnessUpdate_1 = new Patch(lton(0x14203E310), [0xEB]); // je -> jmp.
- jmpOverChangeEquipmentWetnessUpdate_2 = new Patch(lton(0x14203E397), [0xE9, 0xB9, 0x00, 0x00, 0x00, 0x90]); // je -> jmp.
+ noopPlayerWetnessUpdate = new Patch(0x14203E893, [0x90, 0x90, 0x90, 0x90, 0x90]);
+ jmpOverChangeEquipmentWetnessUpdate_1 = new Patch(0x14203E310, [0xEB]); // je -> jmp.
+ jmpOverChangeEquipmentWetnessUpdate_2 = new Patch(0x14203E397, [0xE9, 0xB9, 0x00, 0x00, 0x00, 0x90]); // je -> jmp.
// Noop collision checks.
nint 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"));
@@ -396,52 +444,9 @@ namespace NewCamera
disableGravityEval = new Patch(addr + 0x40, [0x90, 0x90, 0x90, 0x90, 0x90]); // call MonsterHunterWorld.exe+1325810.
}
- public static Player? getPlayerFromSaveSlot()
- {
- nint guiAddr = getSaveSlotGuiAddr.Invoke(MemoryUtil.Read<nint>(0x1451C42B8));
- if (guiAddr == 0x0)
- {
- saveSlotIndex = -1;
- return null;
- }
- // MonsterHunterWorld.exe+ADC42F - movsxd rcx,dword ptr [rax+00000334]
- saveSlotIndex = MemoryUtil.Read<int>(guiAddr + 0x334);
- if (saveSlotIndex == -1)
- {
- return null;
- }
- // MonsterHunterWorld.exe+1B42047 - add r8,00000740
- nint offset = (sPlayer!.Instance + 0x40) + (0x740 * saveSlotIndex);
- if (offset == 0x0 || MemoryUtil.Read<nint>(offset) != 0x1433FE588)
- {
- return null;
- }
- nint playerAddr = MemoryUtil.Read<nint>(offset + 0x18);
- if (playerAddr == 0x0)
- {
- return null;
- }
- return new Player(playerAddr);
- }
-
- public static Player? getPlayer()
- {
- Player? player = Player.MainPlayer;
- if (player != null)
- {
- saveSlotIndex = -1;
- }
- return Player.MainPlayer;
- }
-
- public static Player? getPlayerWithFallback()
+ public static void OnLoad()
{
- Player? player = getPlayer();
- if (player == null)
- {
- player = getPlayerFromSaveSlot();
- }
- return player;
+ sPlayer = SingletonManager.GetSingleton("sPlayer")!;
}
public static void OnUpdate()
@@ -451,22 +456,7 @@ namespace NewCamera
{
if (hideWeapon)
{
- // MonsterHunterWorld.exe+1789ABA - mov rdi,[rcx+000076B0]
- //new NativeAction<nint, int>(0x141789AB0).Invoke(player.Instance, 0);
- nint baseAddr = MemoryUtil.Read<nint>(player.Instance + 0x76B0);
- if (baseAddr != 0x0)
- {
- MemoryUtil.WriteBytes(baseAddr + 0x1A98, [0x1]);
- int weaponParts = MemoryUtil.Read<int>(baseAddr + 0x2250);
- for (int i = 0; i < weaponParts; i++)
- {
- nint partsAddr = MemoryUtil.Read<nint>(baseAddr + ((i + 0x16B) * 24));
- if (partsAddr != 0x0)
- {
- MemoryUtil.WriteBytes(partsAddr + 0x1A98, [0x1]);
- }
- }
- }
+ hideWeaponFunc.Invoke(player.Instance, 0);
}
if (hideKnife)
{
@@ -480,33 +470,6 @@ namespace NewCamera
}
}
- private static void CollisionCheckHook(nint unknownPtr, nint unknownPtr2)
- {
- debugLog($"CollisionCheckHook(0x{unknownPtr:X}, 0x{unknownPtr2:X}) @ {updateTick}");
-
- Player? player = null;
- if (enableCrawl && (player = getPlayer()) != null)
- {
- nint controlsAddr = MemoryUtil.Read<nint>(player.Instance + 0x12608);
- bool combatControls = false;
- if (controlsAddr != 0x0)
- {
- combatControls = MemoryUtil.Read<byte>(controlsAddr + 0xB18) == 0x80;
- }
- if (combatControls)
- {
- procEnvironmentCollision.Invoke(player.Instance, psuedoObject1);
- procEnvironmentCollision.Invoke(player.Instance, psuedoObject2);
- }
- else
- {
- enableCrawl = false;
- }
- }
-
- collisionCheckHook!.Original(unknownPtr, unknownPtr2);
- }
-
private static void SetZoneStateHook(nint player, int flags)
{
debugLog($"SetZoneStateHook(0x{player:X}, 0x{flags:X}) @ {updateTick}");
@@ -551,1128 +514,43 @@ namespace NewCamera
}
}
- private static void RefreshEntityParamsHook(nint entity, nint unknownPtr2)
- {
- debugLog($"RefreshEntityParamsHook(0x{entity:X}, 0x{unknownPtr2:X}) @ {updateTick}");
-
- refreshEntityParamsHook!.Original(entity, unknownPtr2);
-
- Player? player = getPlayerWithFallback();
- if (player != null && entity == player && playerOpacityOverride != 1.0f)
- {
- MemoryUtil.GetRef<float>(player.Instance + 0x78E0) = playerOpacityOverride;
- }
- }
-
- private static string extractPartName(string fullString)
- {
- string partName = "";
- if (fullString.StartsWith("pl\\f_equip") || fullString.StartsWith("pl\\m_equip"))
- {
- partName = fullString.Split('\\')[3];
- }
- else if (fullString.StartsWith("wp\\"))
- {
- partName = fullString.Split('\\')[2];
- }
- else if (fullString.StartsWith("pl\\hair"))
- {
- partName = fullString.Split('\\')[2];
- }
- else if (fullString.StartsWith("pl\\f_face") || fullString.StartsWith("pl\\m_face"))
- {
- partName = fullString.Split('\\')[4].Substring(2);
- }
- return partName;
- }
-
- private static void collectArmorParts(nint baseAddr, nint addr)
- {
- int part;
- string fullString = Marshal.PtrToStringAnsi(addr + 0xC)!;
- string partName = extractPartName(fullString);
- if (partName == "body") part = Armor.Body;
- else if (partName == "helm") part = Armor.Helmet;
- else if (partName == "arm") part = Armor.Arm;
- else if (partName == "wst") part = Armor.Waist;
- else if (partName == "leg") part = Armor.Leg;
- else if (partName.StartsWith("slg")) part = Armor.Slinger;
- else if (fullString.StartsWith("wp\\")) part = Armor.Weapon;
- else if (partName.StartsWith("hair")) part = Armor.Hair;
- else if (partName == "face000") part = Armor.Face;
- else if (partName == "face000_eyelens") part = Armor.EyeLens;
- else return;
- playerArmor[part] = baseAddr;
-
- int jointCount = MemoryUtil.Read<int>(baseAddr + 0x4A0);
- nint jointAddr = MemoryUtil.Read<nint>(baseAddr + 0x4A8);
- for (int i = 0; i < jointCount; i++)
- {
- nint childAddr = MemoryUtil.Read<nint>(jointAddr + 0x8);
- if (childAddr != 0x0 && MemoryUtil.Read<nint>(childAddr) == 0x142F21A90)
- {
- childAddr = MemoryUtil.Read<nint>(childAddr + 0x8);
- if (childAddr != 0x0)
- {
- nint childVtable = MemoryUtil.Read<nint>(childAddr);
- if (childVtable == 0x1435195B8) // Jiggle Bone Container.
- {
- if (part == Armor.Body)
- {
- ignoredJoints.Add(jointAddr);
- }
- }
- else if (childVtable == 0x143524BD8)
- {
- childAddr = MemoryUtil.Read<nint>(childAddr + 0x188);
- if (childAddr != 0x0 && MemoryUtil.Read<nint>(childAddr) == 0x143519530)
- {
- nint jiggleData = MemoryUtil.Read<nint>(MemoryUtil.Read<nint>(childAddr + 0xA0));
- if (MemoryUtil.Read<nint>(jiggleData) == 0x143519508)
- {
- if (!jiggleBones.Contains(jiggleData))
- {
- int jiggleIndex = jiggleBones.Count();
- jiggleBones.Add(jiggleData);
- if (setChestIndex)
- {
- if (jiggleIndex == chestBoneIndex1)
- {
- chestBone1 = jiggleData;
- }
- if (jiggleIndex == chestBoneIndex2)
- {
- chestBone2 = jiggleData;
- }
- }
- else if (part == Armor.Body)
- {
- // Guess that chest bones are the last jiggle bones on the body.
- if (chestBone1 == 0x0)
- {
- chestBone1 = jiggleData;
- chestBoneIndex1 = jiggleIndex;
- }
- else
- {
- if (chestBone2 != 0x0)
- {
- chestBone1 = chestBone2;
- chestBoneIndex1 = chestBoneIndex2;
- }
- chestBone2 = jiggleData;
- chestBoneIndex2 = jiggleIndex;
- }
- }
- }
- }
- }
- if (part == Armor.Body)
- {
- ignoredJoints.Add(jointAddr);
- }
- }
-#if QUARANTINED_FEATURES
- else if (childVtable == 0x143249170)
- {
- childAddr = MemoryUtil.Read<nint>(childAddr + 0x188);
- if (childAddr != 0x0 && MemoryUtil.Read<nint>(childAddr) == 0x1432492F0)
- {
- ikJoints.Add(jointAddr);
- }
- }
-#endif
- }
- }
- if (part == Armor.Body)
- {
- bodyJoints.Add(jointAddr);
- }
- else if (part == Armor.Face)
- {
- faceJoints.Add(jointAddr);
- }
- jointAddr += 0xC0;
- }
-
- if (part == Armor.Body)
- {
- for (int i = 0; i < bodyJoints.Count; i++)
- {
- jointAddr = bodyJoints[i];
- if (ignoredJoints.Contains(jointAddr))
- {
- continue;
- }
- byte id = MemoryUtil.Read<byte>(jointAddr + 0xA0);
- Assert(playerJoints[id] == 0x0);
- playerJoints[id] = jointAddr;
- }
- foreach (nint joint in bodyRotations.Where(e => !bodyJoints.Contains(e.Key)).Select(e => e.Key).ToList())
- {
- 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())
- {
- ikOffsets.Remove(joint);
- }
-#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 static void drawJoint(nint jointAddr, Dictionary<nint, List<Vector3>> rotations, Dictionary<nint, List<Vector3>> offsets)
- {
- if (jointAddr == 0x0) return;
- ImGui.PushID(jointAddr);
- bool hasRotation = rotations.ContainsKey(jointAddr);
- bool hasOffset = offsets.ContainsKey(jointAddr);
-#if QUARANTINED_FEATURES
- bool hasIkOffset = ikOffsets.ContainsKey(jointAddr);
-#endif
- ImGui.DragFloat4("Rotation", ref MemoryUtil.GetRef<Vector4>(jointAddr + 0x70), 0.005f);
- if (hasRotation)
- {
- ImGui.PushID("Rotation");
- bool doRemove = ImGui.Button("X");
- ImGui.SameLine();
- if (ImGui.Button("Reset"))
- {
- rotations[jointAddr][0] = default;
- }
- ImGui.SameLine();
- Vector3 v = rotations[jointAddr][0];
- if (ImGui.DragFloat3($"##Rotation Offset", ref v, 0.005f))
- {
- rotations[jointAddr][0] = v;
- }
- if (doRemove) rotations.Remove(jointAddr);
- ImGui.PopID();
- }
- ImGui.DragFloat4("Position", ref MemoryUtil.GetRef<Vector4>(jointAddr + 0x50), 0.005f);
- if (hasOffset)
- {
- 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();
- }
-#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"))
- {
- rotations.Add(jointAddr, new List<Vector3>()
- {
- new Vector3()
- });
- }
- }
- if (!hasOffset)
- {
- if (!hasRotation)
- {
- ImGui.SameLine();
- }
- if (ImGui.Button("Add Offset"))
- {
- offsets.Add(jointAddr, new List<Vector3>()
- {
- new Vector3()
- });
- }
- }
-#if QUARANTINED_FEATURES
- if (ikJoints.Contains(jointAddr) && !hasIkOffset)
- {
- if (!hasOffset)
- {
- ImGui.SameLine();
- }
- if (ImGui.Button("Add IK Offset"))
- {
- ikOffsets.Add(jointAddr, new List<Vector3>()
- {
- new Vector3()
- });
- }
- }
-#endif
- ImGui.PopID();
- }
-
- private static void drawJoint(nint jointAddr)
- {
- drawJoint(jointAddr, bodyRotations, bodyOffsets);
- }
-
- private static 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];
- byte id = MemoryUtil.Read<byte>(jointAddr + 0xA0);
- ImGui.PushID(jointAddr);
- if (ImGui.CollapsingHeader($"Joint #{i} (0x{jointAddr:X}, id: 0x{id:X})"))
- {
- drawJoint(jointAddr, rotations, offsets);
- }
- ImGui.PopID();
- drawJointLeaf(ref joints, i + 1, rotations, offsets);
- }
-
- private static void drawJoints(float width)
- {
- ImGui.PushItemWidth(width * 0.75f);
- ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.Framed;
- bool expanded;
- if (ImGui.TreeNodeEx("Root", flags))
- {
- drawJoint(playerJoints[Joint.Root2]);
- ImGui.TreePop();
- }
- ImGui.PushID("Neck");
- if (ImGui.TreeNodeEx("Neck", flags))
- {
- if (ImGui.TreeNodeEx("Upper", flags))
- {
- drawJoint(playerJoints[Joint.UpperNeck]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Lower", flags))
- {
- drawJoint(playerJoints[Joint.LowerNeck]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID(); // Neck.
- ImGui.PushID("Back");
- if (ImGui.TreeNodeEx("Back", flags))
- {
- if (ImGui.TreeNodeEx("Upper", flags))
- {
- drawJoint(playerJoints[Joint.UpperBack]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Lower", flags))
- {
- drawJoint(playerJoints[Joint.LowerBack]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID(); // Back.
- ImGui.PushID("Right Arm");
- if (ImGui.TreeNodeEx("Right Arm", flags))
- {
- if (ImGui.TreeNodeEx("Collarbone", flags))
- {
- drawJoint(playerJoints[Joint.RightCollarbone]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Shoulder", flags))
- {
- drawJoint(playerJoints[Joint.RightShoulder]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Elbow", flags))
- {
- drawJoint(playerJoints[Joint.RightElbow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Wrist", flags))
- {
- drawJoint(playerJoints[Joint.RightWrist]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID(); // Right Arm.
- ImGui.PushID("Right Hand");
- if (ImGui.TreeNodeEx("Right Hand", flags))
- {
- ImGui.PushID("Thumb");
- if (ImGui.TreeNodeEx("Thumb", flags))
- {
- if (ImGui.TreeNodeEx("Base", flags))
- {
- drawJoint(playerJoints[Joint.RightThumbLow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- drawJoint(playerJoints[Joint.RightThumbMid]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Tip", flags))
- {
- drawJoint(playerJoints[Joint.RightThumbHigh]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID();
- ImGui.PushID("Index");
- if (ImGui.TreeNodeEx("Index", flags))
- {
- if (ImGui.TreeNodeEx("Base", flags))
- {
- drawJoint(playerJoints[Joint.RightIndexLow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- drawJoint(playerJoints[Joint.RightIndexMid]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Tip", flags))
- {
- drawJoint(playerJoints[Joint.RightIndexHigh]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID();
- ImGui.PushID("Middle");
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- if (ImGui.TreeNodeEx("Base", flags))
- {
- drawJoint(playerJoints[Joint.RightMiddleLow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- drawJoint(playerJoints[Joint.RightMiddleMid]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Tip", flags))
- {
- drawJoint(playerJoints[Joint.RightMiddleHigh]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID();
- ImGui.PushID("Ring");
- if (ImGui.TreeNodeEx("Ring", flags))
- {
- if (ImGui.TreeNodeEx("Base", flags))
- {
- drawJoint(playerJoints[Joint.RightRingLow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- drawJoint(playerJoints[Joint.RightRingMid]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Tip", flags))
- {
- drawJoint(playerJoints[Joint.RightRingHigh]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID();
- ImGui.PushID("Pinky");
- if (ImGui.TreeNodeEx("Pinky", flags))
- {
- if (ImGui.TreeNodeEx("Base", flags))
- {
- drawJoint(playerJoints[Joint.RightPinkyLow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- drawJoint(playerJoints[Joint.RightPinkyMid]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Tip", flags))
- {
- drawJoint(playerJoints[Joint.RightPinkyHigh]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID();
- expanded = ImGui.TreeNodeEx("Palm", flags);
- if (ImGui.BeginItemTooltip())
- {
- ImGui.Text("Outer Palm/Pinky+Ring");
- ImGui.EndTooltip();
- }
- if (expanded)
- {
- drawJoint(playerJoints[Joint.RightPalm]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID(); // Right Hand.
- ImGui.PushID("Right Leg");
- if (ImGui.TreeNodeEx("Right Leg", flags))
- {
- if (ImGui.TreeNodeEx("Hip", flags))
- {
- drawJoint(playerJoints[Joint.RightHip]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Knee", flags))
- {
- drawJoint(playerJoints[Joint.RightKnee]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Ankle", flags))
- {
- drawJoint(playerJoints[Joint.RightAnkle]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Toes", flags))
- {
- drawJoint(playerJoints[Joint.RightToes]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID(); // Right Leg.
- ImGui.PushID("Left Arm");
- if (ImGui.TreeNodeEx("Left Arm", flags))
- {
- if (ImGui.TreeNodeEx("Collarbone", flags))
- {
- drawJoint(playerJoints[Joint.LeftCollarbone]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Shoulder", flags))
- {
- drawJoint(playerJoints[Joint.LeftShoulder]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Elbow", flags))
- {
- drawJoint(playerJoints[Joint.LeftElbow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Wrist", flags))
- {
- drawJoint(playerJoints[Joint.LeftWrist]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID(); // Left Arm.
- ImGui.PushID("Left Hand");
- if (ImGui.TreeNodeEx("Left Hand", flags))
- {
- ImGui.PushID("Thumb");
- if (ImGui.TreeNodeEx("Thumb", flags))
- {
- if (ImGui.TreeNodeEx("Base", flags))
- {
- drawJoint(playerJoints[Joint.LeftThumbLow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- drawJoint(playerJoints[Joint.LeftThumbMid]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Tip", flags))
- {
- drawJoint(playerJoints[Joint.LeftThumbHigh]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID();
- ImGui.PushID("Index");
- if (ImGui.TreeNodeEx("Index", flags))
- {
- if (ImGui.TreeNodeEx("Base", flags))
- {
- drawJoint(playerJoints[Joint.LeftIndexLow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- drawJoint(playerJoints[Joint.LeftIndexMid]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Tip", flags))
- {
- drawJoint(playerJoints[Joint.LeftIndexHigh]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID();
- ImGui.PushID("Middle");
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- if (ImGui.TreeNodeEx("Base", flags))
- {
- drawJoint(playerJoints[Joint.LeftMiddleLow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- drawJoint(playerJoints[Joint.LeftMiddleMid]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Tip", flags))
- {
- drawJoint(playerJoints[Joint.LeftMiddleHigh]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID();
- ImGui.PushID("Ring");
- if (ImGui.TreeNodeEx("Ring", flags))
- {
- if (ImGui.TreeNodeEx("Base", flags))
- {
- drawJoint(playerJoints[Joint.LeftRingLow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- drawJoint(playerJoints[Joint.LeftRingMid]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Tip", flags))
- {
- drawJoint(playerJoints[Joint.LeftRingHigh]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID();
- ImGui.PushID("Pinky");
- if (ImGui.TreeNodeEx("Pinky", flags))
- {
- if (ImGui.TreeNodeEx("Base", flags))
- {
- drawJoint(playerJoints[Joint.LeftPinkyLow]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Middle", flags))
- {
- drawJoint(playerJoints[Joint.LeftPinkyMid]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Tip", flags))
- {
- drawJoint(playerJoints[Joint.LeftPinkyHigh]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID();
- expanded = ImGui.TreeNodeEx("Palm", flags);
- if (ImGui.BeginItemTooltip())
- {
- ImGui.Text("Outer Palm/Pinky+Ring");
- ImGui.EndTooltip();
- }
- if (expanded)
- {
- drawJoint(playerJoints[Joint.LeftPalm]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID(); // Left Hand.
- ImGui.PushID("Left Leg");
- if (ImGui.TreeNodeEx("Left Leg", flags))
- {
- if (ImGui.TreeNodeEx("Hip", flags))
- {
- drawJoint(playerJoints[Joint.LeftHip]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Knee", flags))
- {
- drawJoint(playerJoints[Joint.LeftKnee]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Ankle", flags))
- {
- drawJoint(playerJoints[Joint.LeftAnkle]);
- ImGui.TreePop();
- }
- if (ImGui.TreeNodeEx("Toes", flags))
- {
- drawJoint(playerJoints[Joint.LeftToes]);
- ImGui.TreePop();
- }
- ImGui.TreePop();
- }
- ImGui.PopID(); // Left Leg.
- ImGui.Separator();
- if (ImGui.Checkbox("Attach to Chest", ref attachToChest))
- {
- if (!attachToChest)
- {
- toggleAttachToChest = false;
- }
- }
- if (ImGui.BeginItemTooltip())
- {
- ImGui.Text("While in Free Camera, hold LT + RT and move your joysticks (armor has to have jiggle physics).");
- ImGui.EndTooltip();
- }
- if (!attachToChest)
- {
- ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
- }
- ImGui.SameLine();
- ImGui.Checkbox("Toggle", ref toggleAttachToChest);
- ImGui.SameLine();
- ImGui.Checkbox("Swap Sides", ref swapChestSides);
- ImGui.SetNextItemWidth(width * 0.35f);
- ImGui.DragFloat("Strength", ref chestMoveScale, 0.001f);
- ImGui.Checkbox("Set Index", ref setChestIndex);
- ImGui.SameLine();
- if (!setChestIndex)
- {
- ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
- }
- if (setChestIndex && chestBone1 == 0x0)
- {
- ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0000FF);
- }
- ImGui.SetNextItemWidth(width * 0.17f);
- if (ImGui.InputInt("##Index 1", ref chestBoneIndex1, 1))
- {
- if (chestBoneIndex1 < 0) chestBoneIndex1 = 0;
- }
- if (setChestIndex && chestBone1 == 0x0)
- {
- ImGui.PopStyleColor();
- }
- ImGui.SameLine();
- if (setChestIndex && chestBone2 == 0x0)
- {
- ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0000FF);
- }
- ImGui.SetNextItemWidth(width * 0.17f);
- if (ImGui.InputInt("##Index 2", ref chestBoneIndex2, 1))
- {
- if (chestBoneIndex2 < 0) chestBoneIndex2 = 0;
- }
- if (setChestIndex && chestBone2 == 0x0)
- {
- ImGui.PopStyleColor();
- }
- if (!setChestIndex)
- {
- ImGui.PopStyleVar();
- }
- if (!attachToChest)
- {
- ImGui.PopStyleVar();
- }
- if (ImGui.CollapsingHeader("Jiggle Bones"))
- {
- for (int i = 0; i < jiggleBones.Count; i++)
- {
- nint jiggleData = jiggleBones[i];
- ImGui.PushID(jiggleData);
- if (ImGui.CollapsingHeader($"Jiggle Bone #{i} (0x{jiggleData:X})"))
- {
- ImGui.DragFloat3("Position", ref MemoryUtil.GetRef<Vector3>(jiggleData + 0xD0), 0.05f);
- if (ImGui.BeginItemTooltip())
- {
- ImGui.Text("Drag this position around to influence the bone.");
- ImGui.EndTooltip();
- }
- }
- ImGui.PopID();
- }
- }
- ImGui.Separator();
- if (ImGui.CollapsingHeader("Body Joints"))
- {
- drawJointLeaf(ref bodyJoints, 0, bodyRotations, bodyOffsets);
- }
- if (ImGui.CollapsingHeader("Face Joints"))
- {
- drawJointLeaf(ref faceJoints, 0, faceRotations, faceOffsets);
- }
- ImGui.PopItemWidth();
- }
-
- public static void drawModelParts(nint armorAddr, nint partsAddr = 0x0)
- {
- if (partsAddr == 0x0)
- {
- if (armorAddr == 0x0 || (partsAddr = MemoryUtil.Read<nint>(armorAddr + 0x2A0)) == 0x0)
- {
- return;
- }
- }
- ImGui.PushID(partsAddr);
- string fullString = Marshal.PtrToStringAnsi(partsAddr + 0xC)!;
- if (armorAddr != 0x0)
- {
- string partName = extractPartName(fullString);
- ImGui.Text($"{partName} (0x{armorAddr:X}, {fullString} @ 0x{partsAddr:X}):");
- }
- else
- {
- ImGui.Text($"{fullString} @ 0x{partsAddr:X}:");
- }
- // MonsterHunterWorld.exe+222E651 - mov rax,[r8+000000C8]
- nint baseLod = MemoryUtil.Read<nint>(partsAddr + 0xC8);
- nint baseOffset = MemoryUtil.Read<nint>(partsAddr + 0x408 + (0x8 * 0x1));
- int numParts = MemoryUtil.Read<int>(partsAddr + 0x548 + (0x4 * 0x1));
- // Setting lodCount to 0 is probably the best way to completely hide a model.
- int lodCount = MemoryUtil.Read<int>(partsAddr + 0xD0);
- const int lodStructSize = 0x50;
- const int partsPerLine = 10;
- bool allOn = ImGui.Button("Show All");
- ImGui.SameLine();
- bool allOff = ImGui.Button("Hide All");
- for (int i = 0; i < numParts; i++)
- {
- ref int lodOffset = ref MemoryUtil.GetRef<int>(baseOffset + (i * 0x4));
- nint lod0 = baseLod + lodOffset * lodStructSize;
- bool isVisible = MemoryUtil.GetRef<ushort>(lod0) != 0;
- bool togglePart = ImGui.Checkbox($"##Part #{i}", ref isVisible);
- if (ImGui.BeginItemTooltip())
- {
- ImGui.Text($"Part #{i} (0x{lod0:X})");
- ImGui.EndTooltip();
- }
- int lastLod = (i < numParts - 1) ? MemoryUtil.Read<int>(baseOffset + ((i + 1) * 0x4)) : lodCount;
- int partLodCount = lastLod - lodOffset;
- // This is not a "proper" way to hide a part. It abuses the fact that if the lower
- // 16 bits (lodVisible) of these 4 bytes are 0, a check to skip rendering it will
- // always pass. Also that +0xA appears to be unused/padding.
- // MonsterHunterWorld.exe+222FCE3 - mov eax,[r8]
- ushort lod0Visible = MemoryUtil.GetRef<ushort>(lod0);
- for (int j = 0; j < partLodCount; j++)
- {
- if (togglePart || (lod0Visible != 0 && allOff) || (lod0Visible == 0 && allOn))
- {
- nint lod = lod0 + (j * lodStructSize);
- ref ushort lodVisible = ref MemoryUtil.GetRef<ushort>(lod);
- ref ushort padSub = ref MemoryUtil.GetRef<ushort>(lod + 0xA);
- if (lod0Visible != 0) Assert(padSub == 0);
- // Check against LOD0 to prevent an inconsistent state.
- if ((lodVisible != 0) == (lod0Visible != 0))
- {
- (lodVisible, padSub) = (padSub, lodVisible);
- }
- }
- if (modelOnlyAddressLod0) break;
- }
- if (i != numParts - 1 && i % partsPerLine != partsPerLine - 1)
- {
- ImGui.SameLine();
- }
- }
- ImGui.PopID();
- }
-
- private static void dropArmorState()
- {
- Array.Clear(playerArmor, 0, playerArmor.Length);
- Array.Clear(playerJoints, 0, playerJoints.Length);
- bodyJoints.Clear();
- ignoredJoints.Clear();
- faceJoints.Clear();
-#if QUARANTINED_FEATURES
- ikJoints.Clear();
-#endif
- jiggleBones.Clear();
- chestBone1 = 0x0;
- chestBone2 = 0x0;
- }
-
- private static void dropJointOffsets()
- {
- bodyRotations.Clear();
- bodyOffsets.Clear();
- faceRotations.Clear();
- faceOffsets.Clear();
-#if QUARANTINED_FEATURES
- ikOffsets.Clear();
-#endif
- }
-
- private static bool collectArmorAndJoints(Player player)
- {
- nint bodyArmorParts = MemoryUtil.Read<nint>(player.Instance + 0x2A0);
- if (bodyArmorParts == 0x0)
- {
- return false;
- }
- // MonsterHunterWorld.exe+203E8A2 - mov rax,[rbx+000126C8]
- nint combineArmorList = MemoryUtil.Read<nint>(player.Instance + 0x126C8);
- if (combineArmorList == 0x0)
- {
- return false;
- }
- collectArmorParts(player.Instance, bodyArmorParts);
- nint weapon = MemoryUtil.Read<nint>(player.Instance + 0x76B0);
- if (weapon != 0x0)
- {
- nint weaponParts = MemoryUtil.Read<nint>(weapon + 0x2A0);
- if (weaponParts != 0x0)
- {
- collectArmorParts(weapon, weaponParts);
- }
- }
- nint slinger = MemoryUtil.Read<nint>(player.Instance + 0x8918);
- if (slinger != 0x0)
- {
- nint slingerParts = MemoryUtil.Read<nint>(slinger + 0x2A0);
- if (slingerParts != 0x0)
- {
- collectArmorParts(slinger, slingerParts);
- }
- }
- combineArmorList = MemoryUtil.Read<nint>(combineArmorList + 0x70);
- nint next = combineArmorList;
- while (next != 0x0)
- {
- nint armorAddr = next;
- next = MemoryUtil.Read<nint>(armorAddr + 0x30);
- nint vTable = MemoryUtil.Read<nint>(armorAddr);
- // uWeaponParts: 0x1434D2400, uWeaponEmblem: 0x1434D1D58
- if (vTable == 0x1434A7560) // uPlCombineArmor
- {
- nint partsAddr = 0x0;
- nint childAddr = MemoryUtil.Read<nint>(armorAddr + 0x548);
- if (childAddr != 0x0)
- {
- if (MemoryUtil.Read<nint>(childAddr) == 0x143451520) // Face.
- {
- nint ownerAddr = MemoryUtil.Read<nint>(childAddr + 0x998);
- if (ownerAddr != player.Instance)
- {
- continue;
- }
- if (playerArmor[Armor.Face] == 0x0)
- {
- partsAddr = MemoryUtil.Read<nint>(childAddr + 0x2A0);
- if (partsAddr != 0x0)
- {
- collectArmorParts(childAddr, partsAddr);
- }
- childAddr = MemoryUtil.Read<nint>(childAddr + 0x9C8);
- if (childAddr != 0x0 && MemoryUtil.Read<nint>(childAddr) == 0x143505E98) // Eye lens.
- {
- partsAddr = MemoryUtil.Read<nint>(childAddr + 0x2A0);
- if (partsAddr != 0x0)
- {
- collectArmorParts(childAddr, partsAddr);
- }
- }
- }
- }
- else if (childAddr != player.Instance)
- {
- continue;
- }
- }
- partsAddr = MemoryUtil.Read<nint>(armorAddr + 0x2A0);
- if (partsAddr != 0x0)
- {
- collectArmorParts(armorAddr, partsAddr);
- }
- }
- if (!playerArmor.Where(p => (p == 0x0)).Any())
- {
- break;
- }
- }
- return true;
- }
-
- private static void refreshArmorState(Player player)
- {
- dropArmorState();
- if (!collectArmorAndJoints(player))
- {
- dropJointOffsets();
- }
- lastArmorRefresh = updateTick;
- }
-
- private static void UpdateJointRotationHook(nint model)
+ private static void CollisionCheckHook(nint unknownPtr, nint unknownPtr2)
{
- debugLog($"UpdateJointRotationHook(0x{model:X}) @ {updateTick}");
+ debugLog($"CollisionCheckHook(0x{unknownPtr:X}, 0x{unknownPtr2:X}) @ {updateTick}");
Player? player = null;
- bool updateBody = bodyRotations.Count() > 0 || (enableFreeCamera && orbitPlayer && orbitJoint >= 0);
- if (updateBody || faceRotations.Count() > 0)
- {
- player = getPlayerWithFallback();
- }
-
- if (updateBody)
+ if (enableCrawl && (player = getPlayer()) != null)
{
- if (player != null && model == player.Instance)
+ nint controlsAddr = MemoryUtil.Read<nint>(player.Instance + 0x12608);
+ bool combatControls = controlsAddr != 0x0 && MemoryUtil.Read<byte>(controlsAddr + 0xB18) == 0x80;
+ if (combatControls)
{
- refreshArmorState(player);
- foreach ((nint addr, List<Vector3> rotations) in bodyRotations)
- {
- MemoryUtil.GetRef<Quaternion>(addr + 0x70) *= Quaternion.CreateFromYawPitchRoll(rotations[0].X, rotations[0].Y, rotations[0].Z);
- }
- /*
- if (playerArmor[Armor.Waist] != 0x0)
- {
- MemoryUtil.GetRef<byte>(playerArmor[Armor.Waist] + 0x2D0) = hideKnife ? (byte)0xFD : (byte)0xFF;
- checkKnifeHidden = false;
- }
- */
+ procEnvironmentCollision.Invoke(player.Instance, psuedoObject1);
+ procEnvironmentCollision.Invoke(player.Instance, psuedoObject2);
}
- }
-
- if (faceRotations.Count() > 0)
- {
- if (player != null && model == playerArmor[Armor.Face])
+ else
{
- if (!updateBody)
- {
- refreshArmorState(player);
- }
- else
- {
- Assert(lastArmorRefresh == updateTick);
- }
- foreach ((nint addr, List<Vector3> rotations) in faceRotations)
- {
- MemoryUtil.GetRef<Quaternion>(addr + 0x70) *= Quaternion.CreateFromYawPitchRoll(rotations[0].X, rotations[0].Y, rotations[0].Z);
- }
-
+ enableCrawl = false;
}
}
- updateJointRotationHook!.Original(model);
+ collisionCheckHook!.Original(unknownPtr, unknownPtr2);
}
- private static void UpdateJointPositionHook(nint model)
+ private static void RefreshEntityParamsHook(nint entity, nint unknownPtr2)
{
- debugLog($"UpdateJointPositionHook(0x{model:X}) @ {updateTick}");
+ debugLog($"RefreshEntityParamsHook(0x{entity:X}, 0x{unknownPtr2:X}) @ {updateTick}");
- updateJointPositionHook!.Original(model);
+ refreshEntityParamsHook!.Original(entity, unknownPtr2);
Player? player = null;
- bool updateBody = bodyOffsets.Count() > 0;
- if (updateBody || faceOffsets.Count() > 0)
+ if (playerOpacityOverride != 1.0f && (player = getPlayerWithFallback()) != null && entity == player)
{
- player = getPlayerWithFallback();
- }
-
- if (updateBody)
- {
- if (player != null && model == player.Instance)
- {
- refreshArmorState(player);
- foreach ((nint addr, List<Vector3> offsets) in bodyOffsets)
- {
- MemoryUtil.GetRef<Vector3>(addr + 0x50) += offsets[0];
- }
- }
- }
-
- if (faceOffsets.Count() > 0)
- {
- if (player != null && model == playerArmor[Armor.Face])
- {
- if (!updateBody)
- {
- refreshArmorState(player);
- }
- else
- {
- Assert(lastArmorRefresh == updateTick);
- }
- foreach ((nint addr, List<Vector3> offsets) in faceOffsets)
- {
- MemoryUtil.GetRef<Vector3>(addr + 0x50) += offsets[0];
- }
- }
- }
- }
-
-#if QUARANTINED_FEATURES
- private static void UpdateIKHook(nint superOfChild, nint joint, nint obj)
- {
- if (ikOffsets.ContainsKey(joint))
- {
- Vector3 offset = ikOffsets[joint][0];
- MemoryUtil.GetRef<Vector3>(superOfChild + 0x1380) += offset;
+ MemoryUtil.GetRef<float>(player.Instance + 0x78E0) = playerOpacityOverride;
}
- updateIKHook!.Original(superOfChild, joint, obj);
}
-#endif
- /*
- private void ChangeEquipmentHook(nint unknownPtr, int unknownInt)
- {
- 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);
- }
- */
-
- public static void drawPlayerInfo(Player player, float width)
+ public static void DrawPlayerInfo(Player player, float width)
{
nint playerSettings = getPlayerSettings();
@@ -1681,6 +559,7 @@ namespace NewCamera
ImGui.Checkbox("Hide Weapon", ref hideWeapon);
ImGui.SameLine();
ImGui.Checkbox("Hide Knife", ref hideKnife);
+
ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f));
ImGui.Text("Head Armor Display");
// MonsterHunterWorld.exe+11A2967 - cmp byte ptr [rax+001403E1],01
@@ -1707,152 +586,16 @@ namespace NewCamera
ImGui.Separator();
- bool armorStateRefreshed = false;
-
- ImGui.PushID("Joints");
- if (ImGui.CollapsingHeader("Joints"))
- {
- if (!armorStateRefreshed)
- {
- refreshArmorState(player);
- armorStateRefreshed = true;
- }
- ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f));
-#if QUARANTINED_FEATURES
- 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}, Joint Offsets: {bodyOffsets.Count + faceOffsets.Count}");
-#endif
- ImGui.SameLine();
- ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f));
- if (ImGui.Button("Clear"))
- {
- dropJointOffsets();
- }
- ImGui.SameLine();
- /*
- ref byte ikDisabledB = ref MemoryUtil.GetRef<byte>(MemoryUtil.Read<nint>(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();
- */
- ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f));
- if (ImGui.Checkbox("Disable IK", ref ikForcedOff))
- {
- if (ikForcedOff)
- {
- forceDisableIK.Enable();
- }
- else
- {
- forceDisableIK.Disable();
- }
- }
- if (ImGui.BeginItemTooltip())
- {
- ImGui.Text("Forcefully disable inverse kinematics.");
- ImGui.EndTooltip();
- }
- drawJoints(width);
- ImGui.Separator();
- }
- ImGui.PopID();
-
- ImGui.PushID("Parts");
- if (ImGui.CollapsingHeader("Armor Parts"))
- {
- if (!armorStateRefreshed)
- {
- refreshArmorState(player);
- armorStateRefreshed = true;
- }
- bool expaned = ImGui.CollapsingHeader("Helmet");
- ImGui.SameLine();
- ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x1373C):X})");
- if (expaned)
- {
- drawModelParts(playerArmor[Armor.Helmet]);
- ImGui.Separator();
- }
- expaned = ImGui.CollapsingHeader("Body");
- ImGui.SameLine();
- ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x13740):X})");
- if (expaned)
- {
- drawModelParts(playerArmor[Armor.Body]);
- ImGui.Separator();
- }
- expaned = ImGui.CollapsingHeader("Arms");
- ImGui.SameLine();
- ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x13744):X})");
- if (expaned)
- {
- drawModelParts(playerArmor[Armor.Arm]);
- ImGui.Separator();
- }
- expaned = ImGui.CollapsingHeader("Waist");
- ImGui.SameLine();
- ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x13748):X})");
- if (expaned)
- {
- drawModelParts(playerArmor[Armor.Waist]);
- ImGui.Separator();
- }
- expaned = ImGui.CollapsingHeader("Legs");
- ImGui.SameLine();
- ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x1374C):X})");
- if (expaned)
- {
- drawModelParts(playerArmor[Armor.Leg]);
- ImGui.Separator();
- }
- /*
- expaned = ImGui.CollapsingHeader("Weapon");
- if (expaned)
- {
- drawModelParts(playerArmor[Armor.Weapon]);
- ImGui.Separator();
- }
- */
- expaned = ImGui.CollapsingHeader("Slinger");
- ImGui.SameLine();
- ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x13D8C):X}_{MemoryUtil.Read<int>(player.Instance + 0x13D90):X})");
- if (expaned)
- {
- drawModelParts(playerArmor[Armor.Slinger]);
- ImGui.Separator();
- }
- if (ImGui.CollapsingHeader("Hair"))
- {
- drawModelParts(playerArmor[Armor.Hair]);
- ImGui.Separator();
- }
- if (ImGui.CollapsingHeader("Face"))
- {
- drawModelParts(playerArmor[Armor.Face]);
- ImGui.Separator();
- }
- if (ImGui.CollapsingHeader("Eye Lens"))
- {
- drawModelParts(playerArmor[Armor.EyeLens]);
- }
- ImGui.Separator();
- }
- ImGui.PopID();
+ Poser.DrawUI(width, player);
nint controlsAddr = MemoryUtil.Read<nint>(player.Instance + 0x12608);
nint zoneStateAddr = MemoryUtil.Read<nint>(0x1451C42B8);
ZoneState zoneState = ZoneState.Unknown;
if (controlsAddr != 0x0 && zoneStateAddr != 0x0)
{
+#if !QUARANTINED_FEATURES
+ ImGui.Text($"Current Zone State: {((MemoryUtil.GetRef<byte>(zoneStateAddr + 0xD2EA) == 0x1) ? "Hub" : "Combat")}");
+#endif
ref byte passiveFlag = ref MemoryUtil.GetRef<byte>(player.Instance + 0x7626);
ref byte passiveFlag2 = ref MemoryUtil.GetRef<byte>(MemoryUtil.Read<nint>(player.Instance + 0x7D20) + 0x9B8);
bool passive = passiveFlag == 0x1 && passiveFlag2 == 0x1;
@@ -1868,9 +611,7 @@ namespace NewCamera
}
bool combatControls = MemoryUtil.Read<byte>(controlsAddr + 0xB18) == 0x80;
zoneState = combatControls ? ZoneState.Combat : ZoneState.Hub;
-#if !QUARANTINED_FEATURES
- ImGui.Text($"Current Zone State: {((MemoryUtil.GetRef<byte>(zoneStateAddr + 0xD2EA) == 0x1) ? "Hub" : "Combat")}");
-#else
+#if QUARANTINED_FEATURES
if (ImGui.Checkbox("Combat Controls", ref combatControls))
{
passiveFlag = ByteFlag(!combatControls);
@@ -2043,12 +784,20 @@ namespace NewCamera
ImGui.EndTooltip();
}
+ ImGui.PushID("Opacity");
ref float playerOpacity = ref MemoryUtil.GetRef<float>(player.Instance + 0x78E0);
- ImGui.SetNextItemWidth(width * 0.325f);
+ if (ImGui.Button("Reset"))
+ {
+ playerOpacity = 1.0f;
+ playerOpacityOverride = 1.0f;
+ }
+ ImGui.SameLine();
+ ImGui.SetNextItemWidth(width * 0.3f);
if (ImGui.DragFloat("Opacity", ref playerOpacity, 0.01f, 0.0f, Single.MaxValue))
{
playerOpacityOverride = playerOpacity;
}
+ ImGui.PopID();
ImGui.PushID("Wetness");
if (ImGui.CollapsingHeader("Wetness"))
@@ -2092,25 +841,25 @@ namespace NewCamera
}
ImGui.PopID();
+ ImGui.PushID("Position");
ImGui.PushItemWidth(width * 0.75f);
ImGui.DragFloat3("Position", ref player.Position, 0.5f);
Vector3 forward = new Vector3(player.Forward.X, player.Forward.Y, player.Forward.Z);
ImGui.DragFloat3("Forward", ref forward, 0.0f);
Vector4 rotation = new Vector4(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W);
ImGui.SliderFloat4("Rotation", ref rotation, -1.0f, 1.0f);
- Vector3 rotationOffset = new Vector3();
- if (ImGui.DragFloat3("Rotation Offset", ref rotationOffset, 0.0025f))
+ if (Models.DrawRotate("Rotate", rotation, out Vector4 result))
{
- Quaternion qRotation = new Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W);
- qRotation *= Quaternion.CreateFromYawPitchRoll(rotationOffset.X, rotationOffset.Y, rotationOffset.Z);
- player.Rotation = new MtQuaternion(qRotation.X, qRotation.Y, qRotation.Z, qRotation.W);
+ player.Rotation = new MtQuaternion(result.X, result.Y, result.Z, result.W);
}
ImGui.PopItemWidth();
- if (ImGui.Button("Reset"))
+ if (ImGui.Button("Upright"))
{
player.Rotation.X = 0.0f;
player.Rotation.Z = 0.0f;
}
+ ImGui.PopID();
+
if (ImGui.Checkbox("Disable Collision", ref disableCollision))
{
if (disableCollision)
@@ -2230,7 +979,8 @@ namespace NewCamera
ImGui.PopItemFlag();
ImGui.PopStyleVar();
}
- drawAnimationInfo(player, width, false);
+
+ Models.drawAnimationInfo(player, width, false);
}
}
}
diff --git a/Plugin.cs b/Plugin.cs
index d49ab19..3a022d4 100755
--- a/Plugin.cs
+++ b/Plugin.cs
@@ -1,12 +1,9 @@
//#define ENABLE_ASSERTS
//#define HOOK_ORDER_ASSERTS
//#define LOG_DEBUG_MESSAGES
-#define MOUSE_AND_KEYBOARD_LAYER
-//#define INTEROP_FEATURE
+#define INTEROP_FEATURE
using System.Numerics;
-using System.Runtime.InteropServices;
-using System.Text.RegularExpressions;
#if ENABLE_ASSERTS
using System.Diagnostics;
#endif
@@ -19,8 +16,8 @@ using SharpPluginLoader.Core.IO;
using SharpPluginLoader.Core.View;
using SharpPluginLoader.Core.Memory;
using SharpPluginLoader.Core.Actions;
-using SharpPluginLoader.Core.Components;
using SharpPluginLoader.Core.Configuration;
+using SharpPluginLoader.Core.Rendering;
// Tentative List of Actions:
// - Toggle Free Camera
@@ -169,7 +166,7 @@ namespace NewCamera
}
}
- public unsafe class Plugin : IPlugin
+ public class Plugin : IPlugin
{
public string Name => "New Camera";
public string Author => "Akon City Software";
@@ -184,8 +181,6 @@ namespace NewCamera
#endif
}
- public static nint lton(long l) { unchecked { return (nint)l; } }
-
public static byte ByteFlag(bool f) { return f ? (byte)0x1 : (byte)0x0; }
private static readonly MtObject sMain = SingletonManager.GetSingleton("sMhMain")!;
@@ -217,7 +212,7 @@ namespace NewCamera
private bool freeCamera = false;
private bool freeCameraFromViewMode = false;
private bool freeCameraFallback = false;
- private bool freeCameraNoMenu = false;
+ private bool freeCameraIgnoreMenu = false;
private Camera? vCamera = null;
private int vCameraViewportIndex = -1;
private float? restoreFov = null;
@@ -229,7 +224,7 @@ namespace NewCamera
private bool unlockMovementHeld = false;
private bool unlockMovementToggled = false;
private bool unlockMovementPause = false;
- private bool playerMovementLocked => !(unlockMovementHeld || unlockMovementToggled) || unlockMovementPause;
+ private bool playerMovementUnlocked => !unlockMovementPause && (unlockMovementHeld || unlockMovementToggled);
private bool lockVerticalToggled = false;
private NativeFunction<nint, int, int, nint> getViewParamOffset;
@@ -245,9 +240,8 @@ namespace NewCamera
private bool enableOffsetPerspective = false;
private bool offsetPerspective = false;
- private Player? lastPlayer = null;
- private Camera? pCamera = null;
- private int pCameraViewportIndex = -1;
+ private static Camera? pCamera = null;
+ private static int pCameraViewportIndex = -1;
private bool applyPerspective = false;
private float previousFov = -1.0f;
private int previousCameraAnimState = 0;
@@ -255,40 +249,24 @@ namespace NewCamera
private bool enableCombo = false;
private Button[]? freeCameraCombo = null;
- private bool disableComboButton1 = false;
+ private bool blockComboButton1 = false;
private bool comboButton1Down = false;
- private static readonly MtObject sMhController = SingletonManager.GetSingleton("sMhSteamController")!;
- private nint primaryPad = 0x0;
- private int PadLx, PadLy;
- private int PadRx, PadRy;
-
- private uint lastPadDown = 0u;
- private uint? prevPadDown = null;
private bool unlockInputToggled = false;
private bool unlockInputForMenu = false;
private bool unlockInputHideMenu = false;
- private bool buttonWasDown(Button button)
- {
- return (lastPadDown & (uint)button) == (uint)button;
- }
- private bool buttonWasPressed(Button button)
- {
- return (lastPadDown & (uint)button) == (uint)button && (prevPadDown & (uint)button) != (uint)button;
- }
- private bool buttonWasReleased(Button button)
- {
- return (lastPadDown & (uint)button) != (uint)button && (prevPadDown & (uint)button) == (uint)button;
- }
-#if MOUSE_AND_KEYBOARD_LAYER
+ private static readonly MtObject sMhController = SingletonManager.GetSingleton("sMhSteamController")!;
+ private int PadLx, PadLy;
+ private int PadRx, PadRy;
+
private static readonly MtObject sMhMouse = SingletonManager.GetSingleton("sMhMouse")!;
- private static readonly MtObject sMhKeyboard = SingletonManager.GetSingleton("sMhKeyboard")!;
private bool mouseEnabled = false;
private float mouseSensitivity;
+
+ private static readonly MtObject sMhKeyboard = SingletonManager.GetSingleton("sMhKeyboard")!;
private bool keyboardEnabled = false;
private int keyboardLookValue;
-#endif
private float plusRight = 0.0f;
private float plusForward = 0.0f;
@@ -296,11 +274,6 @@ namespace NewCamera
private bool sortMonsters = true;
private bool sortAnimals = true;
- private string modelFilter = "";
- private bool modelFilterIsRegex = false;
- private Regex? modelRegex = null;
- public static bool modelOnlyAddressLod0 = false;
-
private delegate void ProcessCameraDelegate(nint cameraPointer);
private Hook<ProcessCameraDelegate>? setCameraHook;
private Hook<ProcessCameraDelegate>? calculateCameraHook;
@@ -333,9 +306,6 @@ namespace NewCamera
private Hook<CalculateViewDelegate>? calculateViewHook;
*/
- private delegate void WritePadInputDelegate(nint unknownPtr, nint unknownPtr2, nint unknownPtr3);
- private Hook<WritePadInputDelegate>? writePadInputHook;
-
private delegate float CheckMovementDelegate(int stickValue, float alwaysZero);
private Hook<CheckMovementDelegate>? checkMovementHook;
@@ -414,13 +384,12 @@ namespace NewCamera
enableCombo = binds.EnableCombo;
freeCameraCombo = Config.ParseCombo(binds.FreeCameraCombo);
typedCombo = binds.FreeCameraCombo.Replace(",", "+");
- disableComboButton1 = binds.DisableComboButton1UnlessButton2Held;
-#if MOUSE_AND_KEYBOARD_LAYER
+ blockComboButton1 = binds.ComboButton1BlocksUnlessButton2Held;
+
mouseEnabled = binds.EnableMouse;
mouseSensitivity = binds.MouseSensitivity;
keyboardEnabled = binds.EnableKeyboard;
keyboardLookValue = binds.KeyboardLookSensitivity;
-#endif
Config.Settings camera = config.Camera;
cameraSpeed = camera.Speed;
@@ -435,7 +404,7 @@ namespace NewCamera
stickDeadzone = camera.StickDeadzone;
alternateNearClip = camera.AlternateNearClip;
- enableOffsetPerspective = config.PerspectiveCameraEnabled;
+ enableOffsetPerspective = config.CameraOffsetEnabled;
ConfigManager.SaveConfig<Config>(this);
@@ -450,6 +419,8 @@ namespace NewCamera
PlayerExt.Initialize();
+ Poser.Initialize();
+
getViewParamOffset = new NativeFunction<nint, int, int, nint>(0x14136E6C0);
// Asserts based on version 15.23.00.
@@ -524,10 +495,6 @@ namespace NewCamera
calculateViewHook = Hook.Create<CalculateViewDelegate>(addr, CalculateViewHook);
*/
- addr = PatternScanner.FindFirst(Pattern.FromString("48 89 5C 24 08 57 44 8B 9A 60 01 00 00 48 8B DA 41 0F BF 40 08 4D 8B D0 89 82 80 01 00 00 BF 00 10 00 00 41 0F BF 40 0A 89 82 84 01 00 00 41 0F BF 40 0C 89 82 78 01 00 00 41 0F BF 40 0E 89 82 7C 01 00 00"));
- Assert(addr == 0x1422A1280); // nint, nint, nint
- writePadInputHook = Hook.Create<WritePadInputDelegate>(addr, WritePadInputHook);
-
// Place where we can change the analog stick value the game uses for player movement.
addr = PatternScanner.FindFirst(Pattern.FromString("66 0F 6E C1 0F 5B C0 85 C9 78 11"));
Assert(addr == 0x142107CB0); // int, float
@@ -551,12 +518,12 @@ namespace NewCamera
noopCharacterFade.Enable();
}
- underwaterCamera1 = new Patch(lton(0x1412AD54D), [0x90, 0x90, 0x90, 0x90, 0x90, 0x90]); // Nop "Is diving" check.
- underwaterCamera2 = new Patch(lton(0x1412AD571), [0xB1, 0x01, 0x28, 0xC1, 0x90, 0x90, 0x90]); // Make cl the inverse of al.
- underwaterCamera3 = new Patch(lton(0x141FA5A7E), [0x90, 0x90]); // Nop check.
- underwaterCamera4 = new Patch(lton(0x141FA5BA0), [0x40, 0x84, 0xF6, 0x90, 0x74]); // jae -> je.
- underwaterCamera5 = new Patch(lton(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(lton(0x1424236DD), [0x0F, 0x57, 0xF6, 0x90, 0x90, 0x90, 0x90]);
+ underwaterCamera1 = new Patch(0x1412AD54D, [0x90, 0x90, 0x90, 0x90, 0x90, 0x90]); // Nop "Is diving" check.
+ underwaterCamera2 = new Patch(0x1412AD571, [0xB1, 0x01, 0x28, 0xC1, 0x90, 0x90, 0x90]); // Make cl the inverse of al.
+ underwaterCamera3 = new Patch(0x141FA5A7E, [0x90, 0x90]); // Nop check.
+ underwaterCamera4 = new Patch(0x141FA5BA0, [0x40, 0x84, 0xF6, 0x90, 0x74]); // jae -> je.
+ underwaterCamera5 = new Patch(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(0x1424236DD, [0x0F, 0x57, 0xF6, 0x90, 0x90, 0x90, 0x90]);
underwaterCheckHook = Hook.Create<UnderwaterCheck>(0x1412AD500, UnderwaterCheckHook); // nint
return data;
@@ -636,12 +603,15 @@ namespace NewCamera
public void OnLoad()
{
- PlayerExt.sPlayer = SingletonManager.GetSingleton("sPlayer")!;
+ PlayerExt.OnLoad();
+
Config config = loadConfig();
+
if (enableOffsetPerspective && config.Selected != "")
{
setPerspectivePreset(config.Presets[config.Selected]);
}
+
#if INTEROP_FEATURE
if (config.TuningToolInterop)
{
@@ -657,141 +627,28 @@ namespace NewCamera
#endif
}
- private void toggleUi()
- {
- uiToggled = !uiToggled;
- if (uiToggled)
- {
- jmpOverUi.Enable();
- }
- else
- {
- jmpOverUi.Disable();
- }
- if (unlockInputForMenu)
- {
- unlockInputHideMenu = uiToggled;
- }
- }
-
- private Player? checkPlayerChange()
- {
- Player? player = PlayerExt.getPlayer();
- if (player != lastPlayer)
- {
- pCamera = null;
- pCameraViewportIndex = -1;
- lastPlayer = player;
- }
- return player;
- }
-
- private int getVisibleCamera()
- {
- for (int i = 0; i < 8; i++)
- {
- Viewport vp = CameraSystem.GetViewport(i);
- // A viewport can be visible with a null camera.
- if (vp.Visible && vp.Camera != null)
- {
- return i;
- }
- }
- return -1;
- }
-
- private void checkCurrentVisibleCamera(Player? player)
- {
- int prevIndex = vCameraViewportIndex;
- vCameraViewportIndex = getVisibleCamera();
- if (vCameraViewportIndex >= 0)
- {
- Camera camera = CameraSystem.GetViewport(vCameraViewportIndex).Camera!;
- // Evaluate potential free camera target change.
- if (freeCamera)
- {
- if (vCamera != camera)
- {
- if (player != null)
- {
- // Try to position the camera behind the player.
- cameraPosition = player.Position;
- cameraPosition.X -= player.Forward.X * 250.0f;
- cameraPosition.Y += 200.0f;
- cameraPosition.Z -= player.Forward.Z * 250.0f;
- cameraTarget = player.Position;
- cameraTarget.Y += 150.0f;
- }
- else
- {
- cameraPosition = camera.Position;
- cameraTarget = camera.Target;
- }
- Quaternion forward = Quaternion.Normalize(getForward(cameraPosition, cameraTarget));
- cameraYaw = Single.RadiansToDegrees(MathF.Atan2(forward.Z, forward.X));
- cameraPitch = Single.RadiansToDegrees(MathF.Asin(forward.Y));
- }
- }
- vCamera = camera;
- // Assume that after a player is set the visible camera is the player camera.
- if (pCamera == null && player != null)
- {
- pCamera = vCamera;
- pCameraViewportIndex = vCameraViewportIndex;
- }
- }
- else
- {
- vCamera = null;
- pCamera = null;
- pCameraViewportIndex = -1;
- }
- }
-
- private void checkCameraAnimState()
- {
- if (pCamera != null)
- {
- previousCameraAnimState = MemoryUtil.Read<int>(pCamera.Instance + 0x240);
- if (previousCameraAnimState == 5)
- {
- ActionInfo currentActionInfo = lastPlayer!.ActionController.CurrentAction;
- // 1:314 = Wingdrake landing on area enter.
- // 1:319 = Disoriented wingdrake landing next to monster.
- if (currentActionInfo.ActionSet == 1 && (currentActionInfo.ActionId == 314 || currentActionInfo.ActionId == 319))
- {
- // Temporarily disable evaluation of cameraAnimState != 5.
- ignoreAnimState = true;
- }
- }
- else if (ignoreAnimState)
- {
- // Once cameraAnimState is no longer 5, resume default logic.
- ignoreAnimState = false;
- }
- }
- else
- {
- previousCameraAnimState = 0;
- }
- }
-
- private void resetStatePerFrame()
- {
- primaryPad = 0x0;
-
- // Zero pad input in case no controllers are connected.
- PadLx = 0; PadLy = 0;
- PadRx = 0; PadRy = 0;
-
- cameraOffset = Vector3.Zero;
- }
-
public void OnUpdate(float deltaTime)
{
if (updateTick == int.MaxValue) updateTick = 0;
else updateTick++;
+ /*
+ if (Input.IsDown(Mouse.Right)) Log.Info("Down");
+ if (Input.IsPressed(Mouse.Left)) Log.Info("Pressed");
+ if (Input.IsReleased(Mouse.Left)) Log.Info("Released");
+ if (Input.IsChanged(Mouse.Left)) Log.Info("Changed");
+
+ if (Input.IsDown(Button.Triangle)) Log.Info("Down");
+ if (Input.IsPressed(Button.Triangle)) Log.Info("Pressed");
+ if (Input.IsReleased(Button.Triangle)) Log.Info("Released");
+ if (Input.IsChanged(Button.Triangle)) Log.Info("Changed");
+
+ if (Input.IsDown(Key.H)) Log.Info("Down");
+ if (Input.IsPressed(Key.H)) Log.Info("Pressed");
+ if (Input.IsReleased(Key.H)) Log.Info("Released");
+ if (Input.IsChanged(Key.H)) Log.Info("Changed");
+ */
+
debugLog($"OnUpdate() @ {updateTick}");
#if HOOK_ORDER_ASSERTS
@@ -799,36 +656,10 @@ namespace NewCamera
hookOrder = 0;
#endif
-#if MOUSE_AND_KEYBOARD_LAYER
- if (keyboardEnabled)
- {
- if (Input.IsPressed(Key.NumPad0))
- {
- enableFreeCamera = !enableFreeCamera;
- }
- if (Input.IsPressed(Key.NumPadPeriod))
- {
- toggleUi();
- }
- if (Input.IsPressed(Key.NumPadSlash))
- {
- if (disableNearDofOverride != 0)
- {
- TuningToolInterop.RemoveOverride(disableNearDofOverride);
- disableNearDofOverride = 0;
- }
- else
- {
- disableNearDofOverride = TuningToolInterop.AddOverride("Dof Near Enable", new Vector4(), 0);
- }
- }
- }
-#endif
-
Player? player = null;
if (freeCameraFallback)
{
- player = checkPlayerChange();
+ player = PlayerExt.getPlayer();
checkCurrentVisibleCamera(player); // Ensure vCamera is valid.
if (vCamera != null)
{
@@ -854,7 +685,7 @@ namespace NewCamera
}
}
freeCameraFallback = true;
- freeCameraNoMenu = false;
+ freeCameraIgnoreMenu = false;
ref float gameSpeed = ref MemoryUtil.GetRef<float>(sMain.Instance + 0xA4);
if (freezeGame && gameSpeed != 0.0f)
@@ -868,8 +699,6 @@ namespace NewCamera
}
PlayerExt.OnUpdate();
-
- resetStatePerFrame();
}
private static Quaternion getForward(Vector3 pos, Vector3 target)
@@ -1044,37 +873,46 @@ namespace NewCamera
deltaTime = MemoryUtil.Read<float>(sMain.Instance + 0x94);
}
- bool lockVerticalAndModifySpeed = buttonWasDown(Button.L2) || lockVerticalToggled;
+ Player? player = PlayerExt.getLastPlayer();
+ if (player == null)
+ {
+ player = PlayerExt.getPlayerFromSaveSlot();
+ }
+
+ bool lockVerticalAndModifySpeed = (!Input.PadCaptured && Input.IsDown(Button.L2)) || lockVerticalToggled;
float adjustedSpeed = cameraSpeed * deltaTime * (lockVerticalAndModifySpeed ? cameraSpeedModifier : 1.0f);
bool lockCameraLook = false;
- if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0;
- if (Math.Abs(PadLx) < stickDeadzone) PadLx = 0;
- if (Math.Abs(PadRx) < stickDeadzone) PadRx = 0;
- if (Math.Abs(PadRy) < stickDeadzone) PadRy = 0;
-
cameraFrame = Vector3.Zero;
- Player? player = lastPlayer;
- if (player == null)
+ PadRx = 0; PadRy = 0;
+ PadLx = 0; PadLy = 0;
+
+ if (!Input.PadCaptured)
{
- player = PlayerExt.getPlayerFromSaveSlot();
+ if (Math.Abs(Input.GetPadRx()) >= stickDeadzone)
+ {
+ PadRx = Input.GetPadRx();
+ }
+ if (Math.Abs(Input.GetPadRy()) >= stickDeadzone)
+ {
+ PadRy = Input.GetPadRy();
+ }
+ if (Math.Abs(Input.GetPadLx()) >= stickDeadzone)
+ {
+ PadLx = Input.GetPadLx();
+ }
+ if (Math.Abs(Input.GetPadLy()) >= stickDeadzone)
+ {
+ PadLy = Input.GetPadLy();
+ }
}
- /*
- // PadLx/y is read in WritePadInputHook().
- if ((buttonWasDown(Button.L2) && buttonWasDown(Button.R2)) || toggleAttachToChest)
+ if ((!Input.PadCaptured && Input.IsDown(Button.L2) && Input.IsDown(Button.R2)) || PlayerExt.Attach.Toggle)
{
- if (player != null && attachToChest && chestBone1 != 0x0 && chestBone2 != 0x0)
+ if (player != null && PlayerExt.Attach.Available())
{
- Quaternion rotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W);
- Vector3 up = Vector3.Transform(new Vector3(0.0f, 1.0f, 0.0f), rotation);
- Vector3 right = Vector3.Transform(new Vector3(1.0f, 0.0f, 0.0f), rotation);
- ref Vector3 jiggle1 = ref MemoryUtil.GetRef<Vector3>((swapChestSides ? chestBone2 : chestBone1) + 0xD0);
- ref Vector3 jiggle2 = ref MemoryUtil.GetRef<Vector3>((swapChestSides ? chestBone1 : chestBone2) + 0xD0);
- float scale = (Int16.MaxValue / adjustedSpeed / chestMoveScale);
- jiggle1 -= (right * (PadRx / scale)) + (up * (PadRy / scale));
- jiggle2 -= (right * (PadLx / scale)) + (up * (PadLy / scale));
+ PlayerExt.Attach.Apply(player, deltaTime, PadRx, PadRy, PadLx, PadLy);
lockCameraLook = true;
}
else // Left stick zoom.
@@ -1083,24 +921,34 @@ namespace NewCamera
cameraFov = Math.Clamp(cameraFov - Ly, 1.0f, 179.0f);
}
}
- */
- if (playerMovementLocked || orbitPlayer) // Move camera.
+ else if (!playerMovementUnlocked || orbitPlayer) // Move camera.
{
-#if MOUSE_AND_KEYBOARD_LAYER
- if (keyboardEnabled)
+ if (keyboardEnabled && !Input.KeyboardCaptured)
{
- if (Input.IsDown(Key.Up)) PadLy += Int16.MaxValue;
- if (Input.IsDown(Key.Down)) PadLy -= Int16.MaxValue;
- if (Input.IsDown(Key.Left)) PadLx -= Int16.MaxValue;
- if (Input.IsDown(Key.Right)) PadLx += Int16.MaxValue;
+ if (Input.IsDown(Key.Up))
+ {
+ PadLy += Int16.MaxValue;
+ }
+ if (Input.IsDown(Key.Down))
+ {
+ PadLy -= Int16.MaxValue;
+ }
+ if (Input.IsDown(Key.Left))
+ {
+ PadLx -= Int16.MaxValue;
+ }
+ if (Input.IsDown(Key.Right))
+ {
+ PadLx += Int16.MaxValue;
+ }
}
-#endif
+
float Ly = PadLy / (Int16.MaxValue / adjustedSpeed);
float Lx = PadLx / (Int16.MaxValue / adjustedSpeed);
if (orbitPlayer)
{
- if (playerMovementLocked)
+ if (!playerMovementUnlocked)
{
if (lockVerticalAndModifySpeed)
{
@@ -1121,7 +969,14 @@ namespace NewCamera
}
else
{
- orbitMovementRotation += Lx / 5.0f;
+ if (PadLy < 0)
+ {
+ orbitMovementRotation -= Lx / 3.0f;
+ }
+ else
+ {
+ orbitMovementRotation += Lx / 3.0f;
+ }
}
if (orbitMovementRotation >= 180.0f)
{
@@ -1165,22 +1020,22 @@ namespace NewCamera
}
}
- if (!unlockInputToggled && !comboButton1Down)
+ if (!unlockInputToggled && !comboButton1Down && !Input.PadCaptured)
{
- if (buttonWasDown(Button.Share))
+ if (Input.IsDown(Button.Share))
{
- if (buttonWasPressed(Button.Square))
+ if (Input.IsPressed(Button.Square))
{
setNearClip(camera, !guessAltNearClipSet(camera));
}
}
- if (buttonWasDown(Button.R1))
+ if (Input.IsDown(Button.R1))
{
- if (buttonWasPressed(Button.Right))
+ if (Input.IsPressed(Button.Right))
{
cameraRoll = (restoreRoll != null) ? (float)restoreRoll : 0.0f;
}
- if (buttonWasPressed(Button.Up))
+ if (Input.IsPressed(Button.Up))
{
if (restoreFov != null)
{
@@ -1194,27 +1049,26 @@ namespace NewCamera
}
else if (!unlockInputForMenu || unlockInputHideMenu)
{
- if (buttonWasDown(Button.Up))
+ if (Input.IsDown(Button.Up))
{
cameraFrame.Y += adjustedSpeed / 2.0f;
}
- if (buttonWasDown(Button.Down))
+ if (Input.IsDown(Button.Down))
{
cameraFrame.Y -= adjustedSpeed / 2.0f;
}
- if (buttonWasDown(Button.Left))
+ if (Input.IsDown(Button.Left))
{
cameraRoll -= adjustedSpeed / 4.0f;
}
- if (buttonWasDown(Button.Right))
+ if (Input.IsDown(Button.Right))
{
cameraRoll += adjustedSpeed / 4.0f;
}
}
}
-#if MOUSE_AND_KEYBOARD_LAYER
- if (keyboardEnabled)
+ if (keyboardEnabled && !Input.KeyboardCaptured)
{
if (Input.IsDown(Key.NumPadMinus))
{
@@ -1255,30 +1109,35 @@ namespace NewCamera
{
cameraRoll -= adjustedSpeed / 4.0f;
}
+ if (Input.IsDown(Key.NumPad8))
+ {
+ PadRy += keyboardLookValue;
+ }
+ if (Input.IsDown(Key.NumPad2))
+ {
+ PadRy -= keyboardLookValue;
+ }
+ if (Input.IsDown(Key.NumPad4))
+ {
+ PadRx -= keyboardLookValue;
+ }
+ if (Input.IsDown(Key.NumPad6))
+ {
+ PadRx += keyboardLookValue;
+ }
}
-#endif
- // Camera look. PadRx/y is read in WritePadInputHook().
if (!lockCameraLook)
{
-#if MOUSE_AND_KEYBOARD_LAYER
- if (keyboardEnabled)
- {
- if (Input.IsDown(Key.NumPad8)) PadRy += keyboardLookValue;
- if (Input.IsDown(Key.NumPad2)) PadRy -= keyboardLookValue;
- if (Input.IsDown(Key.NumPad4)) PadRx -= keyboardLookValue;
- if (Input.IsDown(Key.NumPad6)) PadRx += keyboardLookValue;
- }
-#endif
float adjustedSensitivity = cameraSensitivity * deltaTime * cameraFov;
float Rx = PadRx / (Int16.MaxValue / adjustedSensitivity);
float Ry = PadRy / (Int16.MaxValue / adjustedSensitivity);
-#if MOUSE_AND_KEYBOARD_LAYER
- if (mouseEnabled && !playerInMenu())
+ if (mouseEnabled && !Input.MouseCaptured && !inMenu())
{
- Rx += MemoryUtil.GetRef<int>(sMhMouse.Instance + 0xFC) * mouseSensitivity;
- Ry -= MemoryUtil.GetRef<int>(sMhMouse.Instance + 0x100) * mouseSensitivity;
- ref int scrollY = ref MemoryUtil.GetRef<int>(sMhMouse.Instance + 0x17C);
+ // Update mouse _after_ factoring in deltaTime.
+ Rx += Input.GetMouseDeltaX() * mouseSensitivity;
+ Ry -= Input.GetMouseDeltaY() * mouseSensitivity;
+ int scrollY = Input.GetScrollDeltaY();
if (orbitPlayer)
{
orbitDistance -= scrollY * cameraZoomSpeed * 2.0f;
@@ -1292,7 +1151,6 @@ namespace NewCamera
cameraFov = Math.Clamp(cameraFov - scrollY * cameraZoomSpeed, 1.0f, 179.0f);
}
}
-#endif
cameraYaw += Rx;
if (plusRight != 0.0f && !orbitPlayer)
{
@@ -1355,10 +1213,10 @@ namespace NewCamera
{
Quaternion rotation;
Vector3 target;
- bool targetJoint = orbitJoint >= 0 && orbitJoint < PlayerExt.bodyJoints.Count;
+ bool targetJoint = orbitJoint >= 0 && orbitJoint < Poser.bodyJoints.Count;
if (targetJoint)
{
- nint jointAddr = PlayerExt.bodyJoints[orbitJoint];
+ nint jointAddr = Poser.bodyJoints[orbitJoint];
target = MemoryUtil.GetRef<Vector3>(jointAddr + 0x50);
rotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W);
rotation *= MemoryUtil.GetRef<Quaternion>(jointAddr + 0x70);
@@ -1418,6 +1276,102 @@ namespace NewCamera
camera.FieldOfView = cameraFov;
}
+ public static void OnPlayerChange()
+ {
+ pCamera = null;
+ pCameraViewportIndex = -1;
+ }
+
+ private int getVisibleCamera()
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ Viewport vp = CameraSystem.GetViewport(i);
+ // A viewport can be visible with a null camera.
+ if (vp.Visible && vp.Camera != null)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private void checkCurrentVisibleCamera(Player? player)
+ {
+ int prevIndex = vCameraViewportIndex;
+ vCameraViewportIndex = getVisibleCamera();
+ if (vCameraViewportIndex >= 0)
+ {
+ Camera camera = CameraSystem.GetViewport(vCameraViewportIndex).Camera!;
+ // Evaluate potential free camera target change.
+ if (freeCamera)
+ {
+ if (vCamera != camera)
+ {
+ if (player != null)
+ {
+ // Try to position the camera behind the player.
+ cameraPosition = player.Position;
+ cameraPosition.X -= player.Forward.X * 250.0f;
+ cameraPosition.Y += 200.0f;
+ cameraPosition.Z -= player.Forward.Z * 250.0f;
+ cameraTarget = player.Position;
+ cameraTarget.Y += 150.0f;
+ }
+ else
+ {
+ cameraPosition = camera.Position;
+ cameraTarget = camera.Target;
+ }
+ Quaternion forward = Quaternion.Normalize(getForward(cameraPosition, cameraTarget));
+ cameraYaw = Single.RadiansToDegrees(MathF.Atan2(forward.Z, forward.X));
+ cameraPitch = Single.RadiansToDegrees(MathF.Asin(forward.Y));
+ }
+ }
+ vCamera = camera;
+ // Assume that after a player is set the visible camera is the player camera.
+ if (pCamera == null && player != null)
+ {
+ pCamera = vCamera;
+ pCameraViewportIndex = vCameraViewportIndex;
+ }
+ }
+ else
+ {
+ vCamera = null;
+ pCamera = null;
+ pCameraViewportIndex = -1;
+ }
+ }
+
+ private void checkCameraAnimState()
+ {
+ if (pCamera != null)
+ {
+ previousCameraAnimState = MemoryUtil.Read<int>(pCamera.Instance + 0x240);
+ if (previousCameraAnimState == 5)
+ {
+ ActionInfo currentActionInfo = PlayerExt.getLastPlayer()!.ActionController.CurrentAction;
+ // 1:314 = Wingdrake landing on area enter.
+ // 1:319 = Disoriented wingdrake landing next to monster.
+ if (currentActionInfo.ActionSet == 1 && (currentActionInfo.ActionId == 314 || currentActionInfo.ActionId == 319))
+ {
+ // Temporarily disable evaluation of cameraAnimState != 5.
+ ignoreAnimState = true;
+ }
+ }
+ else if (ignoreAnimState)
+ {
+ // Once cameraAnimState is no longer 5, resume default logic.
+ ignoreAnimState = false;
+ }
+ }
+ else
+ {
+ previousCameraAnimState = 0;
+ }
+ }
+
private void SetCameraHook(nint cameraPointer)
{
debugLog($"SetCameraHook(0x{cameraPointer:X}) @ {updateTick}");
@@ -1427,7 +1381,7 @@ namespace NewCamera
hookOrder = 1;
#endif
- Player? player = checkPlayerChange();
+ Player? player = PlayerExt.getPlayer();
checkCurrentVisibleCamera(player);
checkCameraAnimState();
@@ -1552,11 +1506,8 @@ namespace NewCamera
if (vCamera != null && freeCamera)
{
updateFreeCamera(vCamera);
-
MemoryUtil.GetRef<Vector3>(psuedoViewModeObject + 0xE0) = cameraFrame;
-
processViewMode.Invoke(psuedoViewModeObject);
-
cameraPosition = MemoryUtil.GetRef<Vector3>(psuedoViewModeObject + 0x90);
}
*/
@@ -1576,11 +1527,15 @@ namespace NewCamera
enableFreeCamera = true;
freeCameraFromViewMode = true;
}
+ else
+ {
+ startViewModeHook!.Original(viewModeObject);
+ }
}
+ // The order of this hook between SetCameraHook() and CalculateCameraHook() is inconsistent.
private void SetCameraTentHook(nint unknownPtr)
{
- // The order of this hook between SetCameraHook() and CalculateCameraHook() is inconsistent.
debugLog($"SetCameraTentHook(0x{unknownPtr:X}) @ {updateTick}");
if (freeCamera && vCamera != null)
@@ -1599,6 +1554,7 @@ namespace NewCamera
}
freeCameraFallback = false;
+ freeCameraIgnoreMenu = true;
}
private void SetCameraCutsceneHook(nint unknownPtr)
@@ -1616,7 +1572,7 @@ namespace NewCamera
}
freeCameraFallback = false;
- freeCameraNoMenu = true;
+ freeCameraIgnoreMenu = true;
}
/*
@@ -1655,311 +1611,258 @@ namespace NewCamera
MemoryUtil.GetRef<float>(sMain.Instance + 0xA4) = freezeGame ? 0.0f : resumeSpeed;
}
- private bool playerInMenu()
+ private bool inMenu()
{
- // This doesn't align with in-game mouse controls. This can be observed when closing the pause
- // menu where there is a brief moment the camera moves -> freezes again -> then starts normally.
- return !freeCameraNoMenu && MemoryUtil.GetRef<byte>(Gui.SingletonInstance.Instance + 0x147A8) == 0x1;
+ return !freeCameraIgnoreMenu && MemoryUtil.GetRef<byte>(Gui.SingletonInstance.Instance + 0x147AC) > 0x3;
}
- // This can undoubtedly be simplified.
- private void WritePadInputHook(nint unknownPtr, nint unknownPtr2, nint unknownPtr3)
+ private void offsetSelectedPreset(int n)
{
- debugLog($"WritePadInputHook(0x{unknownPtr:X}, 0x{unknownPtr2:X}, 0x{unknownPtr3:X}) @ {updateTick}");
+ Config config = ConfigManager.GetConfig<Config>(this);
+ Dictionary<string, Config.Preset>.KeyCollection presetKeys = config.Presets.Keys;
+ if (presetKeys.Count > 0)
+ {
+ if (config.Selected != "")
+ {
+ int selectedIndex;
+ for (selectedIndex = 0; selectedIndex < presetKeys.Count; selectedIndex++)
+ {
+ string presetKey = presetKeys.ElementAt(selectedIndex);
+ if (presetKey == config.Selected)
+ {
+ break;
+ }
+ }
+ selectedIndex += n;
+ if (selectedIndex >= presetKeys.Count)
+ {
+ selectedIndex -= presetKeys.Count;
+ }
+ else if (selectedIndex < 0)
+ {
+ selectedIndex += presetKeys.Count;
+ }
+ config.Selected = presetKeys.ElementAt(selectedIndex);
+ }
+ else
+ {
+ config.Selected = presetKeys.ElementAt((n == 1) ? 0 : presetKeys.Count - 1);
+ }
+ setPerspectivePreset(config.Presets[config.Selected]);
+ ConfigManager.SaveConfig<Config>(this);
+ }
+ }
- // Assume the primary pad always comes first.
- if (primaryPad == 0x0) primaryPad = unknownPtr2;
- if (unknownPtr2 != primaryPad)
+ private void toggleUi()
+ {
+ uiToggled = !uiToggled;
+ if (uiToggled)
{
- writePadInputHook!.Original(unknownPtr, unknownPtr2, unknownPtr3);
- return;
+ jmpOverUi.Enable();
+ }
+ else
+ {
+ jmpOverUi.Disable();
+ }
+ if (unlockInputForMenu)
+ {
+ unlockInputHideMenu = uiToggled;
}
+ }
- Button b1 = 0u, b2 = 0u;
- uint b1u = 0u;
- if (enableCombo && freeCameraCombo != null)
+ public void toggleNearDof()
+ {
+ if (disableNearDofOverride != 0)
{
- b1 = freeCameraCombo[0];
- b2 = freeCameraCombo[1];
- b1u = (uint)b1;
- if (disableComboButton1 && comboButton1Down)
- {
- MemoryUtil.GetRef<uint>(sMhController.Instance + 0x198) |= b1u;
- }
+ TuningToolInterop.RemoveOverride(disableNearDofOverride);
+ disableNearDofOverride = 0;
+ }
+ else
+ {
+ disableNearDofOverride = TuningToolInterop.AddOverride("Dof Near Enable", new Vector4(), 0);
}
+ }
- writePadInputHook!.Original(unknownPtr, unknownPtr2, unknownPtr3);
+ private unsafe void openGestureMenu(bool poses)
+ {
+ // MonsterHunterWorld.exe+1ADA26A - mov rax,[rbx+00014018]
+ // Poses: MonsterHunterWorld.exe+1EC8000
+ // Gestures: MonsterHunterWorld.exe+1EC7D10
+ nint baseAddr = MemoryUtil.Read<nint>(0x1451C4640);
+ nint gesturesAddr = MemoryUtil.Read<nint>(baseAddr + 0x14018);
+ setupGestureMenu.Invoke(gesturesAddr, 0x0, poses ? 0x1 : 0x0); // Poses.
+ showGestureMenu.Invoke(gesturesAddr);
+ }
- uint PadDown = MemoryUtil.Read<uint>(sMhController.Instance + 0x198);
- uint PadRel = MemoryUtil.Read<uint>(sMhController.Instance + 0x1A4);
- prevPadDown = (prevPadDown == null) ? PadDown : lastPadDown;
- lastPadDown = PadDown;
+ private static bool bindsDisabled = false;
- PadLx = MemoryUtil.Read<int>(sMhController.Instance + 0x1B8);
- PadLy = MemoryUtil.Read<int>(sMhController.Instance + 0x1BC);
- PadRx = MemoryUtil.Read<int>(sMhController.Instance + 0x1B0);
- PadRy = MemoryUtil.Read<int>(sMhController.Instance + 0x1B4);
+ public void OnPadUpdate()
+ {
+ if (Input.PadCaptured) return;
+ Button b1 = 0u, b2 = 0u;
if (enableCombo && freeCameraCombo != null)
{
- if (disableComboButton1)
+ b1 = freeCameraCombo[0];
+ b2 = freeCameraCombo[1];
+ if (!bindsDisabled && (Input.IsDown(b1) || Input.IsReleased(b1)))
{
- if (comboButton1Down || enableFreeCamera || !buttonWasDown(b2))
+ if (Input.IsPressed(b2))
{
- if ((PadDown & b1u) == b1u)
- {
- comboButton1Down = true;
- }
- MemoryUtil.GetRef<uint>(sMhController.Instance + 0x198) &= ~b1u;
+ enableFreeCamera = !enableFreeCamera;
}
-
- if (comboButton1Down)
+ if (Input.IsPressed(Button.Share))
{
- if (((PadRel & b1u) == b1u))
- {
- comboButton1Down = false;
- }
- MemoryUtil.GetRef<uint>(sMhController.Instance + 0x1A0) &= ~b1u;
- MemoryUtil.GetRef<uint>(sMhController.Instance + 0x1A4) &= ~b1u;
- MemoryUtil.GetRef<uint>(sMhController.Instance + 0x1A8) &= ~b1u;
+ toggleUi();
+ }
+ if (Input.IsPressed(Button.R1))
+ {
+ Renderer.ToggleMenu();
+ }
+ if (Input.IsPressed(Button.L1))
+ {
+ unlockInputToggled = !unlockInputToggled;
+ }
+ int presetSelect = (Input.IsPressed(Button.Up) ? -1 : 0) + (Input.IsPressed(Button.Down) ? 1 : 0);
+ if (presetSelect != 0 && enableOffsetPerspective)
+ {
+ offsetSelectedPreset(presetSelect);
+ }
+ if (blockComboButton1)
+ {
+ Input.BlockPadButtons();
}
}
- }
-
- if ((comboButton1Down || (!disableComboButton1 && buttonWasDown(b1))))
- {
- if (buttonWasPressed(b2))
- {
- enableFreeCamera = !enableFreeCamera;
- }
- if (buttonWasPressed(Button.Share))
- {
- toggleUi();
- }
- if (buttonWasPressed(Button.L1))
- {
- unlockInputToggled = !unlockInputToggled;
- }
- int presetSelect = (buttonWasPressed(Button.Up) ? -1 : 0) + (buttonWasPressed(Button.Down) ? 1 : 0);
- if (presetSelect != 0)
+ else
{
- Config config = ConfigManager.GetConfig<Config>(this);
- Dictionary<string, Config.Preset>.KeyCollection presetKeys = config.Presets.Keys;
- if (presetKeys.Count > 0)
+ if (Input.IsPressed(b2))
{
- if (config.Selected != "")
- {
- int selectedIndex;
- for (selectedIndex = 0; selectedIndex < presetKeys.Count; selectedIndex++)
- {
- string presetKey = presetKeys.ElementAt(selectedIndex);
- if (presetKey == config.Selected)
- {
- break;
- }
- }
- selectedIndex += presetSelect;
- if (selectedIndex >= presetKeys.Count)
- {
- selectedIndex -= presetKeys.Count;
- }
- else if (selectedIndex < 0)
- {
- selectedIndex += presetKeys.Count;
- }
- config.Selected = presetKeys.ElementAt(selectedIndex);
- }
- else
- {
- config.Selected = presetKeys.ElementAt((presetSelect == 1) ? 0 : presetKeys.Count - 1);
- }
- setPerspectivePreset(config.Presets[config.Selected]);
- ConfigManager.SaveConfig<Config>(this);
+ bindsDisabled = true;
+ }
+ else if (Input.IsReleased(b2))
+ {
+ bindsDisabled = false;
}
}
}
- if (unlockMovementHeld && buttonWasReleased(Button.R2))
+ if (unlockMovementHeld && Input.IsReleased(Button.R2))
{
unlockMovementHeld = false;
unlockMovementPause = false;
}
- bool blockInput = comboButton1Down || (enableFreeCamera && !unlockInputToggled);
+ if (unlockInputForMenu && !inMenu())
+ {
+ unlockInputForMenu = false;
+ }
- if (blockInput)
+ if (enableFreeCamera)
{
- uint Mask = 0u;
- uint StartSelectMask = (uint)Button.Options | (uint)Button.Share;
- uint DPadMask = (uint)Button.Up | (uint)Button.Down | (uint)Button.Left | (uint)Button.Right;
- uint BumperMask = (uint)Button.L1 | (uint)Button.R1;
- uint StickMask = (uint)Button.LsUp | (uint)Button.LsDown | (uint)Button.LsLeft | (uint)Button.LsRight |
- (uint)Button.RsUp | (uint)Button.RsDown | (uint)Button.RsLeft | (uint)Button.RsRight;
- // @TODO: This is broken if you mix keyboard/mouse and controller input.
- if (unlockInputForMenu)
+ bool blockInput = !unlockInputToggled && (!unlockInputForMenu || unlockInputHideMenu);
+
+ if (blockInput)
{
- // Idealy we wouldn't block Y or X here but triggering Rearrange or Edit Shoutout in
- // the gesture menu can desync our primitive "still in menu" handling when B is pressed.
- uint FaceButtonMask = (uint)Button.Triangle | (uint)Button.Square;
- Mask = FaceButtonMask | StartSelectMask;
- if (unlockInputHideMenu)
- {
- Mask |= (uint)Button.Circle; // Still allow A/Cross.
- Mask |= DPadMask | BumperMask | StickMask;
- }
- else if (buttonWasReleased(Button.Circle))
- {
- unlockInputForMenu = false;
- unlockInputHideMenu = false;
- }
+ Input.BlockPadButtons();
+ Input.BlockPadRx();
+ Input.BlockPadRy();
+ Input.BlockPadRz();
+ Input.BlockPadLz();
}
- else
+
+ if (!playerMovementUnlocked || orbitIgnoreCamera)
{
- uint FaceButtonMask = (uint)Button.Cross | (uint)Button.Circle | (uint)Button.Square | (uint)Button.Triangle;
- Mask = FaceButtonMask | StartSelectMask | DPadMask | BumperMask | StickMask;
+ Input.BlockPadLx();
}
- if (enableCombo && freeCameraCombo != null)
+
+ if (!playerMovementUnlocked)
{
- Mask &= ~(b1u | (uint)b2);
+ Input.BlockPadLy();
}
- MemoryUtil.GetRef<uint>(sMhController.Instance + 0x198) &= ~Mask;
- MemoryUtil.GetRef<uint>(sMhController.Instance + 0x1A0) &= ~Mask;
- MemoryUtil.GetRef<uint>(sMhController.Instance + 0x1A8) &= ~Mask;
- MemoryUtil.GetRef<uint>(sMhController.Instance + 0x1AC) &= ~Mask;
- MemoryUtil.GetRef<int>(sMhController.Instance + 0x1C0) = 0; // Left trigger.
- MemoryUtil.GetRef<int>(sMhController.Instance + 0x1C1) = 0; // Right trigger.
- MemoryUtil.GetRef<int>(sMhController.Instance + 0x1B0) = 0; // Rx.
- MemoryUtil.GetRef<int>(sMhController.Instance + 0x1B4) = 0; // Ry.
- }
- if (enableFreeCamera)
- {
- if (playerMovementLocked)
+ if (orbitIgnoreCamera)
{
- MemoryUtil.GetRef<int>(sMhController.Instance + 0x1B8) = 0; // Lx.
- MemoryUtil.GetRef<int>(sMhController.Instance + 0x1BC) = 0; // Ly.
+ if (PadLy < 0)
+ {
+ PadLy -= Math.Abs(PadLx);
+ }
+ else
+ {
+ PadLy += Math.Abs(PadLx);
+ }
+ Input.SetPadLy(PadLy);
}
if (orbitPlayer)
{
- if (plusRight != 0.0f && !playerMovementLocked && !orbitIgnoreCamera)
+ if (plusRight != 0.0f && playerMovementUnlocked && !orbitIgnoreCamera)
{
- int Lx = (int)(Int16.MaxValue * Math.Clamp(plusRight, -1.0f, 1.0f));
- MemoryUtil.GetRef<int>(sMhController.Instance + 0x1B8) = Lx;
+ Input.SetPadLx((int)(Math.Clamp(plusRight, -1.0f, 1.0f) * Int16.MaxValue));
}
if (plusForward != 0.0f)
{
- int Ly = (int)(Int16.MaxValue * Math.Clamp(plusForward, -1.0f, 1.0f));
- MemoryUtil.GetRef<int>(sMhController.Instance + 0x1BC) = Ly;
+ Input.SetPadLy((int)(Math.Clamp(plusForward, -1.0f, 1.0f) * Int16.MaxValue));
}
}
- if (!unlockMovementHeld && buttonWasPressed(Button.R2))
+ if (!unlockMovementHeld && Input.IsPressed(Button.R2))
{
unlockMovementHeld = true;
}
if (unlockMovementHeld)
{
- if (buttonWasPressed(Button.L1))
+ if (Input.IsPressed(Button.L1))
{
unlockMovementToggled = !unlockMovementToggled;
}
- // Temporarily disable for zoom mode.
- if (buttonWasDown(Button.L2))
+ if (Input.IsDown(Button.L2))
{
- unlockMovementPause = true;
+ unlockMovementPause = true; // For zoom mode.
}
- else if (buttonWasReleased(Button.L2))
+ else if (Input.IsReleased(Button.L2))
{
unlockMovementPause = false;
}
}
- if (buttonWasDown(Button.L2) && buttonWasPressed(Button.L1))
+ if (Input.IsDown(Button.L2) && Input.IsPressed(Button.L1))
{
lockVerticalToggled = !lockVerticalToggled;
}
if (blockInput)
{
- if (buttonWasDown(Button.R1))
+ if (Input.IsDown(Button.R1) && Input.IsPressed(Button.Down))
{
- if (buttonWasPressed(Button.Down))
- {
- Player? player = PlayerExt.getPlayer();
- if (player != null)
- {
- // Y - 150 to approximately align the players head with the camera.
- player.Position = new Vector3(cameraPosition.X, cameraPosition.Y - 150.0f, cameraPosition.Z);
- }
- }
-
- if (buttonWasPressed(Button.Left))
+ Player? player = PlayerExt.getPlayer();
+ if (player != null)
{
- toggleFreezeGame();
+ player.Position = new Vector3(cameraPosition.X, cameraPosition.Y - 150.0f, cameraPosition.Z);
}
}
- if (buttonWasDown(Button.Share))
+ if (Input.IsDown(Button.R1) && Input.IsPressed(Button.Left))
{
- if (buttonWasPressed(Button.Cross))
- {
- }
- if (buttonWasPressed(Button.Circle))
- {
- if (disableNearDofOverride != 0)
- {
- TuningToolInterop.RemoveOverride(disableNearDofOverride);
- disableNearDofOverride = 0;
- }
- else
- {
- disableNearDofOverride = TuningToolInterop.AddOverride("Dof Near Enable", new Vector4(), 0);
- }
- }
+ toggleFreezeGame();
}
- else if (freeCameraFromViewMode && !unlockInputForMenu && buttonWasPressed(Button.Circle))
+
+ if (Input.IsDown(Button.Share) && Input.IsPressed(Button.Circle))
{
- enableFreeCamera = false;
+ toggleNearDof();
}
- if (buttonWasPressed(Button.Options) && (plusRight != 0.0f || plusForward != 0.0f))
+ if (freeCameraFromViewMode && !Input.IsDown(Button.Share) && Input.IsPressed(Button.Circle))
{
- if (buttonWasDown(Button.Share))
- {
- plusRight = 0.0f;
- plusForward = 0.0f;
- }
- else
- {
- if (plusRight != 0.0f)
- {
- plusRight = -plusRight;
- }
- if (plusForward != 0.0f)
- {
- plusForward = -plusForward;
- }
- }
+ enableFreeCamera = false;
}
- if (!unlockInputForMenu && buttonWasPressed(Button.Triangle))
+
+ if (!unlockInputForMenu && !freeCameraIgnoreMenu && Input.IsPressed(Button.Triangle))
{
Player? player = PlayerExt.getPlayer();
if (player != null)
{
- nint baseAddr = MemoryUtil.Read<nint>(0x1451C4640);
- // MonsterHunterWorld.exe+1ADA26A - mov rax,[rbx+00014018]
- nint gesturesAddr = MemoryUtil.Read<nint>(baseAddr + 0x14018);
- if (buttonWasDown(Button.Share)) // MonsterHunterWorld.exe+1EC8000
- {
- setupGestureMenu.Invoke(gesturesAddr, 0x0, 0x1); // Poses.
- }
- else // MonsterHunterWorld.exe+1EC7D10
- {
- setupGestureMenu.Invoke(gesturesAddr, 0x0, 0x0); // Gestures.
- }
- showGestureMenu.Invoke(gesturesAddr);
+ openGestureMenu(Input.IsDown(Button.Share));
unlockInputForMenu = true;
}
}
@@ -1967,6 +1870,49 @@ namespace NewCamera
}
}
+ public void OnMouseUpdate()
+ {
+ if (mouseEnabled && !Input.MouseCaptured)
+ {
+ if (freeCamera)
+ {
+ if (freeCameraFromViewMode && Input.IsPressed(Key.Escape))
+ {
+ enableFreeCamera = false;
+ }
+ }
+ }
+ }
+
+ public void OnKeyboardUpdate()
+ {
+ if (keyboardEnabled && !Input.KeyboardCaptured)
+ {
+ if (Input.IsPressed(Key.NumPad0))
+ {
+ enableFreeCamera = !enableFreeCamera;
+ }
+
+ if (Input.IsPressed(Key.NumPadPeriod))
+ {
+ toggleUi();
+ }
+
+ if (freeCamera)
+ {
+ Input.Block(Key.Up);
+ Input.Block(Key.Down);
+ Input.Block(Key.Left);
+ Input.Block(Key.Right);
+
+ if (Input.IsPressed(Key.NumPadSlash))
+ {
+ toggleNearDof();
+ }
+ }
+ }
+ }
+
private float CheckMovementHook(int stickValue, float alwaysZero)
{
debugLog($"CheckMovementHook({stickValue:X}, {alwaysZero}) @ {updateTick}");
@@ -1981,7 +1927,7 @@ namespace NewCamera
vCamera.Target.Y = cameraPosition.Y;
vCamera.Target.Z = cameraPosition.Z + dist * MathF.Sin(Single.DegreesToRadians(orbitMovementRotation));
}
- if (playerMovementLocked && (plusRight == 0.0f && plusForward == 0.0f))
+ if (!playerMovementUnlocked && (plusRight == 0.0f && plusForward == 0.0f))
{
stickValue = 0;
}
@@ -2053,7 +1999,7 @@ namespace NewCamera
}
}
- private void drawViewportInfo(int i, float width, Config config, bool debug)
+ private unsafe void drawViewportInfo(int i, float width, Config config, bool debug)
{
ImGui.PushItemWidth(width * 0.75f);
Viewport vp = CameraSystem.GetViewport(i);
@@ -2157,7 +2103,8 @@ namespace NewCamera
continue;
}
string positionKey = positionKeys.ElementAt(j - 1);
- if (ImGui.Selectable(positionKey))
+ bool isSelected = positionKey == selectedPositionName;
+ if (ImGui.Selectable(positionKey, isSelected))
{
Config.Position pos = config.Positions[positionKey];
selectedPositionName = positionKey;
@@ -2171,6 +2118,7 @@ namespace NewCamera
camera.Position = cameraPosition;
camera.Target = cameraTarget;
}
+ if (isSelected) ImGui.SetItemDefaultFocus();
}
ImGui.EndCombo();
}
@@ -2206,7 +2154,7 @@ namespace NewCamera
}
if (camera == pCamera)
{
- Player? player = checkPlayerChange();
+ Player? player = PlayerExt.getPlayer();
if (!debug && player != null)
{
ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f));
@@ -2318,79 +2266,9 @@ namespace NewCamera
ImGui.PopItemWidth();
}
- public static void drawAnimationInfo(Entity entity, float width, bool debug)
+ public void OnRender()
{
- ActionController actionController = entity.ActionController;
- ActionInfo currentActionInfo = actionController.CurrentAction;
- SharpPluginLoader.Core.Actions.Action? currentAction = null;
- if (currentActionInfo.ActionSet >= 0 && currentActionInfo.ActionSet <= 3)
- {
- ActionList actionList = actionController.GetActionList(currentActionInfo.ActionSet);
- if (currentActionInfo.ActionId >= 0 && currentActionInfo.ActionId < actionList.Count)
- {
- currentAction = actionList[currentActionInfo.ActionId];
- }
- }
- if (debug)
- {
- ImGui.Text($"ActionController: 0x{actionController.Instance:X}");
- ImGui.Text($" Current: {currentAction} {currentActionInfo}");
- if (currentAction != null)
- {
-
- ImGui.Text($" Active Time: {currentAction.ActiveTime}");
- ImGui.Text($" Delta Sec: {currentAction.DeltaSec}");
- }
- }
- AnimationId currentAnimation = entity.CurrentAnimation;
- AnimationLayerComponent? animationLayer = entity.AnimationLayer;
- if (animationLayer != null)
- {
- ImGui.Text(debug ? $"AnimationLayer: 0x{animationLayer.Instance:X}" : "Animation");
- if (debug)
- {
- ImGui.Text($" Current: {currentAnimation}");
- ImGui.Text($" Frame: {animationLayer.CurrentFrame:0.000}/{animationLayer.MaxFrame:0.000}");
- return;
- }
- else
- {
- ImGui.Text($" Current: {currentAnimation.Lmt}.{currentAnimation.Id}, {(currentAction != null ? currentAction.Name : "None")}");
- if (ImGui.BeginItemTooltip())
- {
- ImGui.Text("{Lmt}.{Id}, {Action}");
- ImGui.EndTooltip();
- }
- ImGui.SetNextItemWidth(width * 0.8f);
- ImGui.SliderFloat("Frame", ref animationLayer.CurrentFrame, 0.0f, animationLayer.MaxFrame, "%.3f");
- }
- bool animationPaused = animationLayer.Paused;
- if (ImGui.Checkbox("Paused", ref animationPaused))
- {
- animationLayer.Paused = animationPaused;
- }
- ImGui.SameLine();
- float? lockedSpeed = animationLayer.LockedSpeed;
- float speed = lockedSpeed ?? animationLayer.Speed;
- bool animationLocked = lockedSpeed != null;
- if (ImGui.Checkbox("Set", ref animationLocked))
- {
- if (animationLocked)
- {
- animationLayer.LockSpeed(speed);
- }
- else
- {
- animationLayer.UnlockSpeed();
- }
- }
- ImGui.SameLine();
- ImGui.SetNextItemWidth(width * 0.35f);
- if (ImGui.DragFloat($"Speed", ref speed, 0.01f, 0.0f, 0.0f, "%.3f"))
- {
- if (animationLocked) animationLayer.LockSpeed(speed);
- }
- }
+ Poser.OnRender();
}
public void OnImGuiRender()
@@ -2403,13 +2281,11 @@ namespace NewCamera
Config config = ConfigManager.GetConfig<Config>(this);
// If we use vCamera or pCamera here, we need to ensure they're not invalid.
- Player? player = checkPlayerChange();
+ Player? player = PlayerExt.getPlayer();
checkCurrentVisibleCamera(player);
- ImGui.Separator();
-
ImGui.PushItemWidth(width * 0.475f);
- ImGui.Checkbox("Free Camera", ref enableFreeCamera);
+ ImGui.Checkbox("Enable Free Camera", ref enableFreeCamera);
ImGui.PushID("Settings");
ImGui.DragFloat("Camera Speed", ref cameraSpeed, 0.01f, 0.0f, 0.0f, "%.4f");
if (ImGui.BeginItemTooltip())
@@ -2471,9 +2347,9 @@ namespace NewCamera
ImGui.Separator();
- if (ImGui.Checkbox("Perspective Camera", ref enableOffsetPerspective))
+ if (ImGui.Checkbox("Enable Camera Offset", ref enableOffsetPerspective))
{
- config.PerspectiveCameraEnabled = enableOffsetPerspective;
+ config.CameraOffsetEnabled = enableOffsetPerspective;
if (enableOffsetPerspective)
{
if (config.Selected != "")
@@ -2697,8 +2573,8 @@ namespace NewCamera
ImGui.Separator();
- ImGui.PushID("Binds");
- if (ImGui.CollapsingHeader("Binds"))
+ ImGui.PushID("Controller");
+ if (ImGui.CollapsingHeader("Controller"))
{
if (ImGui.Checkbox("Toggle Free Camera", ref enableCombo))
{
@@ -2742,49 +2618,55 @@ namespace NewCamera
}
}
ImGui.SameLine();
- if (ImGui.Checkbox("Disable Button1 Unless Button2 is Held", ref disableComboButton1))
+ if (ImGui.Checkbox("Button1 Blocks Input Unless Button2 is Held", ref blockComboButton1))
{
comboButton1Down = false;
Config.Settings.Binds binds = config.Binds;
- binds.DisableComboButton1UnlessButton2Held = disableComboButton1;
+ binds.ComboButton1BlocksUnlessButton2Held = blockComboButton1;
config.Binds = binds;
ConfigManager.SaveConfig<Config>(this);
}
if (ImGui.BeginItemTooltip())
{
- ImGui.Text("For example, if bound to RStick+LT, right stick presses will ignored by the game unless you're holding the left trigger.\nIn that case, it can let you avoid switching the targeted monster when toggling free camera.");
+ ImGui.Text("This allows Global binds to not interrupt the game.");
ImGui.EndTooltip();
}
ImGui.Text("Global");
- if (ImGui.BeginItemTooltip())
+ if (!enableCombo)
{
- ImGui.Text("Button1 refers to the first button of the Toggle Free Camera bind.");
- ImGui.EndTooltip();
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
}
if (ImGui.BeginTable("Global Binds", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders))
{
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text("Hold Button1 + Press Select");
+ ImGui.Text("Hold Button1");
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("Button1 refers to the first button of the Toggle Free Camera bind.");
+ ImGui.EndTooltip();
+ }
ImGui.TableSetColumnIndex(1);
- ImGui.Text("Toggle UI");
+ ImGui.Text("");
+
+ ImGui.Indent(6.0f);
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text("Hold Button1 + Press D-Pad Up/Down");
+ ImGui.Text("Select");
ImGui.TableSetColumnIndex(1);
- ImGui.Text("Select Perspective Camera Preset");
+ ImGui.Text("Toggle UI");
- ImGui.EndTable();
- }
+ ImGui.TableNextRow();
+ ImGui.TableSetColumnIndex(0);
+ ImGui.Text("D-Pad Up/Down");
+ ImGui.TableSetColumnIndex(1);
+ ImGui.Text("Select Camera Offset Preset");
- ImGui.Text("While in Free Camera | ( ) = Toggle");
- if (ImGui.BeginTable("Binds", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders))
- {
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text("Hold Button1 + Press LB");
+ ImGui.Text("LB");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Toggle Unlock Input");
if (ImGui.BeginItemTooltip())
@@ -2793,22 +2675,34 @@ namespace NewCamera
ImGui.EndTooltip();
}
+ ImGui.Unindent(6.0f);
+
+ ImGui.EndTable();
+ }
+ if (!enableCombo)
+ {
+ ImGui.PopStyleVar();
+ }
+
+ ImGui.Text("While in Free Camera | ( ) = Toggle");
+ if (ImGui.BeginTable("Binds", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders))
+ {
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text("Hold RT (+ Press LB)");
+ ImGui.Text("Hold RT (LB)");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Unlock Player Movement and Freeze Camera Movement");
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text("Hold LT (+ Press LB)");
+ ImGui.Text("Hold LT (LB)");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Lock Vertical Camera Movement and Apply Speed Modifier");
ImGui.EndTable();
}
- ImGui.Text("Disabled While Input to the Game is Unlocked");
+ ImGui.Text("Disabled While Input is Unlocked");
if (ImGui.BeginTable("More Binds", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders))
{
ImGui.TableNextRow();
@@ -2825,7 +2719,7 @@ namespace NewCamera
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text("Hold LT + RT");
+ ImGui.Text("Hold LT & RT");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Zoom with Left Stick Up/Down");
if (ImGui.BeginItemTooltip())
@@ -2836,7 +2730,7 @@ namespace NewCamera
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text("Press Y");
+ ImGui.Text("Y");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Open Gestures Menu");
@@ -2846,48 +2740,67 @@ namespace NewCamera
ImGui.TableSetColumnIndex(1);
ImGui.Text("");
+ ImGui.Indent(6.0f);
+
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text(" + Press Y");
+ ImGui.Text("Y");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Open Poses Menu");
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text(" + Press X");
+ ImGui.Text("B");
+ ImGui.TableSetColumnIndex(1);
+ ImGui.Text("Toggle Depth of Field Near");
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("Requires World Tuning Tool.");
+ ImGui.EndTooltip();
+ }
+
+ ImGui.TableNextRow();
+ ImGui.TableSetColumnIndex(0);
+ ImGui.Text("X");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Toggle Alternate Near Clip");
+ ImGui.Unindent(6.0f);
+
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
ImGui.Text("Hold RB");
ImGui.TableSetColumnIndex(1);
ImGui.Text("");
+ ImGui.Indent(6.0f);
+
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text(" + Press D-Pad Right");
+ ImGui.Text("D-Pad Right");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Reset Roll");
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text(" + Press D-Pad Up");
+ ImGui.Text("D-Pad Up");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Reset Zoom");
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text(" + Press D-Pad Left");
+ ImGui.Text("D-Pad Left");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Toggle Freeze Game");
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text(" + Press D-Pad Down");
+ ImGui.Text("D-Pad Down");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Teleport Player to Camera Position");
+ ImGui.Unindent(6.0f);
+
ImGui.EndTable();
}
@@ -2895,7 +2808,6 @@ namespace NewCamera
}
ImGui.PopID();
-#if MOUSE_AND_KEYBOARD_LAYER
ImGui.PushID("Mouse/Keyboard");
if (ImGui.CollapsingHeader("Mouse & Keyboard"))
{
@@ -2908,6 +2820,8 @@ namespace NewCamera
ConfigManager.SaveConfig<Config>(this);
}
ImGui.SameLine();
+ float widthDiff = ImGui.CalcTextSize("Enable Keyboard").X - ImGui.CalcTextSize("Enable Mouse").X;
+ ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(widthDiff, 0.0f));
if (ImGui.DragFloat("Mouse Sensitivity", ref mouseSensitivity, 0.001f, 0.0f, 0.0f, "%.4f"))
{
Config.Settings.Binds binds = config.Binds;
@@ -3000,13 +2914,19 @@ namespace NewCamera
ImGui.Separator();
}
ImGui.PopID();
-#endif
ImGui.PushID("Viewport");
- if (ImGui.CollapsingHeader("Viewport") && vCameraViewportIndex >= 0)
+ if (ImGui.CollapsingHeader("Viewport"))
{
- drawViewportInfo(vCameraViewportIndex, width, config, false);
- ImGui.Separator();
+ if (vCameraViewportIndex >= 0)
+ {
+ drawViewportInfo(vCameraViewportIndex, width, config, false);
+ ImGui.Separator();
+ }
+ else
+ {
+ ImGui.Text("No viewports");
+ }
}
ImGui.PopID();
@@ -3020,12 +2940,21 @@ namespace NewCamera
{
if (player != null)
{
- PlayerExt.drawPlayerInfo(player, width);
+ PlayerExt.DrawPlayerInfo(player, width);
ImGui.Separator();
}
+ else
+ {
+ ImGui.Text("Player not found");
+ }
}
ImGui.PopID();
+ if (Poser.overlayJoints)
+ {
+ Renderer.RequestMouseCapture();
+ }
+
ImGui.PushID("World");
if (ImGui.CollapsingHeader("World"))
{
@@ -3152,7 +3081,7 @@ namespace NewCamera
ImGui.Text($"Address: 0x{player.Instance:X}");
ImGui.Text($"Settings: 0x{PlayerExt.getPlayerSettings():X}");
- drawAnimationInfo(player, width, true);
+ Models.drawAnimationInfo(player, width, true);
bool move = player.Move;
if (ImGui.Checkbox("Move", ref move))
@@ -3202,14 +3131,11 @@ namespace NewCamera
ImGui.DragFloat3("Position", ref monster.Position, 0.5f);
Vector4 rotation = new Vector4(monster.Rotation.X, monster.Rotation.Y, monster.Rotation.Z, monster.Rotation.W);
ImGui.SliderFloat4("Rotation", ref rotation, -1.0f, 1.0f);
- Vector3 rotationOffset = new Vector3();
- if (ImGui.DragFloat3("Rotation Offset", ref rotationOffset, 0.0025f))
+ if (Models.DrawRotate("Rotate", rotation, out Vector4 result))
{
- Quaternion qRotation = new Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W);
- qRotation *= Quaternion.CreateFromYawPitchRoll(rotationOffset.X, rotationOffset.Y, rotationOffset.Z);
- monster.Rotation = new MtQuaternion(qRotation.X, qRotation.Y, qRotation.Z, qRotation.W);
+ monster.Rotation = new MtQuaternion(result.X, result.Y, result.Z, result.W);
}
- drawAnimationInfo(monster, width, true);
+ Models.drawAnimationInfo(monster, width, true);
ImGui.PopID();
ImGui.Separator();
}
@@ -3238,7 +3164,12 @@ namespace NewCamera
ImGui.Text($"{animal.Id:X} ({animal.OtherId:X}):");
ImGui.Text($" Address: 0x{animal.Instance:X}");
ImGui.DragFloat3("Position", ref animal.Position, 0.5f);
- // Freeze: +0x1AFC = 0xFFFFFFFC
+ Vector4 rotation = new Vector4(animal.Rotation.X, animal.Rotation.Y, animal.Rotation.Z, animal.Rotation.W);
+ ImGui.SliderFloat4("Rotation", ref rotation, -1.0f, 1.0f);
+ if (Models.DrawRotate("Rotate", rotation, out Vector4 result))
+ {
+ animal.Rotation = new MtQuaternion(result.X, result.Y, result.Z, result.W);
+ }
if (ImGui.Button("Remove"))
{
MemoryUtil.GetRef<uint>(animal.Instance + 0x928) = 0xFFFFFFFF;
@@ -3250,124 +3181,27 @@ namespace NewCamera
ImGui.Separator();
- ImGui.Checkbox("Only Toggle LOD 0", ref modelOnlyAddressLod0);
+ Models.DrawModelsList(width, (player != null) ? player.Instance : 0x0);
+
+ bool expand = ImGui.CollapsingHeader("Objects");
if (ImGui.BeginItemTooltip())
{
- ImGui.Text($"This can be used to check if a given model is showing LOD 0 or not.\nApplies when a part is toggled, meaning you should probably toggle all parts on before enabling this.");
+ ImGui.Text("This reads from the list of objects to be updated.\nTherefore, at any given moment it could be empty.");
ImGui.EndTooltip();
}
- if (ImGui.CollapsingHeader("Loaded Models") && player != null)
+ if (expand)
{
- ImGui.Text("Filter");
- bool updateRegex = false;
- ImGui.SetNextItemWidth(width * 0.5f);
- bool invalidRegex = modelFilterIsRegex && modelFilter != "" && modelRegex == null;
- if (invalidRegex)
- {
- ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0000FF);
- }
- if (ImGui.InputText("##Filter", ref modelFilter, 256))
- {
- if (modelFilterIsRegex)
- {
- updateRegex = true;
- }
- }
- if (invalidRegex)
- {
- ImGui.PopStyleColor();
- }
- ImGui.SameLine();
- if (ImGui.Button("Clear"))
- {
- modelFilter = "";
- if (modelFilterIsRegex)
- {
- updateRegex = true;
- }
- }
- ImGui.SameLine();
- if (ImGui.Checkbox("Regex", ref modelFilterIsRegex))
- {
- if (modelFilterIsRegex)
- {
- updateRegex = true;
- }
- }
- if (updateRegex)
- {
- if (String.IsNullOrEmpty(modelFilter))
- {
- modelRegex = null;
- }
- else
- {
- try
- {
- modelRegex = new Regex(modelFilter);
- }
- catch (ArgumentException)
- {
- modelRegex = null;
- }
- }
- }
- nint bodyArmorParts = MemoryUtil.Read<nint>(player.Instance + 0x2A0);
- if (bodyArmorParts != 0x0)
- {
- nint next = bodyArmorParts - 0x40;
- nint head = next;
- nint prev = MemoryUtil.Read<nint>(next + 0x10);
- for (;next != 0x0;)
- {
- ImGui.PushID(next);
- nint partsAddr = next + 0x40;
- nint vTable = MemoryUtil.Read<nint>(partsAddr);
- if (vTable == 0x143507A18)
- {
- string fullString = Marshal.PtrToStringAnsi(partsAddr + 0xC)!;
- bool filterMatch = false;
- if (modelFilterIsRegex)
- {
- filterMatch = modelRegex == null || modelRegex.Match(fullString).Success;
- }
- else
- {
- filterMatch = String.IsNullOrEmpty(modelFilter) || fullString.StartsWith(modelFilter);
- }
- if (filterMatch)
- {
- PlayerExt.drawModelParts(0x0, partsAddr);
- }
- }
- ImGui.PopID();
- if (head == prev)
- {
- next = MemoryUtil.Read<nint>(next + 0x10);
- }
- else
- {
- next = MemoryUtil.Read<nint>(next + 0x18);
- if (next == 0x0)
- {
- head = prev;
- next = prev;
- }
- }
- }
- }
+ Models.DrawObjectList(width, player!);
}
ImGui.Separator();
-#if MOUSE_AND_KEYBOARD_LAYER
ImGui.PushID("Mouse/Keyboard");
ImGui.Text("Mouse");
ImGui.Text($"Address: 0x{sMhMouse.Instance:X}");
ImGui.Text("Keyboard");
ImGui.Text($"Address: 0x{sMhKeyboard.Instance:X}");
ImGui.PopID();
-#endif
ImGui.PushID("Pad");
ImGui.Text("Pad");
diff --git a/Poser.cs b/Poser.cs
new file mode 100644
index 0000000..39ca033
--- /dev/null
+++ b/Poser.cs
@@ -0,0 +1,2320 @@
+//#define QUARANTINED_FEATURES
+
+using System.Numerics;
+using System.Runtime.InteropServices;
+using System.Globalization;
+using System.Text;
+using System.Text.Json;
+
+using ImGuiNET;
+using SharpPluginLoader.Core;
+using SharpPluginLoader.Core.MtTypes;
+using SharpPluginLoader.Core.Entities;
+using SharpPluginLoader.Core.Memory;
+using SharpPluginLoader.Core.Rendering;
+
+namespace NewCamera
+{
+ using static Plugin;
+
+ public unsafe class Poser
+ {
+ private const string posePath = "nativePC/plugins/CSharp/Poses";
+
+ private static class Armor
+ {
+ public const byte Body = 0;
+ public const byte Helmet = 1;
+ public const byte Arm = 2;
+ public const byte Waist = 3;
+ public const byte Leg = 4;
+ public const byte Slinger = 5;
+ public const byte Hair = 6;
+ public const byte Face = 7;
+ public const byte EyeLens = 8;
+ }
+
+ private static class Joint
+ {
+ public const byte Root = 0x0;
+ public const byte Root2 = 0xD;
+ public const byte LowerBack = 0x1;
+ public const byte UpperBack = 0x2;
+ public const byte LowerNeck = 0x3;
+ public const byte LowerNeckNull = 0xFE;
+ public const byte UpperNeck = 0x4;
+ public const byte LeftCollarbone = 0x5;
+ public const byte LeftShoulderNull = 0x46;
+ public const byte LeftShoulder = 0x6;
+ public const byte LeftElbow = 0x7;
+ public const byte LeftWrist = 0x8;
+ public const byte LeftWristNull = 0x1E;
+ public const byte LeftThumbLow = 0x1F;
+ public const byte LeftThumbMid = 0x20;
+ public const byte LeftThumbHigh = 0x21;
+ public const byte LeftIndexLow = 0x22;
+ public const byte LeftIndexMid = 0x23;
+ public const byte LeftIndexHigh = 0x24;
+ public const byte LeftMiddleLow = 0x25;
+ public const byte LeftMiddleMid = 0x26;
+ public const byte LeftMiddleHigh = 0x27;
+ public const byte LeftPalm = 0x28;
+ public const byte LeftRingLow = 0x29;
+ public const byte LeftRingMid = 0x2A;
+ public const byte LeftRingHigh = 0x2B;
+ public const byte LeftPinkyLow = 0x2C;
+ public const byte LeftPinkyMid = 0x2D;
+ public const byte LeftPinkyHigh = 0x2E;
+ public const byte LeftArmUnk1 = 0x51;
+ public const byte LeftArmUnk2 = 0x65;
+ public const byte LeftArmUnk3 = 0x66;
+ public const byte LeftArmUnk4 = 0x67;
+ public const byte LeftArmUnk5 = 0x68;
+ public const byte LeftArmUnk6 = 0x47;
+ public const byte LeftArmUnk7 = 0x50;
+ public const byte RightCollarbone = 0x9;
+ public const byte RightShoulder = 0xA;
+ public const byte RightElbow = 0xB;
+ public const byte RightWrist = 0xC;
+ public const byte RightWristNull = 0x2F;
+ public const byte RightThumbLow = 0x30;
+ public const byte RightThumbMid = 0x31;
+ public const byte RightThumbHigh = 0x32;
+ public const byte RightIndexLow = 0x33;
+ public const byte RightIndexMid = 0x34;
+ public const byte RightIndexHigh = 0x35;
+ public const byte RightMiddleLow = 0x36;
+ public const byte RightMiddleMid = 0x37;
+ public const byte RightMiddleHigh = 0x38;
+ public const byte RightPalm = 0x39;
+ public const byte RightRingLow = 0x3A;
+ public const byte RightRingMid = 0x3B;
+ public const byte RightRingHigh = 0x3C;
+ public const byte RightPinkyLow = 0x3D;
+ public const byte RightPinkyMid = 0x3E;
+ public const byte RightPinkyHigh = 0x3F;
+ public const byte RightArmUnk1 = 0x53;
+ public const byte RightArmUnk2 = 0x49;
+ public const byte RightArmUnk3 = 0x52;
+ public const byte RightArmUnk4 = 0x48;
+ public const byte Unknown1 = 0xF7;
+ public const byte Unknown2 = 0xF8;
+ public const byte LeftHip = 0xE;
+ public const byte LeftKnee = 0xF;
+ public const byte LeftAnkle = 0x10;
+ public const byte LeftToes = 0x11;
+ public const byte LeftAnkleNull = 0x54;
+ public const byte LeftKneeNull = 0x4B;
+ public const byte LeftHipNull = 0x4A;
+ public const byte Unknown3 = 0x40;
+ public const byte Unknown4 = 0x42;
+ public const byte RightHip = 0x12;
+ public const byte RightKnee = 0x13;
+ public const byte RightAnkle = 0x14;
+ public const byte RightToes = 0x15;
+ public const byte RightAnkleNull = 0x55;
+ public const byte RightKneeNull = 0x4D;
+ public const byte RightHipNull = 0x4C;
+ public const byte Unknown5 = 0x43;
+ public const byte Unknown6 = 0x45;
+ public const byte Unknown7 = 0xF9;
+ public const byte Unknown8 = 0xFA;
+ public const byte Unknown9 = 0xFB;
+ public const byte Unknown10 = 0xFC;
+ public const byte Unknown11 = 0xFD;
+ }
+
+ private static class FaceJoint
+ {
+ public const byte LeftCheek1 = 0x6C;
+ public const byte LeftCheek2 = 0x99;
+ public const byte RightCheek1 = 0x71;
+ public const byte RightCheek2 = 0x9E;
+ public const byte RightCheek3 = 0x70;
+ public const byte LeftCheek3 = 0x6B;
+ public const byte RightCheek4 = 0x6F;
+ public const byte LeftCheek4 = 0x6A;
+ public const byte RightCheek5 = 0x72;
+ public const byte LeftCheek5 = 0x6D;
+ public const byte LeftCheek = 0x6E;
+ public const byte RightCheek = 0x73;
+ public const byte LeftEye = 0x3A;
+ public const byte LeftEye1 = 0x3B;
+ public const byte LeftEye2 = 0x43;
+ public const byte LeftEye3 = 0x42;
+ public const byte LeftEye4 = 0x41;
+ public const byte LeftEye5 = 0x40;
+ public const byte LeftEye6 = 0x3F;
+ public const byte LeftEye7 = 0x46;
+ public const byte LeftEye8 = 0x45;
+ public const byte LeftEye9 = 0x44;
+ public const byte LeftEye10 = 0x3C;
+ public const byte LeftEye11 = 0x3E;
+ public const byte LeftEye12 = 0x3D;
+ public const byte LeftEye13 = 0x68;
+ public const byte RightEye = 0x47;
+ public const byte RightEye1 = 0x48;
+ public const byte RightEye2 = 0x50;
+ public const byte RightEye3 = 0x4F;
+ public const byte RightEye4 = 0x4E;
+ public const byte RightEye5 = 0x4D;
+ public const byte RightEye6 = 0x4C;
+ public const byte RightEye7 = 0x51;
+ public const byte RightEye8 = 0x52;
+ public const byte RightEye9 = 0x53;
+ public const byte RightEye10 = 0x4A;
+ public const byte RightEye11 = 0x4B;
+ public const byte RightEye12 = 0x49;
+ public const byte RightEye13 = 0x69;
+ public const byte Nose = 0x54;
+ public const byte Nose1 = 0x55;
+ public const byte Nose2 = 0x56;
+ public const byte Nose3 = 0x58;
+ public const byte Nose4 = 0x64;
+ public const byte Nose5 = 0x5E;
+ public const byte Nose6 = 0x5F;
+ public const byte Nose7 = 0x65;
+ public const byte Nose8 = 0x5C;
+ public const byte Nose9 = 0x62;
+ public const byte Nose10 = 0x5D;
+ public const byte Nose11 = 0x63;
+ public const byte Nose12 = 0x5B;
+ public const byte Nose13 = 0x61;
+ public const byte Nose14 = 0x5A;
+ public const byte Nose15 = 0x60;
+ public const byte Nose16 = 0x57;
+ public const byte Nose17 = 0x59;
+ public const byte Nose18 = 0x66;
+ public const byte Nose19 = 0x67;
+ public const byte Mouth = 0x75;
+ public const byte Mouth1 = 0x80;
+ public const byte Mouth2 = 0x81;
+ public const byte Mouth3 = 0x86;
+ public const byte Mouth4 = 0x85;
+ public const byte Mouth5 = 0x84;
+ public const byte Mouth6 = 0x83;
+ public const byte Mouth7 = 0x82;
+ public const byte Mouth8 = 0x8B;
+ public const byte Mouth9 = 0x8A;
+ public const byte Mouth10 = 0x89;
+ public const byte Mouth11 = 0x88;
+ public const byte Mouth12 = 0x87;
+ public const byte Mouth13 = 0x8F;
+ public const byte Mouth14 = 0x8E;
+ public const byte Mouth15 = 0x90;
+ public const byte Mouth16 = 0x8D;
+ public const byte Mouth17 = 0x91;
+ public const byte Mouth18 = 0x8C;
+ public const byte Mouth19 = 0x92;
+ public const byte Mouth20 = 0x76;
+ public const byte Mouth21 = 0x77;
+ public const byte Mouth22 = 0x78;
+ public const byte Mouth23 = 0x79;
+ public const byte Mouth24 = 0x7A;
+ public const byte Mouth25 = 0x7F;
+ public const byte Mouth26 = 0x7E;
+ public const byte Mouth27 = 0x7D;
+ public const byte Mouth28 = 0x7C;
+ public const byte Mouth29 = 0x7B;
+ public const byte Mouth30 = 0x74;
+ public const byte ChinMiddle = 0x94;
+ public const byte ChinRight = 0x9C;
+ public const byte ChinLeft = 0x9B;
+ public const byte ChinRightBack = 0x9D;
+ public const byte ChinLeftBack = 0x9A;
+ public const byte NeckMiddle = 0xA0;
+ public const byte Jaw = 0x97;
+ public const byte Jaw1 = 0xEA;
+ public const byte Jaw2 = 0xEB;
+ public const byte JawLeft = 0x98;
+ public const byte JawRight = 0x96;
+ public const byte JawUpLeft = 0x93;
+ public const byte JawUpRight = 0x95;
+ public const byte NeckLeft = 0x9F;
+ public const byte NeckRight = 0xA1;
+ public const byte EyeAgainLeft = 0xF4;
+ public const byte EyeAgainLeft1 = 0xF5;
+ public const byte NoseAgain = 0xF6;
+ public const byte MouthAgain = 0xF7;
+ public const byte Forehead0 = 0xF8;
+ public const byte Forehead = 0xA2;
+ public const byte Forehead1 = 0x36;
+ public const byte Forehead2 = 0x37;
+ public const byte Forehead3 = 0x38;
+ public const byte Forehead4 = 0x35;
+ public const byte Forehead5 = 0x34;
+ public const byte Forehead6 = 0x33;
+ public const byte Forehead7 = 0x32;
+ public const byte Forehead8 = 0x2E;
+ public const byte Forehead9 = 0x2D;
+ public const byte Forehead10 = 0x2F;
+ public const byte Forehead11 = 0x2C;
+ public const byte Forehead12 = 0x30;
+ public const byte Forehead13 = 0x31;
+ public const byte Forehead14 = 0x39;
+ public const byte Base1 = 0xFB;
+ public const byte Base2 = 0xFC;
+ public const byte Base3 = 0xFD;
+ }
+
+ private static nint[] playerArmor = new nint[9];
+ private static List<nint> playerWeapon = new List<nint>();
+ private static nint[] bodyJointMap = new nint[0xFF];
+ private static nint[] faceJointMap = new nint[0xFF];
+ private static int lastArmorRefresh = -1;
+
+ private delegate void UpdateJoints(nint obj);
+ private static Hook<UpdateJoints>? updateJointRotationHook;
+ private static Hook<UpdateJoints>? updateJointPositionHook;
+
+ public static List<nint> bodyJoints = new List<nint>();
+ private static List<nint> ignoredJoints = new List<nint>();
+ private static Dictionary<nint, Vector4> bodyRotations = new Dictionary<nint, Vector4>();
+ private static Dictionary<nint, Vector3> bodyPositions = new Dictionary<nint, Vector3>();
+ private static Dictionary<nint, Vector3> bodyOffsets = new Dictionary<nint, Vector3>();
+
+ private static List<nint> faceJoints = new List<nint>();
+ private static Dictionary<nint, Vector4> faceRotations = new Dictionary<nint, Vector4>();
+ private static Dictionary<nint, Vector3> facePositions = new Dictionary<nint, Vector3>();
+ private static Dictionary<nint, Vector3> faceOffsets = new Dictionary<nint, Vector3>();
+
+ private static List<nint> jiggleBones = new List<nint>();
+
+ private static bool ikForcedOff = false;
+ private static Patch forceDisableIK;
+#if QUARANTINED_FEATURES
+ private delegate void UpdateIKPosition(nint superOfChild, nint joint, nint obj);
+ private static Hook<UpdateIKPosition>? updateIKPositionHook;
+ private static List<nint> ikJoints = new List<nint>();
+ private static Dictionary<nint, Vector3> ikOffsets = new Dictionary<nint, Vector3>();
+#endif
+
+ public static void Initialize()
+ {
+ forceDisableIK = new Patch(0x14031FD40, [0xC6, 0x81, 0x81, 0x01, 0x00, 0x00, 0x00, 0xC3]);
+
+ updateJointRotationHook = Hook.Create<UpdateJoints>(0x14223BA30, UpdateJointRotationHook);
+ updateJointPositionHook = Hook.Create<UpdateJoints>(0x141FBCCD0, UpdateJointPositionHook);
+#if QUARANTINED_FEATURES
+ updateIKPositionHook = Hook.Create<UpdateIKPosition>(0x142472C00, UpdateIKPositionHook);
+#endif
+ }
+
+ private static void dropArmorState()
+ {
+ Array.Clear(playerArmor, 0, playerArmor.Length);
+ playerWeapon.Clear();
+ Array.Clear(bodyJointMap, 0, bodyJointMap.Length);
+ Array.Clear(faceJointMap, 0, faceJointMap.Length);
+ bodyJoints.Clear();
+ ignoredJoints.Clear();
+ faceJoints.Clear();
+#if QUARANTINED_FEATURES
+ ikJoints.Clear();
+#endif
+ jiggleBones.Clear();
+ PlayerExt.Attach.DropState();
+ }
+
+ private static void dropJointOffsets()
+ {
+ bodyRotations.Clear();
+ bodyPositions.Clear();
+ bodyOffsets.Clear();
+ faceRotations.Clear();
+ facePositions.Clear();
+ faceOffsets.Clear();
+#if QUARANTINED_FEATURES
+ ikOffsets.Clear();
+#endif
+ }
+
+ private static void refreshArmorState(Player player)
+ {
+ dropArmorState();
+ if (!collectArmorAndJoints(player))
+ {
+ dropJointOffsets();
+ }
+ /*
+ if (playerArmor[Armor.Waist] != 0x0)
+ {
+ if (hideKnife)
+ {
+ MemoryUtil.GetRef<byte>(playerArmor[Armor.Waist] + 0x2D0) &= 0xFD;
+ }
+ else
+ {
+ MemoryUtil.GetRef<byte>(playerArmor[Armor.Waist] + 0x2D0) |= 0x2;
+ }
+ }
+ */
+ lastArmorRefresh = updateTick;
+ }
+
+ private static void collectArmorParts(nint baseAddr, nint addr)
+ {
+ int part;
+ string fullString = Marshal.PtrToStringAnsi(addr + 0xC)!;
+ string partName = Models.extractPartName(fullString);
+ if (partName == "body") part = Armor.Body;
+ else if (partName == "helm") part = Armor.Helmet;
+ else if (partName == "arm") part = Armor.Arm;
+ else if (partName == "wst") part = Armor.Waist;
+ else if (partName == "leg") part = Armor.Leg;
+ else if (partName.StartsWith("slg")) part = Armor.Slinger;
+ else if (partName.StartsWith("hair")) part = Armor.Hair;
+ else if (partName == "face000") part = Armor.Face;
+ else if (partName == "face000_eyelens") part = Armor.EyeLens;
+ else if (fullString.StartsWith("wp\\"))
+ {
+ playerWeapon.Add(baseAddr);
+ return;
+ }
+ else return;
+ playerArmor[part] = baseAddr;
+
+ int jointCount = MemoryUtil.Read<int>(baseAddr + 0x4A0);
+ nint jointAddr = MemoryUtil.Read<nint>(baseAddr + 0x4A8);
+ for (int i = 0; i < jointCount; i++)
+ {
+ nint childAddr = MemoryUtil.Read<nint>(jointAddr + 0x8);
+ if (childAddr != 0x0 && MemoryUtil.Read<nint>(childAddr) == 0x142F21A90)
+ {
+ childAddr = MemoryUtil.Read<nint>(childAddr + 0x8);
+ if (childAddr != 0x0)
+ {
+ nint childVtable = MemoryUtil.Read<nint>(childAddr);
+ if (childVtable == 0x1435195B8) // Jiggle bone container.
+ {
+ if (part == Armor.Body)
+ {
+ ignoredJoints.Add(jointAddr);
+ }
+ }
+ else if (childVtable == 0x143524BD8)
+ {
+ childAddr = MemoryUtil.Read<nint>(childAddr + 0x188);
+ if (childAddr != 0x0 && MemoryUtil.Read<nint>(childAddr) == 0x143519530)
+ {
+ nint jiggleData = MemoryUtil.Read<nint>(MemoryUtil.Read<nint>(childAddr + 0xA0));
+ if (MemoryUtil.Read<nint>(jiggleData) == 0x143519508)
+ {
+ if (!jiggleBones.Contains(jiggleData))
+ {
+ int jiggleIndex = jiggleBones.Count();
+ jiggleBones.Add(jiggleData);
+ PlayerExt.Attach.OnBone(jiggleData, jiggleIndex, part == Armor.Body);
+ }
+ }
+ }
+ if (part == Armor.Body)
+ {
+ ignoredJoints.Add(jointAddr);
+ }
+ }
+#if QUARANTINED_FEATURES
+ else if (childVtable == 0x143249170)
+ {
+ childAddr = MemoryUtil.Read<nint>(childAddr + 0x188);
+ if (childAddr != 0x0 && MemoryUtil.Read<nint>(childAddr) == 0x1432492F0)
+ {
+ ikJoints.Add(jointAddr);
+ }
+ }
+#endif
+ }
+ }
+ if (part == Armor.Body)
+ {
+ bodyJoints.Add(jointAddr);
+ }
+ else if (part == Armor.Face)
+ {
+ faceJoints.Add(jointAddr);
+ }
+ jointAddr += 0xC0;
+ }
+
+ if (part == Armor.Body)
+ {
+ for (int i = 0; i < bodyJoints.Count; i++)
+ {
+ jointAddr = bodyJoints[i];
+ if (ignoredJoints.Contains(jointAddr))
+ {
+ continue;
+ }
+ byte id = MemoryUtil.Read<byte>(jointAddr + 0xA0);
+ Assert(bodyJointMap[id] == 0x0);
+ bodyJointMap[id] = jointAddr;
+ }
+ foreach ((nint joint, _) in bodyRotations.Where((e) => !bodyJoints.Contains(e.Key))) bodyRotations.Remove(joint);
+ foreach ((nint joint, _) in bodyPositions.Where((e) => !bodyJoints.Contains(e.Key))) bodyPositions.Remove(joint);
+ foreach ((nint joint, _) in bodyOffsets.Where((e) => !bodyJoints.Contains(e.Key))) bodyOffsets.Remove(joint);
+#if QUARANTINED_FEATURES
+ foreach ((nint joint, _) in ikOffsets.Where((e) => !bodyJoints.Contains(e.Key))) ikOffsets.Remove(joint);
+#endif
+ }
+ else if (part == Armor.Face)
+ {
+ for (int i = 0; i < faceJoints.Count; i++)
+ {
+ jointAddr = faceJoints[i];
+ byte id = MemoryUtil.Read<byte>(jointAddr + 0xA0);
+ Assert(faceJointMap[id] == 0x0);
+ faceJointMap[id] = jointAddr;
+ }
+ foreach ((nint joint, _) in faceRotations.Where((e) => !faceJoints.Contains(e.Key))) faceRotations.Remove(joint);
+ foreach ((nint joint, _) in facePositions.Where((e) => !faceJoints.Contains(e.Key))) facePositions.Remove(joint);
+ foreach ((nint joint, _) in faceOffsets.Where((e) => !faceJoints.Contains(e.Key))) faceOffsets.Remove(joint);
+ }
+ }
+
+ private static bool collectArmorAndJoints(Player player)
+ {
+ nint bodyArmorParts = MemoryUtil.Read<nint>(player.Instance + 0x2A0);
+ if (bodyArmorParts == 0x0)
+ {
+ return false;
+ }
+ // MonsterHunterWorld.exe+203E8A2 - mov rax,[rbx+000126C8]
+ nint combineArmorList = MemoryUtil.Read<nint>(player.Instance + 0x126C8);
+ if (combineArmorList == 0x0)
+ {
+ return false;
+ }
+ collectArmorParts(player.Instance, bodyArmorParts);
+ nint next, partsAddr;
+ nint weapon = MemoryUtil.Read<nint>(player.Instance + 0x76B0);
+ if (weapon != 0x0)
+ {
+ partsAddr = MemoryUtil.Read<nint>(weapon + 0x2A0);
+ if (partsAddr != 0x0)
+ {
+ collectArmorParts(weapon, partsAddr);
+ }
+ nint weaponParts = MemoryUtil.Read<nint>(weapon + 0x21D8);
+ next = weaponParts;
+ for (;next != 0x0;)
+ {
+ weaponParts = next;
+ next = MemoryUtil.Read<nint>(weaponParts + 0x30);
+ nint vTable = MemoryUtil.Read<nint>(weaponParts);
+ if (vTable == 0x1434D1D58) // uWeaponEmblem
+ {
+ if (MemoryUtil.Read<nint>(weaponParts + 0x590) != player.Instance)
+ {
+ continue;
+ }
+ nint parentAddr = MemoryUtil.Read<nint>(weaponParts + 0x5A8);
+ if (parentAddr != 0x0)
+ {
+ vTable = MemoryUtil.Read<nint>(parentAddr);
+ if (vTable == 0x1434D7C88 || vTable == 0x1434D7928) // uWpSubGeneral || uWpQuiver
+ {
+ if (MemoryUtil.Read<nint>(parentAddr + 0x9B0) != player.Instance)
+ {
+ continue;
+ }
+ partsAddr = MemoryUtil.Read<nint>(parentAddr + 0x2A0);
+ if (partsAddr != 0x0)
+ {
+ collectArmorParts(parentAddr, partsAddr);
+ }
+ }
+ }
+ }
+ else if (vTable == 0x1434D2400) // uWeaponParts
+ {
+ if (MemoryUtil.Read<nint>(weaponParts + 0x990) != player.Instance)
+ {
+ continue;
+ }
+ }
+ else
+ {
+ continue;
+ }
+ partsAddr = MemoryUtil.Read<nint>(weaponParts + 0x2A0);
+ if (partsAddr != 0x0)
+ {
+ collectArmorParts(weaponParts, partsAddr);
+ }
+ }
+ }
+ nint slinger = MemoryUtil.Read<nint>(player.Instance + 0x8918);
+ if (slinger != 0x0)
+ {
+ partsAddr = MemoryUtil.Read<nint>(slinger + 0x2A0);
+ if (partsAddr != 0x0)
+ {
+ collectArmorParts(slinger, partsAddr);
+ }
+ }
+ combineArmorList = MemoryUtil.Read<nint>(combineArmorList + 0x70);
+ next = combineArmorList;
+ for (;next != 0x0;)
+ {
+ nint armorAddr = next;
+ next = MemoryUtil.Read<nint>(armorAddr + 0x30);
+ nint vTable = MemoryUtil.Read<nint>(armorAddr);
+ if (vTable == 0x1434A7560) // uPlCombineArmor
+ {
+ nint parentAddr = MemoryUtil.Read<nint>(armorAddr + 0x548);
+ if (parentAddr != 0x0)
+ {
+ if (MemoryUtil.Read<nint>(parentAddr) == 0x143451520) // Face.
+ {
+ if (MemoryUtil.Read<nint>(parentAddr + 0x998) != player.Instance)
+ {
+ continue;
+ }
+ if (playerArmor[Armor.Face] == 0x0)
+ {
+ partsAddr = MemoryUtil.Read<nint>(parentAddr + 0x2A0);
+ if (partsAddr != 0x0)
+ {
+ collectArmorParts(parentAddr, partsAddr);
+ }
+ nint childAddr = MemoryUtil.Read<nint>(parentAddr + 0x9C8);
+ if (childAddr != 0x0 && MemoryUtil.Read<nint>(childAddr) == 0x143505E98) // Eye lens.
+ {
+ partsAddr = MemoryUtil.Read<nint>(childAddr + 0x2A0);
+ if (partsAddr != 0x0)
+ {
+ collectArmorParts(childAddr, partsAddr);
+ }
+ }
+ }
+ }
+ else if (parentAddr != player.Instance)
+ {
+ continue;
+ }
+ }
+ }
+ else
+ {
+ continue;
+ }
+ partsAddr = MemoryUtil.Read<nint>(armorAddr + 0x2A0);
+ if (partsAddr != 0x0)
+ {
+ collectArmorParts(armorAddr, partsAddr);
+ }
+ if (!playerArmor.Where((p) => p == 0x0).Any())
+ {
+ break;
+ }
+ }
+ return true;
+ }
+
+ private static void UpdateJointRotationHook(nint model)
+ {
+ debugLog($"UpdateJointRotationHook(0x{model:X}) @ {updateTick}");
+
+ Player? player = null;
+ bool updateBody = bodyRotations.Count() > 0 || (enableFreeCamera && orbitPlayer && orbitJoint >= 0);
+ bool updateFace = faceRotations.Count() > 0;
+ if (updateBody || updateFace)
+ {
+ player = PlayerExt.getPlayerWithFallback();
+ }
+
+ if (updateBody)
+ {
+ if (player != null && model == player.Instance)
+ {
+ refreshArmorState(player);
+ foreach ((nint addr, Vector4 rotation) in bodyRotations)
+ {
+ MemoryUtil.GetRef<Quaternion>(addr + 0x70) = new Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W);
+ }
+ }
+ }
+
+ if (updateFace)
+ {
+ if (player != null && model == playerArmor[Armor.Face])
+ {
+ if (!updateBody)
+ {
+ refreshArmorState(player);
+ }
+ else
+ {
+ Assert(lastArmorRefresh == updateTick);
+ }
+ foreach ((nint addr, Vector4 rotation) in faceRotations)
+ {
+ MemoryUtil.GetRef<Quaternion>(addr + 0x70) = new Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W);
+ }
+ }
+ }
+
+ updateJointRotationHook!.Original(model);
+ }
+
+ private static void UpdateJointPositionHook(nint model)
+ {
+ debugLog($"UpdateJointPositionHook(0x{model:X}) @ {updateTick}");
+
+ updateJointPositionHook!.Original(model);
+
+ Player? player = null;
+ bool updateBody = bodyPositions.Count() > 0 || bodyOffsets.Count() > 0;
+ bool updateFace = facePositions.Count() > 0 || faceOffsets.Count() > 0;
+ if (updateBody || updateFace)
+ {
+ player = PlayerExt.getPlayerWithFallback();
+ }
+
+ if (updateBody)
+ {
+ if (player != null && model == player.Instance)
+ {
+ refreshArmorState(player);
+ Quaternion rootRotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W);
+ Vector3 rootForward = Vector3.Transform(new Vector3(0.0f, 0.0f, 1.0f), rootRotation);
+ Vector3 rootRight = Vector3.Transform(new Vector3(1.0f, 0.0f, 0.0f), rootRotation);
+ Vector3 rootUp = new Vector3(0.0f, 1.0f, 0.0f);
+ foreach ((nint addr, Vector3 position) in bodyPositions)
+ {
+ MemoryUtil.GetRef<Vector3>(addr + 0x50) = player.Position + ((rootForward * position.X) + (rootUp * position.Y) + (rootRight * position.Z));
+ }
+ foreach ((nint addr, Vector3 offset) in bodyOffsets)
+ {
+ MemoryUtil.GetRef<Vector3>(addr + 0x50) += ((rootForward * offset.X) + (rootUp * offset.Y) + (rootRight * offset.Z));
+ }
+ }
+ }
+
+ if (updateFace)
+ {
+ if (player != null && model == playerArmor[Armor.Face])
+ {
+ if (!updateBody)
+ {
+ refreshArmorState(player);
+ }
+ else
+ {
+ Assert(lastArmorRefresh == updateTick);
+ }
+ Quaternion rootRotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W);
+ Vector3 rootForward = Vector3.Transform(new Vector3(0.0f, 0.0f, 1.0f), rootRotation);
+ Vector3 rootRight = Vector3.Transform(new Vector3(1.0f, 0.0f, 0.0f), rootRotation);
+ Vector3 rootUp = new Vector3(0.0f, 1.0f, 0.0f);
+ foreach ((nint addr, Vector3 position) in facePositions)
+ {
+ MemoryUtil.GetRef<Vector3>(addr + 0x50) = player.Position + ((rootForward * position.X) + (rootUp * position.Y) + (rootRight * position.Z));
+ }
+ foreach ((nint addr, Vector3 offset) in faceOffsets)
+ {
+ MemoryUtil.GetRef<Vector3>(addr + 0x50) += ((rootForward * offset.X) + (rootUp * offset.Y) + (rootRight * offset.Z));
+ }
+
+ }
+ }
+ }
+
+#if QUARANTINED_FEATURES
+ private static void UpdateIKPositionHook(nint superOfChild, nint joint, nint obj)
+ {
+ debugLog($"UpdateIKPositionHook(0x{superOfChild:X}, 0x{joint:X}, 0x{obj:X}) @ {updateTick}");
+
+ if (ikOffsets.ContainsKey(joint))
+ {
+ Vector3 offset = ikOffsets[joint];
+ MemoryUtil.GetRef<Vector3>(superOfChild + 0x1380) += offset;
+ }
+
+ updateIKPositionHook!.Original(superOfChild, joint, obj);
+ }
+#endif
+
+ private static void drawJoint(nint jointAddr, Dictionary<nint, Vector4> rotations, Dictionary<nint, Vector3> offsets)
+ {
+ if (jointAddr == 0x0) return;
+ ImGui.PushID(jointAddr);
+ bool hasRotation = rotations.ContainsKey(jointAddr);
+ bool hasOffset = offsets.ContainsKey(jointAddr);
+#if QUARANTINED_FEATURES
+ bool hasIkOffset = ikOffsets.ContainsKey(jointAddr);
+#endif
+ ref Vector3 position = ref MemoryUtil.GetRef<Vector3>(jointAddr + 0x50);
+ ref Vector4 rotation = ref MemoryUtil.GetRef<Vector4>(jointAddr + 0x70);
+ ImGui.DragFloat4("Rotation", ref rotation, 0.005f);
+ if (hasRotation)
+ {
+ ImGui.PushID("Rotation");
+ bool doRemove = ImGui.Button("X");
+ ImGui.SameLine();
+ if (ImGui.Button("Reset"))
+ {
+ rotations[jointAddr] = default;
+ }
+ ImGui.SameLine();
+ if (Models.DrawRotate("##Rotate", rotations[jointAddr], out Vector4 result))
+ {
+ rotations[jointAddr] = result;
+ }
+ if (doRemove) rotations.Remove(jointAddr);
+ ImGui.PopID();
+ }
+ ImGui.DragFloat3("Position", ref position, 0.005f);
+ if (hasOffset)
+ {
+ ImGui.PushID("Position");
+ bool doRemove = ImGui.Button("X");
+ ImGui.SameLine();
+ if (ImGui.Button("Reset"))
+ {
+ offsets[jointAddr] = default;
+ }
+ ImGui.SameLine();
+ Vector3 v = offsets[jointAddr];
+ if (ImGui.DragFloat3($"##Offset", ref v, 0.005f))
+ {
+ offsets[jointAddr] = v;
+ }
+ if (doRemove) offsets.Remove(jointAddr);
+ ImGui.PopID();
+ }
+#if QUARANTINED_FEATURES
+ if (hasIkOffset)
+ {
+ ImGui.PushID("IK");
+ bool doRemove = ImGui.Button("X");
+ ImGui.SameLine();
+ if (ImGui.Button("Reset"))
+ {
+ ikOffsets[jointAddr] = default;
+ }
+ ImGui.SameLine();
+ Vector3 v = ikOffsets[jointAddr];
+ if (ImGui.DragFloat3($"##IK Offset", ref v, 0.025f))
+ {
+ ikOffsets[jointAddr] = v;
+ }
+ if (doRemove) ikOffsets.Remove(jointAddr);
+ ImGui.PopID();
+ }
+#endif
+ if (!hasRotation)
+ {
+ if (ImGui.Button("Add Rotation"))
+ {
+ rotations.Add(jointAddr, rotation);
+ }
+ }
+ if (!hasOffset)
+ {
+ if (!hasRotation)
+ {
+ ImGui.SameLine();
+ }
+ if (ImGui.Button("Add Offset"))
+ {
+ offsets.Add(jointAddr, new Vector3());
+ }
+ }
+#if QUARANTINED_FEATURES
+ if (ikJoints.Contains(jointAddr) && !hasIkOffset)
+ {
+ if (!hasOffset)
+ {
+ ImGui.SameLine();
+ }
+ if (ImGui.Button("Add IK Offset"))
+ {
+ ikOffsets.Add(jointAddr, new Vector3());
+ }
+ }
+#endif
+ ImGui.PopID();
+ }
+
+ private static void drawBodyJoint(nint jointAddr)
+ {
+ drawJoint(jointAddr, bodyRotations, bodyOffsets);
+ }
+
+ private static void drawFaceJoint(nint jointAddr)
+ {
+ drawJoint(jointAddr, faceRotations, faceOffsets);
+ }
+
+ private static void drawJointLeaf(ref List<nint> joints, int i, Dictionary<nint, Vector4> rotations, Dictionary<nint, Vector3> offsets)
+ {
+ if (i >= joints.Count) return;
+ nint jointAddr = joints[i];
+ byte id = MemoryUtil.Read<byte>(jointAddr + 0xA0);
+ ImGui.PushID(jointAddr);
+ if (ImGui.CollapsingHeader($"Joint #{i} (0x{jointAddr:X}, id: 0x{id:X})"))
+ {
+ drawJoint(jointAddr, rotations, offsets);
+ }
+ ImGui.PopID();
+ drawJointLeaf(ref joints, i + 1, rotations, offsets);
+ }
+
+ private static void drawBodyJoints()
+ {
+ ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.Framed;
+ bool expanded;
+ if (ImGui.TreeNodeEx("Root", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.Root2]);
+ ImGui.TreePop();
+ }
+ ImGui.PushID("Neck");
+ if (ImGui.TreeNodeEx("Neck", flags))
+ {
+ if (ImGui.TreeNodeEx("Upper", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.UpperNeck]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Lower", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LowerNeck]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Neck.
+ ImGui.PushID("Back");
+ if (ImGui.TreeNodeEx("Back", flags))
+ {
+ if (ImGui.TreeNodeEx("Upper", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.UpperBack]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Lower", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LowerBack]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Back.
+ ImGui.PushID("Right Arm");
+ if (ImGui.TreeNodeEx("Right Arm", flags))
+ {
+ if (ImGui.TreeNodeEx("Collarbone", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightCollarbone]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Shoulder", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightShoulder]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Elbow", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightElbow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Wrist", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightWrist]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Right Arm.
+ ImGui.PushID("Right Hand");
+ if (ImGui.TreeNodeEx("Right Hand", flags))
+ {
+ ImGui.PushID("Thumb");
+ if (ImGui.TreeNodeEx("Thumb", flags))
+ {
+ if (ImGui.TreeNodeEx("Base", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightThumbLow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightThumbMid]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Tip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightThumbHigh]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID();
+ ImGui.PushID("Index");
+ if (ImGui.TreeNodeEx("Index", flags))
+ {
+ if (ImGui.TreeNodeEx("Base", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightIndexLow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightIndexMid]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Tip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightIndexHigh]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID();
+ ImGui.PushID("Middle");
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ if (ImGui.TreeNodeEx("Base", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightMiddleLow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightMiddleMid]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Tip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightMiddleHigh]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID();
+ ImGui.PushID("Ring");
+ if (ImGui.TreeNodeEx("Ring", flags))
+ {
+ if (ImGui.TreeNodeEx("Base", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightRingLow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightRingMid]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Tip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightRingHigh]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID();
+ ImGui.PushID("Pinky");
+ if (ImGui.TreeNodeEx("Pinky", flags))
+ {
+ if (ImGui.TreeNodeEx("Base", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightPinkyLow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightPinkyMid]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Tip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightPinkyHigh]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID();
+ expanded = ImGui.TreeNodeEx("Palm", flags);
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("Outer Palm/Pinky+Ring");
+ ImGui.EndTooltip();
+ }
+ if (expanded)
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightPalm]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Right Hand.
+ ImGui.PushID("Right Leg");
+ if (ImGui.TreeNodeEx("Right Leg", flags))
+ {
+ if (ImGui.TreeNodeEx("Hip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightHip]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Knee", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightKnee]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Ankle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightAnkle]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Toes", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.RightToes]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Right Leg.
+ ImGui.PushID("Left Arm");
+ if (ImGui.TreeNodeEx("Left Arm", flags))
+ {
+ if (ImGui.TreeNodeEx("Collarbone", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftCollarbone]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Shoulder", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftShoulder]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Elbow", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftElbow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Wrist", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftWrist]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Left Arm.
+ ImGui.PushID("Left Hand");
+ if (ImGui.TreeNodeEx("Left Hand", flags))
+ {
+ ImGui.PushID("Thumb");
+ if (ImGui.TreeNodeEx("Thumb", flags))
+ {
+ if (ImGui.TreeNodeEx("Base", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftThumbLow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftThumbMid]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Tip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftThumbHigh]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID();
+ ImGui.PushID("Index");
+ if (ImGui.TreeNodeEx("Index", flags))
+ {
+ if (ImGui.TreeNodeEx("Base", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftIndexLow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftIndexMid]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Tip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftIndexHigh]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID();
+ ImGui.PushID("Middle");
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ if (ImGui.TreeNodeEx("Base", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftMiddleLow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftMiddleMid]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Tip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftMiddleHigh]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID();
+ ImGui.PushID("Ring");
+ if (ImGui.TreeNodeEx("Ring", flags))
+ {
+ if (ImGui.TreeNodeEx("Base", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftRingLow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftRingMid]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Tip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftRingHigh]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID();
+ ImGui.PushID("Pinky");
+ if (ImGui.TreeNodeEx("Pinky", flags))
+ {
+ if (ImGui.TreeNodeEx("Base", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftPinkyLow]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftPinkyMid]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Tip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftPinkyHigh]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID();
+ expanded = ImGui.TreeNodeEx("Palm", flags);
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("Outer Palm/Pinky+Ring");
+ ImGui.EndTooltip();
+ }
+ if (expanded)
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftPalm]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Left Hand.
+ ImGui.PushID("Left Leg");
+ if (ImGui.TreeNodeEx("Left Leg", flags))
+ {
+ if (ImGui.TreeNodeEx("Hip", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftHip]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Knee", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftKnee]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Ankle", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftAnkle]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Toes", flags))
+ {
+ drawBodyJoint(bodyJointMap[Joint.LeftToes]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Left Leg.
+ }
+
+ private static void drawFaceJoints()
+ {
+ ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.Framed;
+ ImGui.PushID("Lips");
+ if (ImGui.TreeNodeEx("Lips", flags))
+ {
+ if (ImGui.TreeNodeEx("Right Edge", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth2]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Lower 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth3]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Lower 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth4]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Upper 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth29]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Upper 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth28]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Edge", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth1]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Lower 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth7]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Lower 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth6]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Upper 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth25]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Upper 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth26]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle Lower", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth5]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle Upper", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth27]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Lips.
+ ImGui.PushID("Mouth");
+ if (ImGui.TreeNodeEx("Mouth", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth]);
+ if (ImGui.TreeNodeEx("Bottom Teeth", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth30]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Lower 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth12]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Lower 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth11]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Upper 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth24]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Upper 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth23]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Lower 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth8]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Lower 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth9]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Upper 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth20]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Upper 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth21]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle Lower", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth10]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle Upper", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth22]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Under", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth15]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Under", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth14]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Middle Under", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth13]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Cheek 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth17]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Cheek 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth19]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Cheek 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth16]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Cheek 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Mouth18]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Mouth.
+ ImGui.PushID("Cheeks");
+ if (ImGui.TreeNodeEx("Cheeks", flags))
+ {
+ if (ImGui.TreeNodeEx("Right Cheek", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightCheek]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Cheek 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightCheek1]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Cheek 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightCheek2]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Cheek 3", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightCheek3]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Cheek 4", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightCheek4]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Right Cheek 5", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightCheek5]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Cheek", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftCheek]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Cheek 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftCheek1]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Cheek 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftCheek2]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Cheek 3", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftCheek3]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Cheek 4", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftCheek4]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Left Cheek 5", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftCheek5]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Cheeks.
+ ImGui.PushID("Right Eye");
+ if (ImGui.TreeNodeEx("Right Eye", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye]);
+ if (ImGui.TreeNodeEx("Eyeball", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye1]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Outer", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye2]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye3]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye4]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid 3", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye5]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Inner", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye6]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Lower 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye7]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Lower 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye8]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Lower 3", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye9]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Top 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye10]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Top 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye11]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Top 3", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye12]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Under Eye", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.RightEye13]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Right Eye.
+ ImGui.PushID("Left Eye");
+ if (ImGui.TreeNodeEx("Left Eye", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye]);
+ if (ImGui.TreeNodeEx("Eyeball", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye1]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Outer", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye2]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye3]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye4]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid 3", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye5]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Inner", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye6]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Lower 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye7]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Lower 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye8]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Lower 3", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye9]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Top 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye10]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Top 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye11]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Eyelid Top 3", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye12]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Under Eye", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.LeftEye13]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Left Eye.
+ ImGui.PushID("Chin");
+ if (ImGui.TreeNodeEx("Chin", flags))
+ {
+ if (ImGui.TreeNodeEx("Chin Right", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.ChinRight]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Chin Right Back", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.ChinRightBack]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Chin Middle", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.ChinMiddle]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Chin Left", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.ChinLeft]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Chin Left Back", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.ChinLeftBack]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Neck Right", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.NeckRight]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Neck Middle", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.NeckMiddle]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Neck Left", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.NeckLeft]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Jaw", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Jaw]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Jaw Right", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.JawRight]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Jaw Up Right", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.JawUpRight]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Jaw Left", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.JawLeft]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Jaw Up Left", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.JawUpLeft]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Chin.
+ ImGui.PushID("Brow");
+ if (ImGui.TreeNodeEx("Brow", flags))
+ {
+ if (ImGui.TreeNodeEx("Brow 0", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead0]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead1]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead2]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 3", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead3]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 4", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead4]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 5", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead5]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 6", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead6]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 7", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead7]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 8", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead8]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 9", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead9]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 10", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead10]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 11", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead11]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 12", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead12]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 13", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead13]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Brow 14", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Forehead14]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Brow.
+ ImGui.PushID("Nose");
+ if (ImGui.TreeNodeEx("Nose", flags))
+ {
+ if (ImGui.TreeNodeEx("Nose", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 1", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose1]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 2", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose2]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 3", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose3]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 4", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose4]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 5", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose5]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 6", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose6]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 7", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose7]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 8", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose8]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 9", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose9]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 10", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose10]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 11", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose11]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 12", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose12]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 13", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose13]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 14", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose14]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 15", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose15]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 16", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose16]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 17", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose17]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 18", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose18]);
+ ImGui.TreePop();
+ }
+ if (ImGui.TreeNodeEx("Nose 19", flags))
+ {
+ drawFaceJoint(faceJointMap[FaceJoint.Nose19]);
+ ImGui.TreePop();
+ }
+ ImGui.TreePop();
+ }
+ ImGui.PopID(); // Nose.
+ }
+
+ private static string typedPoseName = "";
+ private static string selectedPoseName = "";
+ private static string[] poseList = [];
+ private static bool poseSelectionStarted = false;
+
+ private static float StringToSingle(string s) { return Convert.ToSingle(s, CultureInfo.InvariantCulture); }
+
+ public static Vector3 StringToVector3(string s, char delim = ',')
+ {
+ if (String.IsNullOrEmpty(s)) throw new FormatException();
+ string[] sp = s.Split(delim).Select((v) => v.Trim()).ToArray();
+ if (sp.Length != 3) throw new FormatException();
+ return new Vector3(StringToSingle(sp[0]), StringToSingle(sp[1]), StringToSingle(sp[2]));
+ }
+
+ public static Vector4 StringToVector4(string s, char delim = ',')
+ {
+ if (String.IsNullOrEmpty(s)) throw new FormatException();
+ string[] sp = s.Split(delim).Select((v) => v.Trim()).ToArray();
+ if (sp.Length != 4) throw new FormatException();
+ return new Vector4(StringToSingle(sp[0]), StringToSingle(sp[1]), StringToSingle(sp[2]), StringToSingle(sp[3]));
+ }
+
+ private static string Vector3ToString(Vector3 v)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", v.X, v.Y, v.Z);
+ }
+
+ private static string Vector4ToString(Vector4 v)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0},{1},{2},{3}", v.X, v.Y, v.Z, v.W);
+ }
+
+ public static bool overlayJoints = false;
+
+ public static void DrawUI(float width, Player player)
+ {
+ bool armorStateRefreshed = false;
+
+ ImGui.PushID("Joints");
+ if (ImGui.CollapsingHeader("Joints"))
+ {
+ if (!armorStateRefreshed)
+ {
+ refreshArmorState(player);
+ armorStateRefreshed = true;
+ }
+ ImGui.Checkbox("Overlay Joints", ref overlayJoints);
+ ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f));
+#if QUARANTINED_FEATURES
+ ImGui.Text($"Rotations: {bodyRotations.Count + faceRotations.Count}, Positions: {bodyPositions.Count + facePositions.Count}, Offsets: {bodyOffsets.Count + faceOffsets.Count + ikOffsets.Count}");
+#else
+ ImGui.Text($"Rotations: {bodyRotations.Count + faceRotations.Count}, Positions: {bodyPositions.Count + facePositions.Count}, Offsets: {bodyOffsets.Count + faceOffsets.Count}");
+#endif
+ ImGui.SameLine();
+ ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f));
+ if (ImGui.Button("Clear"))
+ {
+ dropJointOffsets();
+ }
+ /*
+ ref byte ikDisabledB = ref MemoryUtil.GetRef<byte>(MemoryUtil.Read<nint>(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("Disable IK", ref ikForcedOff))
+ {
+ if (ikForcedOff)
+ {
+ forceDisableIK.Enable();
+ }
+ else
+ {
+ forceDisableIK.Disable();
+ }
+ }
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("Forcefully disable inverse kinematics.");
+ ImGui.EndTooltip();
+ }
+ ImGui.SameLine();
+ ref byte lookAtDisabledB = ref MemoryUtil.GetRef<byte>(MemoryUtil.Read<nint>(player.Instance + 0x9C0) + 0x5C);
+ bool lookAtDisabled = lookAtDisabledB == 0x0;
+ if (ImGui.Checkbox("Disable Look At", ref lookAtDisabled))
+ {
+ lookAtDisabledB = ByteFlag(!lookAtDisabled);
+ }
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("Stop your character from looking at people, animals, and objects they pass.");
+ ImGui.EndTooltip();
+ }
+
+ ImGui.PushItemWidth(width * 0.3f);
+ ImGui.InputText("##Pose Name", ref typedPoseName, 99);
+ ImGui.SameLine();
+ if (ImGui.Button("Save"))
+ {
+ string name = typedPoseName;
+ if (name != "")
+ {
+ if (!Directory.Exists(posePath))
+ {
+ Directory.CreateDirectory(posePath);
+ }
+ string filename = name + ".json";
+ string path = Path.Join(posePath, filename);
+ using (FileStream stream = File.Open(path, FileMode.Create))
+ {
+ using (Utf8JsonWriter writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true }))
+ {
+ Vector3 rootPosition = player.Position;
+ Quaternion rootRotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W);
+ Vector3 rootForward = Vector3.Transform(new Vector3(0.0f, 0.0f, 1.0f), rootRotation);
+ Vector3 rootRight = Vector3.Transform(new Vector3(1.0f, 0.0f, 0.0f), rootRotation);
+ Vector3 rootUp = new Vector3(0.0f, 1.0f, 0.0f);
+ writer.WriteStartObject();
+ writer.WriteStartObject("body");
+ foreach (nint jointAddr in bodyJoints)
+ {
+ byte id = MemoryUtil.Read<byte>(jointAddr + 0xA0);
+ writer.WritePropertyName($"{id}");
+ writer.WriteStartArray();
+ writer.WriteStringValue(Vector4ToString(MemoryUtil.GetRef<Vector4>(jointAddr + 0x70)));
+ Vector3 positionOffset = default;
+ Vector3 position = MemoryUtil.GetRef<Vector3>(jointAddr + 0x50);
+ Vector3 diff = position - rootPosition;
+ positionOffset.Y = diff.Y;
+ diff.Y = 0.0f;
+ positionOffset.X = Vector3.Dot(rootForward, diff);
+ positionOffset.Z = Vector3.Dot(rootRight, diff);
+ writer.WriteStringValue(Vector3ToString(positionOffset));
+ if (bodyOffsets.ContainsKey(jointAddr))
+ {
+ writer.WriteStringValue(Vector3ToString(bodyOffsets[jointAddr]));
+ }
+ writer.WriteEndArray();
+ }
+ writer.WriteEndObject();
+ writer.WriteStartObject("face");
+ foreach (nint jointAddr in faceJoints)
+ {
+ byte id = MemoryUtil.Read<byte>(jointAddr + 0xA0);
+ writer.WritePropertyName($"{id}");
+ writer.WriteStartArray();
+ writer.WriteStringValue(Vector4ToString(MemoryUtil.GetRef<Vector4>(jointAddr + 0x70)));
+ Vector3 positionOffset = default;
+ Vector3 position = MemoryUtil.GetRef<Vector3>(jointAddr + 0x50);
+ Vector3 diff = position - rootPosition;
+ positionOffset.Y = diff.Y;
+ diff.Y = 0.0f;
+ positionOffset.X = Vector3.Dot(rootForward, diff);
+ positionOffset.Z = Vector3.Dot(rootRight, diff);
+ writer.WriteStringValue(Vector3ToString(positionOffset));
+ if (faceOffsets.ContainsKey(jointAddr))
+ {
+ writer.WriteStringValue(Vector3ToString(faceOffsets[jointAddr]));
+ }
+ writer.WriteEndArray();
+ }
+ writer.WriteEndObject();
+ writer.WriteEndObject();
+ writer.Flush();
+ }
+ }
+ }
+ }
+ ImGui.SameLine();
+ if (ImGui.BeginCombo("##Poses", selectedPoseName, ImGuiComboFlags.HeightLarge))
+ {
+ if (!poseSelectionStarted)
+ {
+ poseList = Directory.GetFiles(posePath);
+ poseSelectionStarted = true;
+ }
+ foreach (string filePath in poseList)
+ {
+ if (Path.GetExtension(filePath) != ".json")
+ {
+ continue;
+ }
+ string fileName = Path.GetFileNameWithoutExtension(filePath);
+ bool isSelected = fileName == selectedPoseName;
+ if (ImGui.Selectable(fileName, isSelected))
+ {
+ dropJointOffsets();
+ selectedPoseName = fileName;
+ Utf8JsonReader reader = new Utf8JsonReader(File.ReadAllBytes(filePath));
+ bool isFace = false;
+ byte currentId = 0xFF;
+ int arrayIndex = 0;
+ while (reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonTokenType.PropertyName:
+ string property = reader.GetString()!;
+ if (property == "body")
+ {
+ isFace = false;
+ }
+ else if (property == "face")
+ {
+ isFace = true;
+ }
+ else
+ {
+ try
+ {
+ currentId = Convert.ToByte(property);
+ }
+ catch (FormatException)
+ {
+ currentId = 0xFF;
+ }
+ catch (OverflowException)
+ {
+ currentId = 0xFF;
+ }
+ }
+ break;
+ case JsonTokenType.StartArray:
+ arrayIndex = 0;
+ break;
+ case JsonTokenType.String:
+ if (currentId == 0xFF) break;
+ if (arrayIndex == 0)
+ {
+ if (isFace)
+ {
+ faceRotations[faceJointMap[currentId]] = StringToVector4(reader.GetString()!);
+ }
+ else
+ {
+ bodyRotations[bodyJointMap[currentId]] = StringToVector4(reader.GetString()!);
+ }
+ }
+ else if (arrayIndex == 1)
+ {
+ if (isFace)
+ {
+ facePositions[faceJointMap[currentId]] = StringToVector3(reader.GetString()!);
+ }
+ else
+ {
+ bodyPositions[bodyJointMap[currentId]] = StringToVector3(reader.GetString()!);
+ }
+ }
+ arrayIndex++;
+ break;
+ }
+ }
+ }
+ if (isSelected) ImGui.SetItemDefaultFocus();
+ }
+ ImGui.EndCombo();
+ }
+ else
+ {
+ poseSelectionStarted = false;
+ }
+ ImGui.SameLine();
+ if (ImGui.Button("Delete"))
+ {
+ if (selectedPoseName != "")
+ {
+ selectedPoseName = "";
+ }
+ }
+ ImGui.PopItemWidth();
+
+ ImGui.PushItemWidth(width * 0.75f);
+ drawBodyJoints();
+ ImGui.Separator();
+ if (ImGui.CollapsingHeader("Face"))
+ {
+ drawFaceJoints();
+ ImGui.Separator();
+ }
+ if (ImGui.CollapsingHeader("Jiggle Bones"))
+ {
+ for (int i = 0; i < jiggleBones.Count; i++)
+ {
+ nint jiggleData = jiggleBones[i];
+ ImGui.PushID(jiggleData);
+ if (ImGui.CollapsingHeader($"Jiggle Bone #{i} (0x{jiggleData:X})"))
+ {
+ ImGui.DragFloat3("Position", ref MemoryUtil.GetRef<Vector3>(jiggleData + 0xD0), 0.05f);
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("Drag this position around to influence the bone.");
+ ImGui.EndTooltip();
+ }
+ }
+ ImGui.PopID();
+ }
+ }
+ ImGui.Separator();
+ if (ImGui.CollapsingHeader("All Joints"))
+ {
+ if (ImGui.CollapsingHeader("Body Joints"))
+ {
+ drawJointLeaf(ref bodyJoints, 0, bodyRotations, bodyOffsets);
+ }
+ if (ImGui.CollapsingHeader("Face Joints"))
+ {
+ drawJointLeaf(ref faceJoints, 0, faceRotations, faceOffsets);
+ }
+ }
+ ImGui.PopItemWidth();
+ ImGui.Separator();
+ }
+ ImGui.PopID();
+
+ ImGui.PushID("Parts");
+ if (ImGui.CollapsingHeader("Armor Parts"))
+ {
+ if (!armorStateRefreshed)
+ {
+ refreshArmorState(player);
+ armorStateRefreshed = true;
+ }
+ bool expaned = ImGui.CollapsingHeader("Helmet");
+ ImGui.SameLine();
+ ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x1373C):X})");
+ if (expaned)
+ {
+ Models.drawModelParts(playerArmor[Armor.Helmet]);
+ ImGui.Separator();
+ }
+ expaned = ImGui.CollapsingHeader("Body");
+ ImGui.SameLine();
+ ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x13740):X})");
+ if (expaned)
+ {
+ Models.drawModelParts(playerArmor[Armor.Body]);
+ ImGui.Separator();
+ }
+ expaned = ImGui.CollapsingHeader("Arms");
+ ImGui.SameLine();
+ ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x13744):X})");
+ if (expaned)
+ {
+ Models.drawModelParts(playerArmor[Armor.Arm]);
+ ImGui.Separator();
+ }
+ expaned = ImGui.CollapsingHeader("Waist");
+ ImGui.SameLine();
+ ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x13748):X})");
+ if (expaned)
+ {
+ Models.drawModelParts(playerArmor[Armor.Waist]);
+ ImGui.Separator();
+ }
+ expaned = ImGui.CollapsingHeader("Legs");
+ ImGui.SameLine();
+ ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x1374C):X})");
+ if (expaned)
+ {
+ Models.drawModelParts(playerArmor[Armor.Leg]);
+ ImGui.Separator();
+ }
+ expaned = ImGui.CollapsingHeader("Slinger");
+ ImGui.SameLine();
+ ImGui.Text($"(id: {MemoryUtil.Read<int>(player.Instance + 0x13D8C):X}_{MemoryUtil.Read<int>(player.Instance + 0x13D90):X})");
+ if (expaned)
+ {
+ Models.drawModelParts(playerArmor[Armor.Slinger]);
+ ImGui.Separator();
+ }
+ if (ImGui.CollapsingHeader("Hair"))
+ {
+ Models.drawModelParts(playerArmor[Armor.Hair]);
+ ImGui.Separator();
+ }
+ if (ImGui.CollapsingHeader("Face"))
+ {
+ Models.drawModelParts(playerArmor[Armor.Face]);
+ ImGui.Separator();
+ }
+ if (ImGui.CollapsingHeader("Eye Lens"))
+ {
+ Models.drawModelParts(playerArmor[Armor.EyeLens]);
+ }
+ ImGui.Separator();
+ }
+ if (ImGui.CollapsingHeader("Weapon Parts"))
+ {
+ bool expaned = ImGui.CollapsingHeader("Weapon");
+ if (expaned)
+ {
+ foreach (nint weaponPart in playerWeapon)
+ {
+ Models.drawModelParts(weaponPart);
+ ImGui.Separator();
+ }
+ }
+ }
+ ImGui.PopID();
+ }
+
+ public static void OnRender()
+ {
+ if (overlayJoints)
+ {
+ for (int i = 0; i < faceJoints.Count; i++)
+ {
+ nint jointAddr = faceJoints[i];
+ ref Vector3 position = ref MemoryUtil.GetRef<Vector3>(jointAddr + 0x50);
+ Primitives.RenderSphere(position, 0.1f, new MtColor(255, 0, 0, 255));
+ }
+ }
+ }
+ }
+}