From 377858fd543439558f7980ba5ca17a0ce690c038 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Wed, 3 Jun 2026 16:41:18 -0400 Subject: Massively improve model part toggling Signed-off-by: Andrew Opalach --- Config.cs | 4 +- Plugin.cs | 339 +++++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 203 insertions(+), 140 deletions(-) diff --git a/Config.cs b/Config.cs index fb3d0a5..07e3cf4 100755 --- a/Config.cs +++ b/Config.cs @@ -8,7 +8,7 @@ namespace NewCamera internal class Config : IConfig { public String Name => "NewCamera"; - public String Version => "4.0"; + public String Version => "4.1"; public const float DEFAULT_FOV = 60.0f; public const float DEFAULT_NEAR_CLIP = 16.0f; @@ -138,7 +138,7 @@ namespace NewCamera } public bool DisableMod { get; set; } = false; - public bool TuningToolInterop { get; set; } = true; + public bool TuningToolInterop = true; public bool OverrideViewMode { get; set; } = false; public Settings Camera { get; set; } = new Settings(); diff --git a/Plugin.cs b/Plugin.cs index 9220b3b..7f88d07 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -1,4 +1,4 @@ -//#define ENABLE_ASSERTS +#define ENABLE_ASSERTS //#define HOOK_ORDER_ASSERTS //#define LOG_DEBUG_MESSAGES #define MOUSE_AND_KEYBOARD_LAYER @@ -48,11 +48,11 @@ using SharpPluginLoader.Core.Configuration; // - Open Poses Menu // @TODO: -// - Pass on ImGui flicker. // - Cleanup math. // - pCamera refactor. // - Attempt to document all test cases I can think of. // - Centralize all bindings to get a better idea of how to structure custom binds. +// - Pass on ImGui flicker. // - WASD for ignore camera direction. // - Make audio like waterfall follow camera position instead of player position. // - Audio high/lowpass possible? @@ -79,6 +79,7 @@ using SharpPluginLoader.Core.Configuration; // - Better name for unknownPtr. // Known Issues: +// - Camera up not respecting collision can badly bug out culling. // - Camera pitch wrap around while in the tent will sometimes flicker at the point of wrapping. // - Likely due to the unpredictable position of SetCameraTentHook() in the chain of hooks. Updating // free camera state within SetCameraTentHook() is not a solution because it comes out laggy. @@ -296,6 +297,7 @@ namespace NewCamera private string modelFilter = ""; private bool modelFilterIsRegex = false; private Regex? modelRegex = null; + private bool modelOnlyAddressLod0 = false; private delegate void ProcessCameraDelegate(nint cameraPointer); private Hook? setCameraHook; @@ -401,7 +403,7 @@ namespace NewCamera } private bool hideWeapon = false; private bool hideKnife = false; - private bool hideSlinger = false; + private bool checkKnifeHidden = false; private static class Armor { @@ -410,9 +412,11 @@ namespace NewCamera public const byte Arm = 2; public const byte Waist = 3; public const byte Leg = 4; - public const byte Face = 5; - public const byte EyeLens = 6; + 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; } private static class Joint @@ -505,7 +509,7 @@ namespace NewCamera public const byte Unknown11 = 85; } - private nint[] playerArmor = new nint[8]; + private nint[] playerArmor = new nint[10]; private nint[] playerJoints = new nint[86]; private delegate void UpdateJoints(nint obj); @@ -979,12 +983,12 @@ namespace NewCamera MemoryUtil.GetRef(vp.Instance + 0x21) = ByteFlag(enable); } - private bool getPassthroughEnabled() + private static bool getPassthroughEnabled() { return MemoryUtil.Read(sMhScene.Instance + 0xE9A0) == 0x1; } - private void setPassthroughEnabled(bool enable) + private static void setPassthroughEnabled(bool enable) { MemoryUtil.GetRef(sMhScene.Instance + 0xE9A0) = ByteFlag(enable); } @@ -1045,6 +1049,7 @@ namespace NewCamera { setPerspectivePreset(config.Presets[config.Selected]); } +#if QUARANTINED_FEATURES if (config.TuningToolInterop) { if (TuningToolInterop.InitFromLoadedInstance()) @@ -1056,6 +1061,7 @@ namespace NewCamera Log.Warn($"Couldn't find loaded '{TuningToolInterop.PluginName}' instance, features will be missing"); } } +#endif } private void toggleUi() @@ -1315,6 +1321,7 @@ namespace NewCamera player = getPlayerWithFallback(); if (player != null) { + // @TODO: Comment this. if (hideWeapon) { nint baseAddr = MemoryUtil.Read(player.Instance + 0x76B0); @@ -1332,6 +1339,7 @@ namespace NewCamera } } } + /* if (hideKnife) { // Emulate what Carving and Flourish emote do at @@ -1341,17 +1349,7 @@ namespace NewCamera MemoryUtil.GetRef(player.Instance + 0x8938) |= (1 << 6); MemoryUtil.GetRef(player.Instance + 0x8968) |= (1 << 6); } - nint slinger = MemoryUtil.Read(player.Instance + 0x8918); - if (slinger != 0x0) - { - ref byte sVisible = ref MemoryUtil.GetRef(slinger + 0x18); - ref byte sSub = ref MemoryUtil.GetRef(slinger + 0x19); - bool slingerHidden = sVisible == 0x0; - if (hideSlinger != slingerHidden) - { - (sVisible, sSub) = (sSub, sVisible); - } - } + */ } resetStatePerFrame(); @@ -2629,6 +2627,10 @@ namespace NewCamera { partName = fullString.Split('\\')[3]; } + else if (fullString.StartsWith("wp\\")) + { + partName = fullString.Split('\\')[2]; + } else if (fullString.StartsWith("pl\\hair")) { partName = fullString.Split('\\')[2]; @@ -2637,42 +2639,27 @@ namespace NewCamera { partName = fullString.Split('\\')[4].Substring(2); } - else if (fullString.StartsWith("wp\\slg")) - { - partName = "slinger"; - } - else if (fullString.StartsWith("accessory\\acc")) - { - partName = fullString.Split('\\')[1]; - } - else if (fullString.StartsWith("npc\\npc")) - { - partName = "npc"; - } return partName; } private void collectArmorParts(nint baseAddr, nint addr) { int part; - string partName = extractPartName(Marshal.PtrToStringAnsi(addr + 0xC)!); + 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 if (partName.StartsWith("hair")) part = Armor.Hair; else return; playerArmor[part] = baseAddr; - if (part == Armor.Body) - { - chestBone1 = 0x0; - chestBone2 = 0x0; - } - int jointCount = MemoryUtil.Read(baseAddr + 0x4A0); nint jointAddr = MemoryUtil.Read(baseAddr + 0x4A8); for (int i = 0; i < jointCount; i++) @@ -2704,7 +2691,7 @@ namespace NewCamera jiggleBones.Add(jiggleData); if (part == Armor.Body) { - // Guess that chest bones are the last jiggle bones. + // Guess that chest bones are the last jiggle bones on the body. if (chestBone1 == 0x0) { chestBone1 = jiggleData; @@ -2744,10 +2731,12 @@ namespace NewCamera { bodyJoints.Add(jointAddr); } + /* else if (part == Armor.Face) { faceJoints.Add(jointAddr); } + */ jointAddr += 0xC0; } if (part == Armor.Body) @@ -2893,6 +2882,7 @@ namespace NewCamera { ImGui.PushItemWidth(width * 0.75f); ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.Framed; + bool expanded; if (ImGui.TreeNodeEx("Root", flags)) { drawJoint(playerJoints[Joint.Root2]); @@ -3064,16 +3054,17 @@ namespace NewCamera ImGui.TreePop(); } ImGui.PopID(); - if (ImGui.TreeNodeEx("Palm", flags)) - { - drawJoint(playerJoints[Joint.RightPalm]); - ImGui.TreePop(); - } + 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. @@ -3237,16 +3228,17 @@ namespace NewCamera ImGui.TreePop(); } ImGui.PopID(); - if (ImGui.TreeNodeEx("Palm", flags)) - { - drawJoint(playerJoints[Joint.LeftPalm]); - ImGui.TreePop(); - } + 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. @@ -3290,7 +3282,7 @@ namespace NewCamera ImGui.SameLine(); ImGui.Checkbox("Swap Sides", ref swapChestSides); ImGui.SetNextItemWidth(width * 0.35f); - ImGui.DragFloat("Scale", ref chestMoveScale, 0.001f); + ImGui.DragFloat("Strength", ref chestMoveScale, 0.001f); if (!attachToChest) { ImGui.PopStyleVar(); @@ -3301,9 +3293,9 @@ namespace NewCamera { nint jiggleData = jiggleBones[i]; ImGui.PushID(jiggleData); - if (ImGui.CollapsingHeader($"Jiggle Bones #{i} (0x{jiggleData:X})")) + if (ImGui.CollapsingHeader($"Jiggle Bone #{i} (0x{jiggleData:X})")) { - ImGui.DragFloat3("Position", ref MemoryUtil.GetRef(jiggleData + 0xD0)); + ImGui.DragFloat3("Position", ref MemoryUtil.GetRef(jiggleData + 0xD0), 0.05f); if (ImGui.BeginItemTooltip()) { ImGui.Text("Drag this position around to influence the bone."); @@ -3321,7 +3313,7 @@ namespace NewCamera ImGui.PopItemWidth(); } - private void drawArmorParts(nint armorAddr, nint partsAddr = 0x0) + private void drawModelParts(nint armorAddr, nint partsAddr = 0x0) { if (partsAddr == 0x0) { @@ -3341,32 +3333,51 @@ namespace NewCamera { ImGui.Text($"{fullString} @ 0x{partsAddr:X}:"); } + // MonsterHunterWorld.exe+222E651 - mov rax,[r8+000000C8] + nint baseLod = MemoryUtil.Read(partsAddr + 0xC8); + nint baseOffset = MemoryUtil.Read(partsAddr + 0x408 + (0x8 * 0x1)); + int numParts = MemoryUtil.Read(partsAddr + 0x548 + (0x4 * 0x1)); + // Setting lodCount to 0 is probably the best way to completely hide a model. + int lodCount = MemoryUtil.Read(partsAddr + 0xD0); + const int lodStructSize = 0x50; const int partsPerLine = 10; - nint baseInner = MemoryUtil.Read(partsAddr + 0xC8); - nint baseOffset = MemoryUtil.Read(partsAddr + 0x408); - int numParts = MemoryUtil.Read(partsAddr + 0x54C); - bool toggleAll = ImGui.Button("Toggle All"); + bool allOn = ImGui.Button("All On"); + ImGui.SameLine(); + bool allOff = ImGui.Button("All Off"); for (int i = 0; i < numParts; i++) { - nint offset = baseOffset + (i * 0x4) + (numParts * 0x4); - ref byte bIndex = ref MemoryUtil.GetRef(offset); - offset = baseInner + ((bIndex + (bIndex * 4)) << 4); - ref byte bVisible = ref MemoryUtil.GetRef(offset); - ref byte bSub = ref MemoryUtil.GetRef(offset + 0xB); - if (toggleAll) - { - (bVisible, bSub) = (bSub, bVisible); - } - bool isVisible = bVisible != 0x0; - if (ImGui.Checkbox($"##Part #{i}", ref isVisible)) - { - (bVisible, bSub) = (bSub, bVisible); - } + ref int lodOffset = ref MemoryUtil.GetRef(baseOffset + (i * 0x4)); + nint lod0 = baseLod + lodOffset * lodStructSize; + bool isVisible = MemoryUtil.GetRef(lod0) != 0; + bool togglePart = ImGui.Checkbox($"##Part #{i}", ref isVisible); if (ImGui.BeginItemTooltip()) { - ImGui.Text($"Part #{i}"); + ImGui.Text($"Part #{i} (0x{lod0:X})"); ImGui.EndTooltip(); } + int lastLod = (i < numParts - 1) ? MemoryUtil.Read(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 padding. + // MonsterHunterWorld.exe+222FCE3 - mov eax,[r8] + ushort lod0Visible = MemoryUtil.GetRef(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(lod); + ref ushort padSub = ref MemoryUtil.GetRef(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(); @@ -3380,6 +3391,8 @@ namespace NewCamera Array.Clear(playerArmor, 0, playerArmor.Length); Array.Clear(playerJoints, 0, playerJoints.Length); bodyJoints.Clear(); + chestBone1 = 0x0; + chestBone2 = 0x0; ignoredJoints.Clear(); jiggleBones.Clear(); faceJoints.Clear(); @@ -3407,6 +3420,24 @@ namespace NewCamera return false; } collectArmorParts(player.Instance, bodyArmorParts); + nint weapon = MemoryUtil.Read(player.Instance + 0x76B0); + if (weapon != 0x0) + { + nint weaponParts = MemoryUtil.Read(weapon + 0x2A0); + if (weaponParts != 0x0) + { + collectArmorParts(weapon, weaponParts); + } + } + nint slinger = MemoryUtil.Read(player.Instance + 0x8918); + if (slinger != 0x0) + { + nint slingerParts = MemoryUtil.Read(slinger + 0x2A0); + if (slingerParts != 0x0) + { + collectArmorParts(slinger, slingerParts); + } + } combineArmorList = MemoryUtil.Read(combineArmorList + 0x70); nint next = combineArmorList; while (next != 0x0) @@ -3470,9 +3501,14 @@ namespace NewCamera } } + private bool usingArmorState() + { + return jointOffsets.Count > 0 || (hideKnife || checkKnifeHidden) || (enableFreeCamera && orbitPlayer && orbitJoint >= 0); + } + private void UpdateJointsHook(nint obj) { - if (!disableMod && !didJointOffset && (jointOffsets.Count > 0 || hideKnife || (enableFreeCamera && orbitPlayer && orbitJoint >= 0))) + if (!disableMod && !didJointOffset && usingArmorState()) { Player? player = getPlayerWithFallback(); if (player != null && obj == player.Instance) @@ -3486,6 +3522,7 @@ namespace NewCamera if (playerArmor[Armor.Waist] != 0x0) { MemoryUtil.GetRef(playerArmor[Armor.Waist] + 0x2D0) = hideKnife ? (byte)0xFD : (byte)0xFF; + checkKnifeHidden = false; } } } @@ -3495,7 +3532,7 @@ namespace NewCamera #if QUARANTINED_FEATURES private void UpdateIKHook(nint superOfChild, nint joint, nint obj) { - if (ikOffsets.ContainsKey(joint)) + if (!disableMod && ikOffsets.ContainsKey(joint)) { Vector3 offset = ikOffsets[joint][0]; MemoryUtil.GetRef(superOfChild + 0x1380) += offset; @@ -3618,7 +3655,6 @@ namespace NewCamera Camera camera = vp.Camera; bool usedByFreeCamera = freeCamera && enableFreeCamera && camera == vCamera; if (debug) ImGui.Text($"Camera Pointer: 0x{camera.Instance:X}"); - if (ImGui.DragFloat("Field of View", ref camera.FieldOfView, 0.1f)) { if (usedByFreeCamera) @@ -3743,30 +3779,30 @@ namespace NewCamera Player? player = checkPlayerChange(); if (!debug && player != null) { - ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 7.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f)); ImGui.Text("Camera Distance"); if (ImGui.BeginItemTooltip()) { ImGui.Text("To save this setting, save your game."); ImGui.EndTooltip(); } - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); ref byte settingB = ref MemoryUtil.GetRef(getPlayerSettings() + 0x1403FD); int settingI = settingB; ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); if (ImGui.RadioButton("Close", ref settingI, 0)) { settingB = (byte)settingI; } ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); if (ImGui.RadioButton("Default", ref settingI, 1)) { settingB = (byte)settingI; } ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); if (ImGui.RadioButton("Far", ref settingI, 2)) { settingB = (byte)settingI; @@ -3888,7 +3924,12 @@ namespace NewCamera } else { - ImGui.Text($" Current: {currentAnimation.Lmt}.{currentAnimation.Id}, Action: {(currentAction != null ? currentAction.Name : "None")}"); + 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"); } @@ -3897,6 +3938,7 @@ namespace NewCamera { animationLayer.Paused = animationPaused; } +#if QUARANTINED_FEATURES ImGui.SameLine(); float? lockedSpeed = animationLayer.LockedSpeed; float speed = lockedSpeed ?? animationLayer.Speed; @@ -3918,6 +3960,7 @@ namespace NewCamera { if (animationLocked) animationLayer.LockSpeed(speed); } +#endif } } @@ -4028,28 +4071,29 @@ namespace NewCamera ImGui.Checkbox("Hide Weapon", ref hideWeapon); ImGui.SameLine(); - ImGui.Checkbox("Hide Knife", ref hideKnife); - ImGui.SameLine(); - ImGui.Checkbox("Hide Slinger", ref hideSlinger); + if (ImGui.Checkbox("Hide Knife", ref hideKnife)) + { + checkKnifeHidden = true; + } ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f)); ImGui.Text("Head Armor Display"); // MonsterHunterWorld.exe+11A2967 - cmp byte ptr [rax+001403E1],01 ref byte showHeadArmor = ref MemoryUtil.GetRef(playerSettings + 0x1403E1); int showHeadArmorInt = showHeadArmor; ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); if (ImGui.RadioButton("Show", ref showHeadArmorInt, 0)) { showHeadArmor = (byte)showHeadArmorInt; } ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); if (ImGui.RadioButton("Hide", ref showHeadArmorInt, 1)) { showHeadArmor = (byte)showHeadArmorInt; } ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); if (ImGui.RadioButton("Hide in Cutscenes", ref showHeadArmorInt, 2)) { showHeadArmor = (byte)showHeadArmorInt; @@ -4099,7 +4143,7 @@ namespace NewCamera ImGui.Text($"Joint Offsets: {jointOffsets.Count}"); #endif ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); if (ImGui.Button("Clear")) { dropJointOffsets(); @@ -4109,63 +4153,75 @@ namespace NewCamera drawJoints(width); ImGui.Separator(); } - bool helmetExpaned = ImGui.CollapsingHeader("Helmet"); + bool expaned = ImGui.CollapsingHeader("Helmet"); ImGui.SameLine(); - ImGui.Text($"(id: 0x{MemoryUtil.Read(player.Instance + 0x1373C):X})"); - if (helmetExpaned) + ImGui.Text($"(id: {MemoryUtil.Read(player.Instance + 0x1373C):X})"); + if (expaned) { - drawArmorParts(playerArmor[Armor.Helmet]); + drawModelParts(playerArmor[Armor.Helmet]); ImGui.Separator(); } - bool bodyExpaned = ImGui.CollapsingHeader("Body"); + expaned = ImGui.CollapsingHeader("Body"); ImGui.SameLine(); - ImGui.Text($"(id: 0x{MemoryUtil.Read(player.Instance + 0x13740):X})"); - if (bodyExpaned) + ImGui.Text($"(id: {MemoryUtil.Read(player.Instance + 0x13740):X})"); + if (expaned) { - drawArmorParts(playerArmor[Armor.Body]); + drawModelParts(playerArmor[Armor.Body]); ImGui.Separator(); } - bool armsExpaned = ImGui.CollapsingHeader("Arms"); + expaned = ImGui.CollapsingHeader("Arms"); ImGui.SameLine(); - ImGui.Text($"(id: 0x{MemoryUtil.Read(player.Instance + 0x13744):X})"); - if (armsExpaned) + ImGui.Text($"(id: {MemoryUtil.Read(player.Instance + 0x13744):X})"); + if (expaned) { - drawArmorParts(playerArmor[Armor.Arm]); + drawModelParts(playerArmor[Armor.Arm]); ImGui.Separator(); } - bool waistExpaned = ImGui.CollapsingHeader("Waist"); + expaned = ImGui.CollapsingHeader("Waist"); ImGui.SameLine(); - ImGui.Text($"(id: 0x{MemoryUtil.Read(player.Instance + 0x13748):X})"); - if (waistExpaned) + ImGui.Text($"(id: {MemoryUtil.Read(player.Instance + 0x13748):X})"); + if (expaned) { - drawArmorParts(playerArmor[Armor.Waist]); + drawModelParts(playerArmor[Armor.Waist]); ImGui.Separator(); } - bool legsExpaned = ImGui.CollapsingHeader("Legs"); + expaned = ImGui.CollapsingHeader("Legs"); ImGui.SameLine(); - ImGui.Text($"(id: 0x{MemoryUtil.Read(player.Instance + 0x1374C):X})"); - if (legsExpaned) + ImGui.Text($"(id: {MemoryUtil.Read(player.Instance + 0x1374C):X})"); + if (expaned) { - drawArmorParts(playerArmor[Armor.Leg]); + drawModelParts(playerArmor[Armor.Leg]); ImGui.Separator(); } - ImGui.Text($"Slinger: 0x{MemoryUtil.Read(player.Instance + 0x13D8C):X}, 0x{MemoryUtil.Read(player.Instance + 0x13D90):X}"); /* - ImGui.Text($"Last Equipped: 0x{lastEquipedId:X}"); - */ - if (ImGui.CollapsingHeader("Face")) + expaned = ImGui.CollapsingHeader("Weapon"); + if (expaned) { - drawArmorParts(playerArmor[Armor.Face]); + drawModelParts(playerArmor[Armor.Weapon]); ImGui.Separator(); } - if (ImGui.CollapsingHeader("Eye Lens")) + */ + expaned = ImGui.CollapsingHeader("Slinger"); + ImGui.SameLine(); + ImGui.Text($"(id: {MemoryUtil.Read(player.Instance + 0x13D8C):X}_{MemoryUtil.Read(player.Instance + 0x13D90):X})"); + if (expaned) { - drawArmorParts(playerArmor[Armor.EyeLens]); + drawModelParts(playerArmor[Armor.Slinger]); ImGui.Separator(); } if (ImGui.CollapsingHeader("Hair")) { - drawArmorParts(playerArmor[Armor.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(); } @@ -4210,13 +4266,13 @@ namespace NewCamera ImGui.EndTooltip(); } ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); ImGui.RadioButton("Off", ref zoneStateInt, 0); ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); ImGui.RadioButton("Hub", ref zoneStateInt, 1); ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 6.0f)); ImGui.RadioButton("Combat", ref zoneStateInt, 2); forceZoneState = (ZoneState)zoneStateInt; if (ImGui.Button("Run Change Zone State")) @@ -5055,20 +5111,6 @@ namespace NewCamera ImGui.TableSetColumnIndex(1); ImGui.Text("Open Poses Menu"); - /* - ImGui.TableNextRow(); - ImGui.TableSetColumnIndex(0); - ImGui.Text(" + Press B"); - ImGui.TableSetColumnIndex(1); - ImGui.Text("Toggle Depth of Field"); - - ImGui.TableNextRow(); - ImGui.TableSetColumnIndex(0); - ImGui.Text(" + Press A"); - ImGui.TableSetColumnIndex(1); - ImGui.Text("Toggle SSAO"); - */ - ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text(" + Press X"); @@ -5124,6 +5166,7 @@ namespace NewCamera config.Binds = binds; ConfigManager.SaveConfig(this); } + ImGui.SameLine(); if (ImGui.DragFloat("Mouse Sensitivity", ref mouseSensitivity, 0.001f, 0.0f, 0.0f, "%.4f")) { Config.Settings.Binds binds = config.Binds; @@ -5138,6 +5181,7 @@ namespace NewCamera config.Binds = binds; ConfigManager.SaveConfig(this); } + ImGui.SameLine(); if (ImGui.DragInt("Keyboard Look Sensitivity", ref keyboardLookValue, 20, 0, Int16.MaxValue)) { Config.Settings.Binds binds = config.Binds; @@ -5440,7 +5484,7 @@ namespace NewCamera { Animal animal = animals[i]; ImGui.PushID(animal.Instance); - ImGui.Text($"0x{animal.Id:X} (0x{animal.OtherId:X}):"); + 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 @@ -5459,7 +5503,12 @@ namespace NewCamera { ImGui.Text("Filter"); bool updateRegex = false; - ImGui.SetNextItemWidth(width * 0.6f); + 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) @@ -5467,6 +5516,19 @@ namespace NewCamera 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)) { @@ -5518,7 +5580,7 @@ namespace NewCamera } if (filterMatch) { - drawArmorParts(0x0, partsAddr); + drawModelParts(0x0, partsAddr); } } ImGui.PopID(); @@ -5538,9 +5600,10 @@ namespace NewCamera } } } + ImGui.Checkbox("Only Toggle LOD 0", ref modelOnlyAddressLod0); if (ImGui.BeginItemTooltip()) { - ImGui.Text($"Part toggling only applies to LOD0."); + 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(); } -- cgit v1.2.3-101-g0448