diff options
| author | 2025-10-11 18:16:04 -0400 | |
|---|---|---|
| committer | 2025-10-11 18:16:04 -0400 | |
| commit | ec7145dd87b1ba12c2f67f6204c138f651210a5f (patch) | |
| tree | 563a9ec52be6103dc96a6a8036e1e4e8ae03341a | |
| parent | 353023e77af45f1f1a719d76b6a03f6343d99737 (diff) | |
| download | NewCamera-ec7145dd87b1ba12c2f67f6204c138f651210a5f.tar.gz NewCamera-ec7145dd87b1ba12c2f67f6204c138f651210a5f.tar.bz2 NewCamera-ec7145dd87b1ba12c2f67f6204c138f651210a5f.zip | |
Add graphical enhancements and lots of fixes
Signed-off-by: Andrew Opalach <andrew@akon.city>
| -rwxr-xr-x | Config.cs | 13 | ||||
| -rwxr-xr-x | Plugin.cs | 1151 |
2 files changed, 938 insertions, 226 deletions
@@ -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<string, Button> buttonMap = new Dictionary<string, Button>
{
@@ -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<String, Preset> Presets { get; set; } = new Dictionary<String, Preset>();
public String Selected { get; set; } = "";
public Dictionary<String, SavedPosition> Positions { get; set; } = new Dictionary<String, SavedPosition>();
+
+ 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;
}
}
@@ -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<SetCameraDelegate>? setCameraHook;
- private delegate void SetCameraTentDelegate(nint unknownPtr);
- private Hook<SetCameraTentDelegate>? setCameraTentHook;
-
private delegate void CalculateCameraDelegate(nint unknownPtr);
private Hook<CalculateCameraDelegate>? calculateCameraHook;
- private delegate void CameraUpDelegate(nint unknownPtr);
- private Hook<CameraUpDelegate>? cameraUpHook;
+ private delegate void SetCameraTentDelegate(nint unknownPtr);
+ private Hook<SetCameraTentDelegate>? setCameraTentHook;
+
+ private delegate void WritePadInputDelegate(nint unknownPtr, nint unknownPtr2, nint unknownPtr3);
+ private Hook<WritePadInputDelegate>? writePadInputHook;
private delegate float CheckMovementDelegate(int stickValue);
private Hook<CheckMovementDelegate>? 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<Config>(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<Config>(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<SetCameraDelegate>(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<CalculateCameraDelegate>(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<SetCameraTentDelegate>(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<CalculateCameraDelegate>(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<CameraUpDelegate>(addr, CameraUpHook);
+ writePadInputHook = Hook.Create<WritePadInputDelegate>(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<CheckMovementDelegate>(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<float>(0x14239CF98) == 4096.0f);
+ Trace.Assert(MemoryUtil.Read<float>(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<Config>(this);
+ if (config.HigherLods)
+ {
+ setLodFactors(true);
+ }
+ }
+
+ // Credit to Otis_Inf.
+ private bool getFadeObjects(int viewportIndex)
+ {
+ Viewport vp = CameraSystem.GetViewport(viewportIndex);
+ return MemoryUtil.Read<byte>(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<nint>(0x1451C4368);
+ float lod1 = MemoryUtil.Read<float>(baseAddr + 0x224);
+ float lod2 = MemoryUtil.Read<float>(baseAddr + 0x228);
+ float lod3 = MemoryUtil.Read<float>(baseAddr + 0x234);
+ float lod4 = MemoryUtil.Read<float>(baseAddr + 0x24C);
+ return lod1 == unknownLod1 && lod2 == unknownLod2 && lod3 == foliageLodFactor && lod4 == terrainLodFactor;
+ }
+
+ private void setLodFactors(bool toggleOn)
+ {
+ nint baseAddr = MemoryUtil.Read<nint>(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<nint>(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<nint>(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<int>(controllerAddr() + 0x1bc);
+ int PadLy = MemoryUtil.Read<int>(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<int>(controllerAddr() + 0x1bc);
+ int PadLy = MemoryUtil.Read<int>(controllerAddr() + 0x1BC);
if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0;
- int PadLx = MemoryUtil.Read<int>(controllerAddr() + 0x1b8);
+ int PadLx = MemoryUtil.Read<int>(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<int>(controllerAddr() + 0x1b0);
+ int PadRx = MemoryUtil.Read<int>(controllerAddr() + 0x1B0);
if (Math.Abs(PadRx) < stickDeadzone) PadRx = 0;
- int PadRy = MemoryUtil.Read<int>(controllerAddr() + 0x1b4);
+ int PadRy = MemoryUtil.Read<int>(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<int>(pCamera.Instance + 0x240);
+ if (previousCameraAnimState == 5)
{
- previousCameraAnimState = MemoryUtil.Read<int>(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<uint>(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<uint>(controllerAddr() + 0x198);
+ PadTrg = MemoryUtil.Read<uint>(controllerAddr() + 0x1A0);
+ PadRel = MemoryUtil.Read<uint>(controllerAddr() + 0x1A4);
+ PadChg = MemoryUtil.Read<uint>(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<uint>(controllerAddr() + 0x198);
+ lastPadDown = PadDown;
+ }
+
+ if (!unlockInputToggled)
+ {
+ if (!readInputsPostHook)
+ {
+ PadTrg = MemoryUtil.Read<uint>(controllerAddr() + 0x1A0);
+ PadRel = MemoryUtil.Read<uint>(controllerAddr() + 0x1A4);
+ PadChg = MemoryUtil.Read<uint>(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<Config>(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<Config>(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<Config>(this);
}
}
+ if (ImGui.Checkbox("Disable Button 1 Unless Button 2 is Held", ref disableComboButton1))
+ {
+ comboButton1Down = false;
+ config.DisableComboButton1UnlessButton2Held = disableComboButton1;
+ ConfigManager.SaveConfig<Config>(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<Config>(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<Config>(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<Config>(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<Config>(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<Config>(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<string, Config.SavedPosition>.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<Config>(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<nint>(0x1451c4640);
+ nint offset = MemoryUtil.Read<nint>(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<int>(controllerAddr() + 0x1b0);
- int PadRy = MemoryUtil.Read<int>(controllerAddr() + 0x1b4);
- int PadLx = MemoryUtil.Read<int>(controllerAddr() + 0x1b8);
- int PadLy = MemoryUtil.Read<int>(controllerAddr() + 0x1bc);
- byte PadRz = MemoryUtil.Read<byte>(controllerAddr() + 0x1c0);
- byte PadLz = MemoryUtil.Read<byte>(controllerAddr() + 0x1c1);
+ int PadRx = MemoryUtil.Read<int>(controllerAddr() + 0x1B0);
+ int PadRy = MemoryUtil.Read<int>(controllerAddr() + 0x1B4);
+ int PadLx = MemoryUtil.Read<int>(controllerAddr() + 0x1B8);
+ int PadLy = MemoryUtil.Read<int>(controllerAddr() + 0x1BC);
+ byte PadRz = MemoryUtil.Read<byte>(controllerAddr() + 0x1C0);
+ byte PadLz = MemoryUtil.Read<byte>(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();
- }
}
}
}
|