From ec7145dd87b1ba12c2f67f6204c138f651210a5f Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sat, 11 Oct 2025 18:16:04 -0400 Subject: Add graphical enhancements and lots of fixes Signed-off-by: Andrew Opalach --- Config.cs | 13 +- Plugin.cs | 1151 +++++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 938 insertions(+), 226 deletions(-) diff --git a/Config.cs b/Config.cs index f40a76c..df575c4 100755 --- a/Config.cs +++ b/Config.cs @@ -12,6 +12,7 @@ namespace MHWNewCamera public const float DEFAULT_SPEED_MODIFIER = 0.25f; public const float DEFAULT_SENSITIVITY = 1.95f; public const double DEFAULT_PITCH_LIMIT = -1.0; + public const double MAX_PITCH_LIMIT = 89.95; public const int DEFAULT_DEADZONE = 4750; public Settings() @@ -39,6 +40,7 @@ namespace MHWNewCamera public float Right { get; set; } public float Up { get; set; } public double Roll { get; set; } + public bool FadeObjects { get; set; } } public struct SavedPosition @@ -53,7 +55,7 @@ namespace MHWNewCamera } public String Name => "MHWNewCamera"; - public String Version => "1.2"; + public String Version => "2.0"; private static Dictionary buttonMap = new Dictionary { @@ -94,11 +96,20 @@ namespace MHWNewCamera public bool EnableCombo { get; set; } = true; public String FreeCameraCombo { get; set; } = "RStick,LT"; + public bool DisableComboButton1UnlessButton2Held { get; set; } = false; public Settings CameraSettings { get; set; } = new Settings(); public bool PerspectiveCameraEnabled { get; set; } = false; public Dictionary Presets { get; set; } = new Dictionary(); public String Selected { get; set; } = ""; public Dictionary Positions { get; set; } = new Dictionary(); + + public bool DisableCharacterFade { get; set; } = false; + + public bool DoubleShadowResolution { get; set; } = false; + public bool SlightlySofterShadows { get; set; } = false; + public bool SofterShadows { get; set; } = false; + public bool HigherLods { get; set; } = false; + public bool LargerFoliageSwayRange { get; set; } = false; } } diff --git a/Plugin.cs b/Plugin.cs index 5c8cc10..7da717a 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -1,4 +1,6 @@ //#define ADDR_ASSERTS +//#define HOOK_ORDER_ASSERTS +//#define LOG_DEBUG_MESSAGES using ImGuiNET; using System.Numerics; @@ -10,21 +12,17 @@ using SharpPluginLoader.Core.Memory; using SharpPluginLoader.Core.Actions; using SharpPluginLoader.Core.Components; using SharpPluginLoader.Core.Configuration; -#if ADDR_ASSERTS +#if ADDR_ASSERTS || HOOK_ORDER_ASSERTS using System.Diagnostics; #endif // @TODO: -// - Trigger blue camera on minimap. -// - Ability to disable more inputs in freecam. -// - Update default binds. -// - Bind to change preset. -// - Bind to reverse freecam input (left AND right stick no effect on camera). +// - White vase thing in research base still fades when close. +// - Shadow cache size? or shadow map count? // - Display equiped armor in the debug UI. // - Manully set freecam viewport index. // - Override in-game viewmode. // - +right and +forward to move character. -// - Keyframes? // - Special case freecam for cutscenes and canteen animations. // Test cases: @@ -51,12 +49,23 @@ using System.Diagnostics; // - Look at monster. // - Scoutflies point in a direction. // - Mount monster. +// // Free Camera: // - Toggle rapidly and there should be no visual jump. // - Story cutscenes. // - Canteen cutscene/animation. // - Inside tent. // - Equipment select inside tent. +// +// Disable Character Fade: +// - NPCs that spawn invisible and fade-in have to actually fade-in. +// - A night time in Astera, there will eventually be 3 hunters eating at the table next to the handler. +// If this is broken, two of them will be invisible. +// +// 2x Shadow Resolution: +// - The shadow of the \"Waterfall Bridge\" lift in Astera. +// - Walk up the stairs towards the canteen and the shadow of the lift will fade-out. Move the camera +// back and forth and make sure the lower resolution shadow aligns with the higher res one. namespace MHWNewCamera { @@ -78,6 +87,14 @@ namespace MHWNewCamera private bool enableCombo = false; private Button[]? freeCameraCombo = null; + private bool disableComboButton1 = false; + private bool comboButton1Down = false; + + private uint lastPadDown = 0; + private bool buttonWasDown(Button button) + { + return (lastPadDown & (uint)button) == (uint)button; + } private double cameraFov = DEFAULT_FOV; private float cameraForward = 0.0f; @@ -88,24 +105,28 @@ namespace MHWNewCamera private double cameraYaw = 0.0; private double cameraPitch = 0.0; private double cameraRoll = 0.0; + private bool fadeObjects = true; private int cameraWrapState = 0; private bool freeCamera = false; private bool enableFreeCamera = false; private Camera? vCamera = null; - private bool cameraSetFromAlt = false; + private int vCameraViewportIndex = -1; private Vector3 cameraPosition; private Vector3 cameraTarget; private double? preDetachFov = null; private double? preDetachRoll = null; private bool unlockMovementHeld = false; private bool unlockMovementToggled = false; + private bool unlockMovementPause = false; + private bool unlockInputToggled = false; private bool offsetPerspective = false; private bool enableOffsetPerspective = false; - private bool applyPerspective = false; private Player? lastPlayer = null; private Camera? pCamera = null; + private int pCameraViewportIndex = -1; + private bool applyPerspective = false; private float previousFov = -1.0f; private int previousCameraAnimState = 0; private bool ignoreAnimState = false; @@ -117,19 +138,68 @@ namespace MHWNewCamera private delegate void SetCameraDelegate(nint unknownPtr); private Hook? setCameraHook; - private delegate void SetCameraTentDelegate(nint unknownPtr); - private Hook? setCameraTentHook; - private delegate void CalculateCameraDelegate(nint unknownPtr); private Hook? calculateCameraHook; - private delegate void CameraUpDelegate(nint unknownPtr); - private Hook? cameraUpHook; + private delegate void SetCameraTentDelegate(nint unknownPtr); + private Hook? setCameraTentHook; + + private delegate void WritePadInputDelegate(nint unknownPtr, nint unknownPtr2, nint unknownPtr3); + private Hook? writePadInputHook; private delegate float CheckMovementDelegate(int stickValue); private Hook? checkMovementHook; - private Patch disableCameraAnimation; + private Patch swapMinimapFollowsCamera; + + private bool uiToggled = false; + private Patch jmpOverUi; + + private bool disableCharacterFade = false; + private Patch noopCharacterFade; + + private bool doubleShadowRes = false; + private Patch shadowRes1; + private Patch shadowRes1_2; + private Patch shadowRes1_3; + private Patch shadowRes2; + private Patch shadowRes3; + private Patch shadowRes4; + private Patch shadowRes4_2; + private bool softerShadows = false; + private bool slightlySofterShadows = false; + private Patch higherMinThreshold; + private Patch slightlyHigherMinThreshold; + + private void doubleShadowResEnable() + { + shadowRes1.Enable(); + shadowRes1_2.Enable(); + shadowRes1_3.Enable(); + shadowRes2.Enable(); + shadowRes3.Enable(); + shadowRes4.Enable(); + shadowRes4_2.Enable(); + } + + private void doubleShadowResDisable() + { + shadowRes1.Disable(); + shadowRes1_2.Disable(); + shadowRes1_3.Disable(); + shadowRes2.Disable(); + shadowRes3.Disable(); + shadowRes4.Disable(); + shadowRes4_2.Disable(); + } + + private float unknownLod1 = 0.0f; + private float unknownLod2 = 0.0f; + private float foliageLodFactor = 1.565f; + private float terrainLodFactor = 64.0f; + + private bool largerFoliageSwayRange = false; + private Patch addressHigherValueForFoliageSway; private bool disableCollision = false; private bool disableExtraCollision = false; @@ -201,7 +271,19 @@ namespace MHWNewCamera private string typedPositionName = ""; private string selectedPositionName = ""; - public void OnLoad() +#if HOOK_ORDER_ASSERTS + private int hookOrder = 0; + private int frameTick = 0; +#endif + + private void debugLog(string message) + { +#if LOG_DEBUG_MESSAGES + Log.Debug(message); +#endif + } + + private Config loadConfig() { Config config = ConfigManager.GetConfig(this); @@ -209,6 +291,7 @@ namespace MHWNewCamera enableCombo = config.EnableCombo; freeCameraCombo = Config.ParseCombo(config.FreeCameraCombo); typedCombo = config.FreeCameraCombo.Replace(",", "+"); + disableComboButton1 = config.DisableComboButton1UnlessButton2Held; Config.Settings settings = config.CameraSettings; cameraSpeed = settings.CameraSpeed; @@ -216,9 +299,9 @@ namespace MHWNewCamera cameraSpeedModifier = settings.CameraSpeedModifier; cameraSensitivity = settings.CameraSensitivity; cameraPitchLimit = settings.CameraPitchLimit; - if (cameraPitchLimit != -1.0f) + if (cameraPitchLimit != -1.0) { - cameraPitchLimit = Math.Clamp(cameraPitchLimit, 0.0f, 89.95f); + cameraPitchLimit = Math.Clamp(cameraPitchLimit, 0.0, Config.Settings.MAX_PITCH_LIMIT); } stickDeadzone = settings.StickDeadzone; @@ -231,20 +314,46 @@ namespace MHWNewCamera cameraRight = preset.Right; cameraYOffset = preset.Up; cameraRoll = preset.Roll; + fadeObjects = preset.FadeObjects; } + disableCharacterFade = config.DisableCharacterFade; + + doubleShadowRes = config.DoubleShadowResolution; + slightlySofterShadows = config.SlightlySofterShadows; + if (slightlySofterShadows && config.SofterShadows) + { + config.SofterShadows = false; + } + softerShadows = config.SofterShadows; + largerFoliageSwayRange = config.LargerFoliageSwayRange; + ConfigManager.SaveConfig(this); + return config; + } + + public void OnPreMain() + { + Config config = loadConfig(); + // Asserts based on version 15.23.00. // @TODO: Handle addr not found. - // A place to check state before CalculateCameraHook. - nint addr = PatternScanner.FindFirst(Pattern.FromString("48 8B C4 48 89 58 08 48 89 70 10 48 89 78 18 4C 89 60 20 55 41 56 41 57 48 8D A8 28 FE FF FF 48 81 EC C0 02 00 00 0F 29 70 D8 48 8B F1")); + // Place where we can check camera state early. + nint addr = PatternScanner.FindFirst(Pattern.FromString("40 53 48 81 EC 80 00 00 00 8B 81 B0 17 00 00 48 8B D9 85 C0 ?? ??")); #if ADDR_ASSERTS - Trace.Assert(addr == 0x141fa16d0); // nint + Trace.Assert(addr == 0x141FA11A0); // nint #endif setCameraHook = Hook.Create(addr, SetCameraHook); + // Place where we can adjust the camera position. + addr = PatternScanner.FindFirst(Pattern.FromString("48 8B C4 55 41 57 48 81 EC D8 00 00 00 44 0F 29 40 B8 45 33 FF ?? ?? ?? ?? ?? ?? ?? ?? ?? 48 8B E9")); +#if ADDR_ASSERTS + Trace.Assert(addr == 0x141FA5380); // nint +#endif + calculateCameraHook = Hook.Create(addr, CalculateCameraHook); + // Very special case for inside tent. addr = PatternScanner.FindFirst(Pattern.FromString("48 89 5C 24 10 48 89 6C 24 18 48 89 7C 24 20 41 56 48 83 EC 60 48 8B D9 0F 57 DB ?? ?? ?? ?? ?? ?? ?? 0F 57 D2 33 D2")); #if ADDR_ASSERTS @@ -252,69 +361,147 @@ namespace MHWNewCamera #endif setCameraTentHook = Hook.Create(addr, SetCameraTentHook); - // Hook where we can adjust the camera position. - addr = PatternScanner.FindFirst(Pattern.FromString("48 8B C4 55 41 57 48 81 EC D8 00 00 00 44 0F 29 40 B8 45 33 FF ?? ?? ?? ?? ?? ?? ?? ?? ?? 48 8B E9")); -#if ADDR_ASSERTS - Trace.Assert(addr == 0x141fa5380); // nint -#endif - calculateCameraHook = Hook.Create(addr, CalculateCameraHook); - - // Hook where we can set Camera.Up before it's used. - addr = PatternScanner.FindFirst(Pattern.FromString("40 53 48 81 EC 80 00 00 00 8B 81 B0 17 00 00 48 8B D9 85 C0 ?? ??")); + 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")); #if ADDR_ASSERTS - Trace.Assert(addr == 0x141fa11a0); // nint + Trace.Assert(addr == 0x1422A1280); // nint, nint, nint #endif - cameraUpHook = Hook.Create(addr, CameraUpHook); + writePadInputHook = Hook.Create(addr, WritePadInputHook); - // Hook where we can change the analog stick value the game uses for character movement. + // 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")); #if ADDR_ASSERTS - Trace.Assert(addr == 0x142107cb0); // int + Trace.Assert(addr == 0x142107CB0); // int #endif checkMovementHook = Hook.Create(addr, CheckMovementHook); unchecked { - addr = PatternScanner.FindFirst(Pattern.FromString("40 53 48 81 EC B0 00 00 00 48 8B D9 48 8B D1 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 48 8B 03 48 8D 54 24 30")); + addr = PatternScanner.FindFirst(Pattern.FromString("84 C0 0F 84 ?? ?? ?? ?? 48 8B 57 28 45 33 C0 48 8B CE E8 ?? ?? ?? ?? 48 8B 97 E0 01 00 00 41 B0 01 48 8B CE E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B D8")); #if ADDR_ASSERTS - Trace.Assert(addr == 0x1423b1420); // nint + Trace.Assert(addr == 0x141E55D9E); #endif - disableCameraAnimation = new Patch(addr + 0x50, [ - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 + swapMinimapFollowsCamera = new Patch(addr + 0x3, [0x85]); // je -> jne + + addr = PatternScanner.FindFirst(Pattern.FromString("48 89 5C 24 18 48 89 6C 24 20 57 48 83 EC 20 48 8B 59 68 48 8B FA 48 8B E9 48 85 DB 0F 84 ?? ?? ?? ?? 4C 89 74 24 38 4C 8B B3 80 00 00 00 4D 85 F6")); +#if ADDR_ASSERTS + Trace.Assert(addr == 0x14234DD60); +#endif + jmpOverUi = new Patch(addr + 0x1c, [0xE9, 0x65, 0x01, 0x00, 0x00, 0x90]); + + addr = PatternScanner.FindFirst(Pattern.FromString("CC 48 89 5C 24 18 57 48 83 EC 30 48 89 74 24 48 48 8B D9 E8 ?? ?? ?? ?? 48 8B 8B B0 0D 00 00 8B 81 54 89 00 00 C1 E8 0D A8 01")); +#if ADDR_ASSERTS + Trace.Assert(addr == 0x1411A6A9F); +#endif + noopCharacterFade = new Patch(addr + 0x13, [0x90, 0x90, 0x90, 0x90, 0x90]); // call MonsterHunterWorld.exe+11A6D50 + if (disableCharacterFade && !disableMod) + { + noopCharacterFade.Enable(); + } + + addr = PatternScanner.FindFirst(Pattern.FromString("48 83 EC 28 F3 0F 10 0D ?? ?? ?? ?? 80 F9 04 75 2F 48 8B 0D ?? ?? ?? ?? E8 D3 8A E4 01 48 8B 0D ?? ?? ?? ?? 33 D2 E8 ?? ?? ?? ??")); +#if ADDR_ASSERTS + Trace.Assert(addr == 0x14043FF80); +#endif + shadowRes1 = new Patch(addr + 0x8, [0xCC, 0xF3, 0xAC, 0x02]); + shadowRes1_2 = new Patch(addr + 0x68, [0x59]); // movss -> mulss + shadowRes1_3 = new Patch(addr + 0x77, [0x59]); // movss -> mulss + + addr = PatternScanner.FindFirst(Pattern.FromString("83 FA FF 74 06 89 91 1C 55 00 00 8B 91 30 55 00 00 83 FA FF 7F 06 8B 91 1C 55 00 00 85 D2 74 4B 83 EA 01 74 3B 83 EA 01 74 2B 83 EA 01 74 1B 83 FA 01 74 0B C7 81 20 55 00 00 01 00 00 00 C3 C7 81 20 55 00 00 00 10 00 00")); +#if ADDR_ASSERTS + Trace.Assert(addr == 0x142287A50); +#endif + shadowRes2 = new Patch(addr + 0x3F, [ + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC3, + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC3, + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC3, // Has to be 8192 for the fallback lower res shadow to be aligned. + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xC3, + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xC3 + ]); + + addr = PatternScanner.FindFirst(Pattern.FromString("89 91 30 55 00 00 83 FA FF 7F 06 8B 91 1C 55 00 00 85 D2 74 4B 83 EA 01 74 3B 83 EA 01 74 2B 83 EA 01 74 1B 83 FA 01 74 0B C7 81 20 55 00 00 01 00 00 00 C3 C7 81 20 55 00 00 00 10 00 00")); +#if ADDR_ASSERTS + Trace.Assert(addr == 0x142287AD0); +#endif + shadowRes3 = new Patch(addr + 0x34, [ + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC3, + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC3, + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC3, + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xC3, + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xC3 + ]); + + addr = PatternScanner.FindFirst(Pattern.FromString("89 91 00 55 00 00 83 FA 05 77 41 48 63 C2 4C 8D 05 ?? ?? ?? ?? 41 8B 94 80 84 8B 28 02 49 03 D0 FF E2 B8 00 08 00 00")); +#if ADDR_ASSERTS + Trace.Assert(addr == 0x142288B00); +#endif + shadowRes4 = new Patch(addr + 0x29, [ + 0xB8, 0x00, 0x16, 0x00, 0x00, 0xEB, 0x21, // "Primary shadow range". The game only ever addresses this case. ]); + // Multiply even on "High" because it's now 2.0 not 1.0. + shadowRes4_2 = new Patch(addr + 0x5E, [0x90, 0x90]); + + if (doubleShadowRes && !disableMod) + { + doubleShadowResEnable(); + } + + addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 10 8F D0 E5 00 00 0F 57 C0 F3 0F 59 0D ?? ?? ?? ?? 8B C1 48 C1 E8 0C 25 FF 03 00 00 F3 48 0F 2A C3 F3 0F 5E C8 F3 41 0F 11 0C 87")); +#if ADDR_ASSERTS + Trace.Assert(addr == 0x142286B1B); + Trace.Assert(MemoryUtil.Read(0x14239CF98) == 4096.0f); + Trace.Assert(MemoryUtil.Read(0x140598864) == 3072.0f); +#endif + slightlyHigherMinThreshold = new Patch(addr + 0xF, [0x36, 0x1D, 0x31, 0xFE]); + if (slightlySofterShadows && !disableMod) + { + slightlyHigherMinThreshold.Enable(); + } + higherMinThreshold = new Patch(addr + 0xF, [0x6A, 0x64, 0x11, 0x00]); + if (softerShadows && !disableMod) + { + higherMinThreshold.Enable(); + } + + addr = PatternScanner.FindFirst(Pattern.FromString("74 4D 33 C0 48 81 C1 00 02 00 00 F3 0F 10 11 0F 2F CA 72 0C FF C0 48 83 C1 04 83 F8 03 72 EC C3")); +#if ADDR_ASSERTS + Trace.Assert(addr == 0x1426D89CA); +#endif + addressHigherValueForFoliageSway = new Patch(addr + 0x7, [0x04]); + if (largerFoliageSwayRange && !disableMod) + { + addressHigherValueForFoliageSway.Enable(); + } // Noop collision checks. addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 11 06 F3 0F 10 48 04 F3 0F 58 4E 04 F3 0F 11 4E 04 F3 0F 10 40 08 F3 0F 58 46 08 F3 0F 11 46 08 44 8B AF E0 0B 00 00")); #if ADDR_ASSERTS - Trace.Assert(addr == 0x141c001b5); + Trace.Assert(addr == 0x141C001B5); #endif disableXCollision = new Patch(addr, [0x90, 0x90, 0x90, 0x90]); #if ADDR_ASSERTS - Trace.Assert(addr + 0xe == 0x141c001c3); + Trace.Assert(addr + 0xE == 0x141C001C3); #endif - disableYCollision = new Patch(addr + 0xe, [0x90, 0x90, 0x90, 0x90, 0x90]); + disableYCollision = new Patch(addr + 0xE, [0x90, 0x90, 0x90, 0x90, 0x90]); #if ADDR_ASSERTS - Trace.Assert(addr + 0x1d == 0x141c001d2); + Trace.Assert(addr + 0x1D == 0x141C001D2); #endif - disableZCollision = new Patch(addr + 0x1d, [0x90, 0x90, 0x90, 0x90, 0x90]); + disableZCollision = new Patch(addr + 0x1D, [0x90, 0x90, 0x90, 0x90, 0x90]); addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 11 46 04 F3 0F 10 46 08 F3 0F 5C C2 F3 0F 11 46 08 ?? ?? F3 0F")); #if ADDR_ASSERTS - Trace.Assert(addr == 0x141c000d2); + Trace.Assert(addr == 0x141C000D2); #endif disableSecondaryYCollision = new Patch(addr, [0x90, 0x90, 0x90, 0x90, 0x90]); addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 11 46 04 F3 0F 10 58 08 F3 0F 58 5E 08 F3 0F 11 5E 08 44 8B 87 D0 0B 00 00 41 F6 C0 03")); #if ADDR_ASSERTS - Trace.Assert(addr == 0x141bfff90); + Trace.Assert(addr == 0x141BFFF90); #endif disableExtraYCollision = new Patch(addr, [0x90, 0x90, 0x90, 0x90, 0x90]); addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 11 83 80 00 00 00 F3 0F 11 8B 84 00 00 00 F3 0F 11 93 88 00 00 00 89 B3 8C 00 00 00 8B 83 A4 01 00 00 C1 E8 05 44 0F 29 A4 24 D0 01 00 00 44 0F 29 B4 24 B0 01 00 00 A8 01")); #if ADDR_ASSERTS - Trace.Assert(addr + 0x8 == 0x1413259ed); + Trace.Assert(addr + 0x8 == 0x1413259ED); #endif disableGravityYUpdate = new Patch(addr + 0x8, [ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, @@ -325,12 +512,62 @@ namespace MHWNewCamera 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 ]); - // 141BFFF75 - E8 965872FF - call MonsterHunterWorld.exe+1325810 addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 11 97 54 15 00 00 F3 0F 11 8F 58 15 00 00 F3 0F 10 47 68 F3 0F 5E D8 44 89 B7 6C 15 00 00 F3 0F 5E D0 F3 0F 5E C8 F3 0F 11 9F 60 15 00 00 F3 0F 11 97 64 15 00 00 F3 0F 11 8F 68 15 00 00")); #if ADDR_ASSERTS - Trace.Assert(addr + 0x40 == 0x141bfff75); + Trace.Assert(addr + 0x40 == 0x141BFFF75); #endif - disableGravityEval = new Patch(addr + 0x40, [0x90, 0x90, 0x90, 0x90, 0x90]); + disableGravityEval = new Patch(addr + 0x40, [0x90, 0x90, 0x90, 0x90, 0x90]); // call MonsterHunterWorld.exe+1325810 + } + } + + public void OnLoad() + { + Config config = ConfigManager.GetConfig(this); + if (config.HigherLods) + { + setLodFactors(true); + } + } + + // Credit to Otis_Inf. + private bool getFadeObjects(int viewportIndex) + { + Viewport vp = CameraSystem.GetViewport(viewportIndex); + return MemoryUtil.Read(vp.Instance + 0x21) == 1; + } + + private void setFadeObjects(int viewportIndex, bool fadeOut) + { + Viewport vp = CameraSystem.GetViewport(viewportIndex); + MemoryUtil.WriteBytes(vp.Instance + 0x21, fadeOut ? [0x1] : [0x0]); + } + + private bool areLodFactorsSet() + { + nint baseAddr = MemoryUtil.Read(0x1451C4368); + float lod1 = MemoryUtil.Read(baseAddr + 0x224); + float lod2 = MemoryUtil.Read(baseAddr + 0x228); + float lod3 = MemoryUtil.Read(baseAddr + 0x234); + float lod4 = MemoryUtil.Read(baseAddr + 0x24C); + return lod1 == unknownLod1 && lod2 == unknownLod2 && lod3 == foliageLodFactor && lod4 == terrainLodFactor; + } + + private void setLodFactors(bool toggleOn) + { + nint baseAddr = MemoryUtil.Read(0x1451C4368); + if (toggleOn) + { + MemoryUtil.WriteBytes(baseAddr + 0x224, BitConverter.GetBytes(unknownLod1)); // Something with lighting? + MemoryUtil.WriteBytes(baseAddr + 0x228, BitConverter.GetBytes(unknownLod2)); + MemoryUtil.WriteBytes(baseAddr + 0x234, BitConverter.GetBytes(foliageLodFactor)); + MemoryUtil.WriteBytes(baseAddr + 0x24C, BitConverter.GetBytes(terrainLodFactor)); + } + else + { + MemoryUtil.WriteBytes(baseAddr + 0x224, BitConverter.GetBytes(1.0f)); + MemoryUtil.WriteBytes(baseAddr + 0x228, BitConverter.GetBytes(1.0f)); + MemoryUtil.WriteBytes(baseAddr + 0x234, BitConverter.GetBytes(1.0f)); + MemoryUtil.WriteBytes(baseAddr + 0x24C, BitConverter.GetBytes(1.0f)); } } @@ -388,13 +625,13 @@ namespace MHWNewCamera private void setTentBasePos(Vector3 pos, Vector3 target) { // @TODO: This can be picked out of the code. - nint baseAddr = MemoryUtil.Read(0x145011f58); // Default: - MemoryUtil.WriteBytes(baseAddr + 0x3e20, BitConverter.GetBytes(pos.X)); // 0.0 - MemoryUtil.WriteBytes(baseAddr + 0x3e24, BitConverter.GetBytes(pos.Y)); // -19850.0 - MemoryUtil.WriteBytes(baseAddr + 0x3e28, BitConverter.GetBytes(pos.Z)); // 270.0 - MemoryUtil.WriteBytes(baseAddr + 0x3e30, BitConverter.GetBytes(target.X)); // 0.0 - MemoryUtil.WriteBytes(baseAddr + 0x3e34, BitConverter.GetBytes(target.Y)); // -19830.0 - MemoryUtil.WriteBytes(baseAddr + 0x3e38, BitConverter.GetBytes(target.Z)); // 0.0 + nint baseAddr = MemoryUtil.Read(0x145011F58); // Default: + MemoryUtil.WriteBytes(baseAddr + 0x3E20, BitConverter.GetBytes(pos.X)); // 0.0 + MemoryUtil.WriteBytes(baseAddr + 0x3E24, BitConverter.GetBytes(pos.Y)); // -19850.0 + MemoryUtil.WriteBytes(baseAddr + 0x3E28, BitConverter.GetBytes(pos.Z)); // 270.0 + MemoryUtil.WriteBytes(baseAddr + 0x3E30, BitConverter.GetBytes(target.X)); // 0.0 + MemoryUtil.WriteBytes(baseAddr + 0x3E34, BitConverter.GetBytes(target.Y)); // -19830.0 + MemoryUtil.WriteBytes(baseAddr + 0x3E38, BitConverter.GetBytes(target.Z)); // 0.0 } private void disableFreeCamera() @@ -412,16 +649,27 @@ namespace MHWNewCamera } cameraWrapState = 0; setTentBasePos(new Vector3(0.0f, -19850.0f, 270.0f), new Vector3(0.0f, -19830.0f, 0.0f)); - cameraSetFromAlt = false; + if (vCameraViewportIndex != pCameraViewportIndex) + { + setFadeObjects(vCameraViewportIndex, true); + } + else + { + setFadeObjects(pCameraViewportIndex, fadeObjects); + } + swapMinimapFollowsCamera.Disable(); } - private void updateFreecam(Camera camera) + private void updateFreeCamera(Camera camera) { float deltaTime = camera.DeltaTime; - if (Input.IsDown(Button.L2) && Input.IsDown(Button.R2)) // Left stick zoom. + double adjustedSpeed = cameraSpeed * deltaTime; + double buttonOffset = adjustedSpeed / 2.0; + + if (buttonWasDown(Button.L2) && buttonWasDown(Button.R2)) // Left stick zoom. { - int PadLy = MemoryUtil.Read(controllerAddr() + 0x1bc); + int PadLy = MemoryUtil.Read(controllerAddr() + 0x1BC); if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0; double adjustedZoomSpeed = cameraZoomSpeed * deltaTime * cameraFov; double Ly = PadLy / (Int16.MaxValue / adjustedZoomSpeed); @@ -429,39 +677,21 @@ namespace MHWNewCamera } else if (!(unlockMovementHeld || unlockMovementToggled)) // Move camera. { - int PadLy = MemoryUtil.Read(controllerAddr() + 0x1bc); + int PadLy = MemoryUtil.Read(controllerAddr() + 0x1BC); if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0; - int PadLx = MemoryUtil.Read(controllerAddr() + 0x1b8); + int PadLx = MemoryUtil.Read(controllerAddr() + 0x1B8); if (Math.Abs(PadLx) < stickDeadzone) PadLx = 0; - double adjustedSpeed = cameraSpeed * deltaTime; double Lx = PadLx / (Int16.MaxValue / adjustedSpeed); double Ly = PadLy / (Int16.MaxValue / adjustedSpeed); Quaternion forward = getForward(cameraPosition, cameraTarget); - if (Input.IsDown(Button.L2)) + if (buttonWasDown(Button.R2)) { forward.Y = 0.0f; Lx *= cameraSpeedModifier; Ly *= cameraSpeedModifier; - double buttonOffset = adjustedSpeed / 2.0; buttonOffset *= cameraSpeedModifier; - if (Input.IsDown(Button.Up)) - { - cameraPosition.Y += (float)buttonOffset; - } - if (Input.IsDown(Button.Down)) - { - cameraPosition.Y -= (float)buttonOffset; - } - if (Input.IsDown(Button.Left)) - { - cameraRoll -= buttonOffset; - } - if (Input.IsDown(Button.Right)) - { - cameraRoll += buttonOffset; - } } Quaternion right = forward; @@ -483,10 +713,30 @@ namespace MHWNewCamera } } + if (!unlockInputToggled) + { + if (buttonWasDown(Button.Up)) + { + cameraPosition.Y += (float)buttonOffset; + } + if (buttonWasDown(Button.Down)) + { + cameraPosition.Y -= (float)buttonOffset; + } + if (buttonWasDown(Button.Left)) + { + cameraRoll -= buttonOffset; + } + if (buttonWasDown(Button.Right)) + { + cameraRoll += buttonOffset; + } + } + // Camera look. - int PadRx = MemoryUtil.Read(controllerAddr() + 0x1b0); + int PadRx = MemoryUtil.Read(controllerAddr() + 0x1B0); if (Math.Abs(PadRx) < stickDeadzone) PadRx = 0; - int PadRy = MemoryUtil.Read(controllerAddr() + 0x1b4); + int PadRy = MemoryUtil.Read(controllerAddr() + 0x1B4); if (Math.Abs(PadRy) < stickDeadzone) PadRy = 0; double adjustedSensitivity = cameraSensitivity * deltaTime * cameraFov; double Rx = PadRx / (Int16.MaxValue / adjustedSensitivity); @@ -556,7 +806,18 @@ namespace MHWNewCamera camera.FieldOfView = (float)cameraFov; } - private Camera? getVisibleCamera() + private void checkPlayerChange() + { + Player? player = Player.MainPlayer; + if (player != lastPlayer) + { + pCamera = null; + pCameraViewportIndex = -1; + lastPlayer = player; + } + } + + private int getVisibleCamera() { for (int i = 0; i < 8; i++) { @@ -564,69 +825,121 @@ namespace MHWNewCamera // A viewport can be visible with a null camera. if (vp.Visible && vp.Camera != null) { - if (freeCamera && vp.Camera != vCamera) - { - // This will still be broken in most cases, just less broken. - cameraPosition = vp.Camera.Position; - cameraTarget = vp.Camera.Target; - } - return vp.Camera; + return i; } } - return null; + return -1; } - private void SetCameraHook(nint unknownPtr) + private void checkCurrentVisibleCamera() { - if (!disableMod) + vCameraViewportIndex = getVisibleCamera(); + if (vCameraViewportIndex >= 0) { - vCamera = getVisibleCamera(); + Camera camera = CameraSystem.GetViewport(vCameraViewportIndex).Camera!; + // Free camera target change. + if (freeCamera && camera != vCamera) + { + Player? player = Player.MainPlayer; + 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 = Double.RadiansToDegrees(Math.Atan2(forward.Z, forward.X)); + cameraPitch = Double.RadiansToDegrees(Math.Asin(forward.Y)); + } + vCamera = camera; + // pCamera is the first visible camera after a player is set. + // We assume it is the player camera. if (pCamera == null && lastPlayer != null) { - // This assume the visible camera when, or right after, MainPlayer is set is the player camera. pCamera = vCamera; + pCameraViewportIndex = vCameraViewportIndex; + setFadeObjects(pCameraViewportIndex, fadeObjects); } - if (pCamera != null) + } + } + + private void checkCameraAnimState() + { + if (pCamera != null) + { + previousCameraAnimState = MemoryUtil.Read(pCamera.Instance + 0x240); + if (previousCameraAnimState == 5) { - previousCameraAnimState = MemoryUtil.Read(pCamera.Instance + 0x240); - if (previousCameraAnimState == 5) - { - // 1:314 = Wingdrake landing on area enter. - // 1:319 = Scared wingdrake landing next to monster. - Player player = Player.MainPlayer!; - ActionInfo currentActionInfo = player.ActionController.CurrentAction; - if (currentActionInfo.ActionSet == 1 && (currentActionInfo.ActionId == 314 || currentActionInfo.ActionId == 319)) - { - // Temporarily disable evaluation of cameraAnimState != 5. - ignoreAnimState = true; - } - } - else if (ignoreAnimState) + // 1:314 = Wingdrake landing on area enter. + // 1:319 = Disoriented wingdrake landing next to monster. + Player player = Player.MainPlayer!; + ActionInfo currentActionInfo = player.ActionController.CurrentAction; + if (currentActionInfo.ActionSet == 1 && (currentActionInfo.ActionId == 314 || currentActionInfo.ActionId == 319)) { - // Once cameraAnimState is no longer 5, resume default logic. - ignoreAnimState = false; + // Temporarily disable evaluation of cameraAnimState != 5. + ignoreAnimState = true; } } - else + else if (ignoreAnimState) { - previousCameraAnimState = 0; + // Once cameraAnimState is no longer 5, resume default logic. + ignoreAnimState = false; } } - setCameraHook!.Original(unknownPtr); + else + { + previousCameraAnimState = 0; + } } - private void SetCameraTentHook(nint unknownPtr) + private void SetCameraHook(nint unknownPtr) { - if (!disableMod && freeCamera) + if (disableMod) { - setTentBasePos(cameraPosition, cameraTarget); + setCameraHook!.Original(unknownPtr); + return; } - setCameraTentHook!.Original(unknownPtr); - if (!disableMod && freeCamera && vCamera != null) + +#if HOOK_ORDER_ASSERTS + debugLog($"SetCameraHook() @ {frameTick}"); + Trace.Assert(hookOrder == 0); + hookOrder = 1; +#endif + + checkCurrentVisibleCamera(); + checkCameraAnimState(); + + // CalculateCameraHook() within this function. + setCameraHook!.Original(unknownPtr); +#if HOOK_ORDER_ASSERTS + Trace.Assert(hookOrder == 2); + hookOrder = 3; +#endif + + if (applyPerspective) + { + setCameraRoll(pCamera!); + } + + if (freeCamera && vCamera != null) { - updateFreecam(vCamera); setCameraRoll(vCamera); - cameraSetFromAlt = true; + if (!enableFreeCamera) + { + // Disable free camera only after applying all possible + // offsets for this frame. This is to hopefully avoid any + // visual jumps. + disableFreeCamera(); + } } } @@ -644,6 +957,12 @@ namespace MHWNewCamera return; } +#if HOOK_ORDER_ASSERTS + debugLog($"CalculateCameraHook() @ {frameTick}"); + Trace.Assert(hookOrder == 1); + hookOrder = 2; +#endif + if (enableOffsetPerspective && !offsetPerspective) { offsetPerspective = true; @@ -708,49 +1027,208 @@ namespace MHWNewCamera // actually shown, which avoids a jump when toggling freecam. This is also why // we don't enable freecam until after applying a offset on this update. cameraFov = vCamera.FieldOfView; + setFadeObjects(vCameraViewportIndex, false); + swapMinimapFollowsCamera.Enable(); } } - // No else if because we wan't to updateFreecam() if freeCamera was enabled above. + // No else if because we want to updateFreeCamera() if freeCamera was enabled above. if (freeCamera) { - if (!cameraSetFromAlt) - { - updateFreecam(vCamera); - } - cameraSetFromAlt = false; - if (!enableFreeCamera) - { - disableFreeCamera(); - } + updateFreeCamera(vCamera); } } } - private void CameraUpHook(nint unknownPtr) + private void SetCameraTentHook(nint unknownPtr) { - cameraUpHook!.Original(unknownPtr); - if (disableMod) return; - // This is still runs before culling. Checking Camera.Fix for tent idle, at least. - if ((applyPerspective || freeCamera) && vCamera != null && vCamera.Fix) + if (disableMod) + { + setCameraTentHook!.Original(unknownPtr); + return; + } +#if HOOK_ORDER_ASSERTS + // The order of this hook between SetCameraHook() and CalculateCameraHook() is inconsistent. + debugLog($"SetCameraTentHook() @ {frameTick}"); +#endif + if (freeCamera && vCamera != null) { + setTentBasePos(cameraPosition, cameraTarget); + } + setCameraTentHook!.Original(unknownPtr); + if (freeCamera && vCamera != null) + { + vCamera.Position = cameraPosition; + vCamera.Target = cameraTarget; + vCamera.FieldOfView = (float)cameraFov; setCameraRoll(vCamera); } - if (applyPerspective) + } + + // This can undoubtedly be simplified. I'm being conservative about MemoryUtil.Read() because + // I haven't thought about or tested enough to know if it should be a performance consideration. + private void WritePadInputHook(nint unknownPtr, nint unknownPtr2, nint unknownPtr3) + { + if (disableMod) { - setCameraRoll(pCamera!); + writePadInputHook!.Original(unknownPtr, unknownPtr2, unknownPtr3); + return; + } + + uint PadDown = 0, PadTrg = 0, PadRel = 0, PadChg = 0; + if ((enableCombo && freeCameraCombo != null && disableComboButton1) && comboButton1Down) + { + PadDown = MemoryUtil.Read(controllerAddr() + 0x198); + uint b1 = (uint)freeCameraCombo[0]; + PadDown |= b1; + MemoryUtil.WriteBytes(controllerAddr() + 0x198, BitConverter.GetBytes(PadDown)); + } + + writePadInputHook!.Original(unknownPtr, unknownPtr2, unknownPtr3); + + bool readInputsPostHook = false; + + if (enableCombo && freeCameraCombo != null) + { + Button b1 = freeCameraCombo[0]; + Button b2 = freeCameraCombo[1]; + if (disableComboButton1) + { + if (!readInputsPostHook) + { + PadDown = MemoryUtil.Read(controllerAddr() + 0x198); + PadTrg = MemoryUtil.Read(controllerAddr() + 0x1A0); + PadRel = MemoryUtil.Read(controllerAddr() + 0x1A4); + PadChg = MemoryUtil.Read(controllerAddr() + 0x1A8); + lastPadDown = PadDown; + readInputsPostHook = true; + } + uint b1u = (uint)b1; + if (comboButton1Down || enableFreeCamera || !Input.IsDown(b2)) + { + if ((PadDown & b1u) == b1u) + { + comboButton1Down = true; + } + PadDown &= ~b1u; + MemoryUtil.WriteBytes(controllerAddr() + 0x198, BitConverter.GetBytes(PadDown)); + } + if (comboButton1Down) + { + if (((PadRel & b1u) == b1u)) + { + comboButton1Down = false; + } + PadTrg &= ~b1u; + PadRel &= ~b1u; + PadChg &= ~b1u; + MemoryUtil.WriteBytes(controllerAddr() + 0x1A0, BitConverter.GetBytes(PadTrg)); + MemoryUtil.WriteBytes(controllerAddr() + 0x1A4, BitConverter.GetBytes(PadRel)); + MemoryUtil.WriteBytes(controllerAddr() + 0x1A8, BitConverter.GetBytes(PadChg)); + } + } + if ((comboButton1Down || (!disableComboButton1 && Input.IsDown(b1))) && Input.IsPressed(b2)) + { + enableFreeCamera = !enableFreeCamera; + } + } + + if (enableFreeCamera) + { + if (!unlockMovementHeld && Input.IsPressed(Button.L2)) + { + unlockMovementHeld = true; + } + else if (unlockMovementHeld && Input.IsReleased(Button.L2)) + { + unlockMovementHeld = false; + unlockMovementPause = false; + } + if (unlockMovementHeld) + { + if (Input.IsPressed(Button.L1)) + { + unlockMovementToggled = !unlockMovementToggled; + } + // Temporarily disable for zoom mode. + if (Input.IsDown(Button.R2)) + { + unlockMovementPause = true; + } + else if (Input.IsReleased(Button.R2)) + { + unlockMovementPause = false; + } + } + + if (Input.IsDown(Button.L2) && Input.IsPressed(Button.R1)) + { + unlockInputToggled = !unlockInputToggled; + } + + if (Input.IsDown(Button.R2) && Input.IsPressed(Button.R1)) + { + if (uiToggled) + { + jmpOverUi.Disable(); + } + else + { + jmpOverUi.Enable(); + } + uiToggled = !uiToggled; + } + + if (!readInputsPostHook) + { + PadDown = MemoryUtil.Read(controllerAddr() + 0x198); + lastPadDown = PadDown; + } + + if (!unlockInputToggled) + { + if (!readInputsPostHook) + { + PadTrg = MemoryUtil.Read(controllerAddr() + 0x1A0); + PadRel = MemoryUtil.Read(controllerAddr() + 0x1A4); + PadChg = MemoryUtil.Read(controllerAddr() + 0x1A8); + readInputsPostHook = true; + } + PadDown &= ~((uint)Button.Up | (uint)Button.Down | (uint)Button.Left | (uint)Button.Right); + PadDown &= ~((uint)Button.Cross | (uint)Button.Circle | (uint)Button.Square | (uint)Button.Triangle); + //PadDown &= ~((uint)Button.R1 | (uint)Button.L1); + PadTrg &= ~((uint)Button.Up | (uint)Button.Down | (uint)Button.Left | (uint)Button.Right); + PadTrg &= ~((uint)Button.Cross | (uint)Button.Circle | (uint)Button.Square | (uint)Button.Triangle); + //PadTrg &= ~((uint)Button.R1 | (uint)Button.L1); + PadChg &= ~((uint)Button.Up | (uint)Button.Down | (uint)Button.Left | (uint)Button.Right); + PadChg &= ~((uint)Button.Cross | (uint)Button.Circle | (uint)Button.Square | (uint)Button.Triangle); + //PadChg &= ~((uint)Button.R1 | (uint)Button.L1); + MemoryUtil.WriteBytes(controllerAddr() + 0x198, BitConverter.GetBytes(PadDown)); + MemoryUtil.WriteBytes(controllerAddr() + 0x1A0, BitConverter.GetBytes(PadTrg)); + MemoryUtil.WriteBytes(controllerAddr() + 0x1A8, BitConverter.GetBytes(PadChg)); + // Left and right trigger. + MemoryUtil.WriteBytes(controllerAddr() + 0x1C0, BitConverter.GetBytes(0)); + MemoryUtil.WriteBytes(controllerAddr() + 0x1C1, BitConverter.GetBytes(0)); + } } } private float CheckMovementHook(int stickValue) { - if (!disableMod && freeCamera && !(unlockMovementHeld || unlockMovementToggled)) + if (disableMod) + { + return checkMovementHook!.Original(stickValue); + } +#if HOOK_ORDER_ASSERTS + debugLog($"CheckMovementHook() @ {frameTick}"); +#endif + if (freeCamera && !((unlockMovementHeld || unlockMovementToggled) && !unlockMovementPause)) { stickValue = 0; } return checkMovementHook!.Original(stickValue); } - private void disableAllHooks() + private void disableAllCollisionHooks() { if (disableExtraGravity) { @@ -783,7 +1261,7 @@ namespace MHWNewCamera { if (disableMod) { - disableAllHooks(); + disableAllCollisionHooks(); if (freeCamera) { disableFreeCamera(); @@ -802,13 +1280,58 @@ namespace MHWNewCamera player.Rotation.X = 0.0f; player.Rotation.Z = 0.0f; } + bool higherLodsEnabled = areLodFactorsSet(); + if (higherLodsEnabled) + { + setLodFactors(false); + } + if (doubleShadowRes) + { + doubleShadowResDisable(); + } + if (slightlySofterShadows) + { + slightlyHigherMinThreshold.Disable(); + } + if (softerShadows) + { + higherMinThreshold.Disable(); + } + if (largerFoliageSwayRange) + { + addressHigherValueForFoliageSway.Disable(); + } } + else + { + if (config.HigherLods) + { + setLodFactors(true); + } + if (doubleShadowRes) + { + doubleShadowResEnable(); + } + if (slightlySofterShadows) + { + slightlyHigherMinThreshold.Enable(); + } + if (softerShadows) + { + higherMinThreshold.Enable(); + } + if (largerFoliageSwayRange) + { + addressHigherValueForFoliageSway.Enable(); + } + } + config.DisableMod = disableMod; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { - ImGui.Text("Try to disable as much of the mod as possible."); + ImGui.Text("Try to disable as much as possible."); ImGui.EndTooltip(); } if (disableMod) return; @@ -832,8 +1355,6 @@ namespace MHWNewCamera ImGui.PopStyleVar(); } - ImGui.Separator(); - ImGui.PushID("Perspective"); float singleFov = (float)cameraFov; if (ImGui.DragFloat("Field of View", ref singleFov, 0.4f, 1.0f, 179.0f)) @@ -852,6 +1373,18 @@ namespace MHWNewCamera preDetachRoll = roll; } } + if (ImGui.Checkbox("Fade Objects When Close to Camera", ref fadeObjects)) + { + if (pCamera != null) + { + setFadeObjects(pCameraViewportIndex, fadeObjects); + } + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Credit to Otis_Inf."); + ImGui.EndTooltip(); + } if (ImGui.Button("Default")) { cameraFov = DEFAULT_FOV; @@ -860,7 +1393,16 @@ namespace MHWNewCamera cameraXOffset = 0.0f; cameraYOffset = 0.0f; cameraZOffset = 0.0f; - cameraRoll = 0.0f; + cameraRoll = 0.0; + if (preDetachRoll != null) + { + preDetachRoll = cameraRoll; + } + fadeObjects = true; + if (pCamera != null) + { + setFadeObjects(pCameraViewportIndex, fadeObjects); + } config.Selected = ""; ConfigManager.SaveConfig(this); } @@ -879,6 +1421,7 @@ namespace MHWNewCamera preset.Right = cameraRight; preset.Up = cameraYOffset; preset.Roll = cameraRoll; + preset.FadeObjects = pCamera != null ? getFadeObjects(pCameraViewportIndex) : true; if (config.Presets.ContainsKey(name)) { config.Presets[name] = preset; @@ -909,6 +1452,15 @@ namespace MHWNewCamera cameraRight = preset.Right; cameraYOffset = preset.Up; cameraRoll = preset.Roll; + if (preDetachRoll != null) + { + preDetachRoll = cameraRoll; + } + fadeObjects = preset.FadeObjects; + if (pCamera != null) + { + setFadeObjects(pCameraViewportIndex, fadeObjects); + } } if (isSelected) ImGui.SetItemDefaultFocus(); } @@ -931,7 +1483,7 @@ namespace MHWNewCamera ImGui.DragFloat("Camera Speed", ref cameraSpeed, 0.01f, 0.0f); if (ImGui.BeginItemTooltip()) { - ImGui.Text("Movement speed in freecam."); + ImGui.Text("Movement speed in free camera."); ImGui.EndTooltip(); } ImGui.DragFloat("Zoom Speed", ref cameraZoomSpeed, 0.01f, 0.0f); @@ -943,22 +1495,22 @@ namespace MHWNewCamera ImGui.DragFloat("Speed Modifier", ref cameraSpeedModifier, 0.01f, 0.0f); if (ImGui.BeginItemTooltip()) { - ImGui.Text("Value to multiply speed by when L2 is held."); + ImGui.Text("Value to multiply speed by when R2 is held."); ImGui.EndTooltip(); } ImGui.DragFloat("Camera Sensitivity", ref cameraSensitivity, 0.0025f, 0.0f); if (ImGui.BeginItemTooltip()) { - ImGui.Text("Camera look sensitivity in freecam."); + ImGui.Text("Camera look sensitivity in free camera."); ImGui.EndTooltip(); } float pitchLimit = (float)cameraPitchLimit; if (ImGui.InputFloat("Pitch Limit", ref pitchLimit, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue)) { cameraPitchLimit = pitchLimit; - if (cameraPitchLimit != -1.0f) + if (cameraPitchLimit != -1.0) { - cameraPitchLimit = Math.Clamp(cameraPitchLimit, 0.0f, 89.95f); + cameraPitchLimit = Math.Clamp(cameraPitchLimit, 0.0, Config.Settings.MAX_PITCH_LIMIT); } } if (ImGui.BeginItemTooltip()) @@ -1002,6 +1554,45 @@ namespace MHWNewCamera } ImGui.PopID(); + ImGui.PushID("Toggles"); + if (!freeCamera) + { + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); + } + ImGui.Checkbox("Unlock Player Movement", ref unlockMovementToggled); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("LT+LB"); + ImGui.EndTooltip(); + } + ImGui.Checkbox("Unlock Input", ref unlockInputToggled); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("LT+RB"); + ImGui.EndTooltip(); + } + if (!freeCamera) + { + ImGui.PopStyleVar(); + } + if (ImGui.Checkbox("Disable UI", ref uiToggled)) + { + if (uiToggled) + { + jmpOverUi.Enable(); + } + else + { + jmpOverUi.Disable(); + } + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("RT+RB. This will still show the scoutfly marker on menus."); + ImGui.EndTooltip(); + } + ImGui.PopID(); + ImGui.PushID("Binds"); if (ImGui.CollapsingHeader("Binds")) { @@ -1018,7 +1609,7 @@ namespace MHWNewCamera ImGui.SameLine(); if (freeCameraCombo == null) { - ImGui.PushStyleColor(ImGuiCol.Text, 0xff0000ff); + ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0000FF); } ImGui.PushItemWidth(width * 0.15f); ImGui.InputText("##Toggle Free Camera", ref typedCombo, 12); @@ -1043,6 +1634,12 @@ namespace MHWNewCamera ConfigManager.SaveConfig(this); } } + if (ImGui.Checkbox("Disable Button 1 Unless Button 2 is Held", ref disableComboButton1)) + { + comboButton1Down = false; + config.DisableComboButton1UnlessButton2Held = disableComboButton1; + ConfigManager.SaveConfig(this); + } } ImGui.PopID(); @@ -1052,10 +1649,133 @@ namespace MHWNewCamera ImGui.Checkbox("Debug Button", ref debugButton); if (ImGui.BeginItemTooltip()) { - ImGui.Text("Currently toggles how early camera Y position and FOV are set (off = earlier).\nIf you want to see why: go out, set a big \"Up\" offset, aim in your slinger and click this button on and off."); + ImGui.Text("Currently toggles how early camera Y position and FOV are set (off = earlier).\nIf you want to see why: Go out, set a large \"Up\" offset, aim in your slinger and click this button on and off."); + ImGui.EndTooltip(); + } + + ImGui.InputFloat("Unknown LOD Factor 1", ref unknownLod1); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Default: 1.0."); + ImGui.EndTooltip(); + } + ImGui.InputFloat("Unknown LOD Factor 2", ref unknownLod2); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Seems to control whether some objects are still drawn when very far from the camera.\nDefault: 1.0."); + ImGui.EndTooltip(); + } + ImGui.InputFloat("Foliage LOD Factor", ref foliageLodFactor); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("This can sometimes look a bit off when set high.\nDefault: 1.0."); + ImGui.EndTooltip(); + } + ImGui.InputFloat("Terrain/Object LOD Factor", ref terrainLodFactor); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Default: 1.0."); + ImGui.EndTooltip(); + } + bool higherLodsEnabled = areLodFactorsSet(); + if (ImGui.Checkbox("Higher LODs", ref higherLodsEnabled)) + { + setLodFactors(higherLodsEnabled); + config.HigherLods = higherLodsEnabled; + ConfigManager.SaveConfig(this); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Credit to Otis_Inf."); + ImGui.EndTooltip(); + } + + if (ImGui.Checkbox("2x Shadow Resolution (Requires Reload)", ref doubleShadowRes)) + { + if (doubleShadowRes) + { + doubleShadowResEnable(); + } + else + { + doubleShadowResDisable(); + } + config.DoubleShadowResolution = doubleShadowRes; + ConfigManager.SaveConfig(this); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Reload shadows by toggling \"Shadow Quality\" in the options."); ImGui.EndTooltip(); } + if (softerShadows) + { + ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); + } + if (ImGui.Checkbox("Slightly Softer Shadows", ref slightlySofterShadows)) + { + if (slightlySofterShadows) + { + slightlyHigherMinThreshold.Enable(); + } + else + { + slightlyHigherMinThreshold.Disable(); + } + config.SlightlySofterShadows = slightlySofterShadows; + ConfigManager.SaveConfig(this); + } + if (softerShadows) + { + ImGui.PopItemFlag(); + ImGui.PopStyleVar(); + } + + if (slightlySofterShadows) + { + ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); + } + if (ImGui.Checkbox("Softer Shadows", ref softerShadows)) + { + if (softerShadows) + { + higherMinThreshold.Enable(); + } + else + { + higherMinThreshold.Disable(); + } + config.SofterShadows = softerShadows; + ConfigManager.SaveConfig(this); + } + if (slightlySofterShadows) + { + ImGui.PopItemFlag(); + ImGui.PopStyleVar(); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("When 2x shadow resolution is enabled, this matches the original in-game \"High\" setting."); + ImGui.EndTooltip(); + } + + if (ImGui.Checkbox("Larger Foliage Sway Range", ref largerFoliageSwayRange)) + { + if (largerFoliageSwayRange) + { + addressHigherValueForFoliageSway.Enable(); + } + else + { + addressHigherValueForFoliageSway.Disable(); + } + config.LargerFoliageSwayRange = largerFoliageSwayRange; + ConfigManager.SaveConfig(this); + } + ImGui.PushID("Camera"); if (pCamera != null) { @@ -1076,6 +1796,16 @@ namespace MHWNewCamera ImGui.Text($"Pointer: {vp.Instance:x}"); ImGui.Text($"Visible: {vp.Visible}"); ImGui.Text($"Region: {vp.Region.X} {vp.Region.Y} {vp.Region.Width} {vp.Region.Height}"); + bool fadingObjects = getFadeObjects(i); + if (ImGui.Checkbox("Fade Objects When Close to Camera", ref fadingObjects)) + { + setFadeObjects(i, fadingObjects); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Credit to Otis_Inf."); + ImGui.EndTooltip(); + } if (vp.Camera != null) { ImGui.InputFloat("X Offset", ref cameraXOffset); @@ -1127,12 +1857,20 @@ namespace MHWNewCamera } } ImGui.SameLine(); - if (ImGui.BeginCombo("##Positions", "")) + if (ImGui.BeginCombo("##Positions", selectedPositionName)) { Dictionary.KeyCollection positionKeys = config.Positions.Keys; - for (int j = 0; j < positionKeys.Count; j++) + for (int j = 0; j < positionKeys.Count + 1; j++) { - string positionKey = positionKeys.ElementAt(j); + if (j == 0) + { + if (ImGui.Selectable("(Deselect)")) + { + selectedPositionName = ""; + } + continue; + } + string positionKey = positionKeys.ElementAt(j - 1); if (ImGui.Selectable(positionKey)) { Config.SavedPosition pos = config.Positions[positionKey]; @@ -1225,6 +1963,22 @@ namespace MHWNewCamera } ImGui.PopID(); + ImGui.Separator(); + + if (ImGui.Checkbox("Disable Character/Palico Fade", ref disableCharacterFade)) + { + if (disableCharacterFade) + { + noopCharacterFade.Enable(); + } + else + { + noopCharacterFade.Disable(); + } + config.DisableCharacterFade = disableCharacterFade; + ConfigManager.SaveConfig(this); + } + ImGui.PushID("Player"); Player? player = Player.MainPlayer; if (player != null) @@ -1402,7 +2156,7 @@ namespace MHWNewCamera /* // https://github.com/HunterPie/HunterPie/blob/fa73f81ed0cdc921a6cf63f96c0fcff3688d88c2/HunterPie.Integrations/Datasources/MonsterHunterWorld/Entity/Game/MHWGame.cs#L74 bool playerInMenu = false; - nint offset = MemoryUtil.Read(0x1451c4640); + nint offset = MemoryUtil.Read(0x1451C4640); if (offset != 0) { offset += 0x13FD0; @@ -1441,12 +2195,12 @@ namespace MHWNewCamera ImGui.PushID("Pad"); ImGui.Text("Pad:"); ImGui.Text($"Pointer: {controllerAddr():x}"); - int PadRx = MemoryUtil.Read(controllerAddr() + 0x1b0); - int PadRy = MemoryUtil.Read(controllerAddr() + 0x1b4); - int PadLx = MemoryUtil.Read(controllerAddr() + 0x1b8); - int PadLy = MemoryUtil.Read(controllerAddr() + 0x1bc); - byte PadRz = MemoryUtil.Read(controllerAddr() + 0x1c0); - byte PadLz = MemoryUtil.Read(controllerAddr() + 0x1c1); + int PadRx = MemoryUtil.Read(controllerAddr() + 0x1B0); + int PadRy = MemoryUtil.Read(controllerAddr() + 0x1B4); + int PadLx = MemoryUtil.Read(controllerAddr() + 0x1B8); + int PadLy = MemoryUtil.Read(controllerAddr() + 0x1BC); + byte PadRz = MemoryUtil.Read(controllerAddr() + 0x1C0); + byte PadLz = MemoryUtil.Read(controllerAddr() + 0x1C1); ImGui.Text("Left Stick:"); ImGui.Text($" X: {PadLx}"); ImGui.Text($" Y: {PadLy}"); @@ -1462,71 +2216,18 @@ namespace MHWNewCamera ImGui.PopID(); } - private void checkUnlockMovement() - { - if (!unlockMovementHeld && Input.IsPressed(Button.R2)) - { - unlockMovementHeld = true; - } - else if (unlockMovementHeld && Input.IsReleased(Button.R2)) - { - unlockMovementHeld = false; - } - if (unlockMovementHeld && Input.IsPressed(Button.L1)) - { - unlockMovementToggled = !unlockMovementToggled; - } - if (Input.IsDown(Button.R2)) - { - if (Input.IsDown(Button.L2)) - { - if (unlockMovementHeld) - { - unlockMovementHeld = false; - } - if (unlockMovementToggled) - { - unlockMovementToggled = false; - } - } - else if (Input.IsReleased(Button.L2)) - { - unlockMovementHeld = true; - } - } - } - - private void checkPlayerChange() - { - Player? player = Player.MainPlayer; - if (player != lastPlayer) - { - pCamera = null; - lastPlayer = player; - } - } - public void OnUpdate(float deltaTime) { if (disableMod) return; +#if HOOK_ORDER_ASSERTS + Trace.Assert(hookOrder == 0 || hookOrder == 3); + hookOrder = 0; + frameTick++; +#endif + // Consider that pCamera could become an invalid pointer. checkPlayerChange(); - - if (enableCombo && freeCameraCombo != null) - { - Button b1 = freeCameraCombo[0]; - Button b2 = freeCameraCombo[1]; - if ((!Input.IsPressed(b1) && Input.IsDown(b1)) && Input.IsPressed(b2)) - { - enableFreeCamera = !enableFreeCamera; - } - } - - if (freeCamera) - { - checkUnlockMovement(); - } } } } -- cgit v1.2.3-101-g0448