//#define ADDR_ASSERTS //#define HOOK_ORDER_ASSERTS //#define LOG_DEBUG_MESSAGES #define MOUSE_AND_KEYBOARD_LAYER //#define SHADER_FEATURES //#define QUARANTINED_FEATURES using ImGuiNET; using System.Numerics; using System.Runtime.InteropServices; #if ADDR_ASSERTS || HOOK_ORDER_ASSERTS using System.Diagnostics; #endif using SharpPluginLoader.Core; using SharpPluginLoader.Core.Entities; using SharpPluginLoader.Core.IO; using SharpPluginLoader.Core.View; using SharpPluginLoader.Core.Memory; using SharpPluginLoader.Core.Actions; using SharpPluginLoader.Core.Components; using SharpPluginLoader.Core.Configuration; // Tentative List of Actions: // - Toggle Free Camera // - Unlock Player Movement // - Lock Camera Vertical Movement // - Apply Speed Modifier // - Unlock Input // - Toggle UI // - Toggle Depth of Field // - Toggle Motion Blur // - Toggle Reduced Near Clip // - Translate Camera // - Roll Camera // - Reset Roll // - Zoom // - Reset Zoom // - Teleport Player to Camera // - Teleport Camera to Player // - Crawl // - Sit in Hot Springs // - Adjust SSAO/General A/B Graphical Tweaks // - Freeze Game // - Exit Free Camera // - Open Gestures Menu // - Open Poses Menu // @TODO: // - Attempt to document all test cases I can think of. // - Better hook for renderer params. // - Centralize all bindings to get a better idea of how to structure custom binds. // - Use GetRef<>. // - Hide Hunter's Knife/Slinger. // - General "A/B Graphical Settings" function. // - Save toggle state to config file. // - Include Hide Weapon. // - Hunter effects: // - Sweating // - Steamy // - On Fire // - Dung Pod? // - Other Monster Inflicted Debuffs // - Camera "Gear Shift". // - Option to not adjust camera position on camera change. // - Better calculation for positioning camera behind the player. // - Underwater camera crashes in The Rotten Vale. // - Adjust SSAO in cutscenes. // - Read LOD bias setting from in-game setting (Low, Medium or High). // - Make left stick input a curve like Wilds. // - Deadzone? MonsterHunterWorld.exe+5831DB - comiss xmm1,[MonsterHunterWorld.exe+503C438] // - Ability to lock camera to a the player/a joint. // - Simplify and document input handling/blocking logic. // - Find a way to block other inputs while button1 is down (and blocked). // - More multiple controller testing (3 controllers, Steam Input, Windows). // - Thoroughly test "Disable Mod". // - Improve AOB scans. // - Better name for unknownPtr. // - Some objects still fade. // - Glass objects in research base and on the botanical research center table. // - Decals on floor near Astera lift. // - Hanging objects in the Seliana Gathering Hub (some events). // - Manully set free camera viewport index. // - Option to override in-game viewmode. // Known Issues: // - Broken shadow areas due to game bug (more noticeable with increased shadow bias): // - Exit of central camp in Horfrost Reach. // - Sporepuff area in The Ancient Forest. // - Wildspire Waste entrence to enclosed area past the waterfall. // - The Rotten Vale jump out of Southeast Camp. Wall on the opposite side slightly to the left. // - Camera pitch wrap around while in the tent will sometimes flicker at the point of wrapping. // - Likely due to the unpredictable position of SetCameraTentHook() in the chain of hooks. Updating // free camera state within SetCameraTentHook() is not a solution because it comes out laggy. // - With Passive mode enabled out in the field, if you go into a tent, change equipment and quickly leave // the tent the game freezes/uses the wrong camera. // Steam proton launch command: // env DOTNET_ROOT="" WINEDLLOVERRIDES="msvcrt,dinput8=n,b" %command% // Test cases: // Offset Perspective: // - For all cases roll should an extra consideration. // Constant FOV: // - In quest book/board GUI (uses player camera). // previousCameraAnimState = 8 (FOV Only): // - Push through roots. // previousCameraAnimState = 5 (FOV Only): // - Zoom into quest board or The Handler's book. // - Open map animation. // - Entering/Leaving tent. // previousCameraAnimState = 4 (FOV Only): // - Quest depart/return. // - Traveling on the lift in Astera. // previousCameraAnimState = 2 (Apply offset): // - Point camera towards quest board. // - Crawl under object. // Player camera is the target of a transition: // - Leaving dialoge with NPC (The Handler, The Smithy, pub lasses, etc). // - Getting up from hot spring. // - Getting up from canteen. // - Getting up from cart. // - Seasonal gathering hub cutscene. // Directly moves player camera: // - Look at monster. // - Scoutflies point in a direction. // - Mount monster. // - Dive. // // 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 { public struct SSAOParameters { public float depthBias; // +0xB4B0 public float slopedDepthBias; // +0xB4B4 public float maxDepthBias; // +0xB4B8 public float dispersion; // +0xB4BC public float effect; // +0xB430 public float effectGI; // +0xB434 public float depthDifference; // +0xB4C0 public float samplesPerPixel; // +0xB4C4 public int maxSampleNum; // +0xB4C8 public int maxSampleNumHQ; // +0xB4D0 public float radius; // +0xB4D4 public float bias; // +0xB4D8 public float intensity; // +0xB4E0 public bool useHiZ; // +0xB4E5 public float edgeAttenRate; // +0xB4DC }; public struct SSLRParameters { public int loopCount; // +0xE628 public float loopCountFactorForCBR; // +0xE62C public float eliminateDepth; // +0xE630 public float accurateThreshold; // +0xE644 public float accurateThresholdHQ; // +0xE64C public float ditherRadius; // +0xE634 public float importanceBias; // +0xE638 public float mipScale; // +0xE63C public float mipBias; // +0xE640 public bool ditherResolve; // +0xB43F public float edgeAttenRate; // +0xB428 public int mip0CountThreshold; // +0xB438 public float depthEliminateRate; // +0xB42C public bool useMipmap; // +0xE650 public bool gBufferJitter; // +0xB440 }; public struct DOFParameters { public bool enabled; // +0x1DD public bool newVersion; // +0x1DC public float fNumber; // +0x1A0 public float sensorSize; // +0x1A4 public float focusDistance; // +0x1A8 public float nearCoef; // +0x1CC public float farCoef; // +0x1C8 public bool nearEnable; // +0x1DE public bool farEnable; // +0x1DF public bool debugDraw; // +0x1E0 public float radius; // +0x1D0 public float depthScaleForeground; // +0x1D4 public float aspect; // +0x1D8 public bool vignettingEnabled; // +0x200 public bool vignettingEllipse; // +0x201 public float vignettingEllipticity; // +0x204 public float vignettingOffset; // +0x1F8 public float vignettingPow; // +0x1FC public int vignettingColor; // +0x208 }; public enum ZoneState : int { Unknown = 0, Hub = 1, Combat = 2 }; public unsafe class Plugin : IPlugin { public string Name => "MHW New Camera"; public string Author => "Akon City Software"; private const float DEFAULT_FOV = 60.0f; private const float DEFAULT_NEAR_CLIP = 16.0f; private static byte byteFlag(bool f) { return f ? (byte)0x1 : (byte)0x0; } private bool disableMod = false; private static readonly MtObject sMain = SingletonManager.GetSingleton("sMhMain")!; private static readonly MtObject sUmbra = SingletonManager.GetSingleton("sUmbra")!; private bool freezeGame = false; private bool decoupleDtFromGameTime = false; private int advanceFrame = 0; private float cameraSpeed; private float cameraSpeedModifier; private float cameraSensitivity; private float cameraZoomSpeed; private float cameraPitchLimit; private int stickDeadzone; private float alternateNearClip; private float cameraFov = DEFAULT_FOV; private float cameraForward = 0.0f; private float cameraRight = 0.0f; private float cameraUp = 0.0f; private Vector3 cameraOffset; private float cameraYaw = 0.0f; private float cameraPitch = 0.0f; private float cameraRoll = 0.0f; private bool disableFading = false; private int cameraWrapState = 0; private bool enableFreeCamera = false; private bool freeCamera = false; private bool freeCameraFromViewMode = false; private bool freeCameraFallback = false; private Camera? vCamera = null; private int vCameraViewportIndex = -1; private float? restoreFov = null; private float? restoreRoll = null; private float? restoreNearClip = null; private Vector3 cameraPosition; private Vector3 cameraTarget; private Vector3 cameraFrame; private bool unlockMovementHeld = false; private bool unlockMovementToggled = false; private bool unlockMovementPause = false; private bool playerMovementLocked => !(unlockMovementHeld || unlockMovementToggled) || unlockMovementPause; private bool lockVerticalToggled = false; private bool orbitPlayer = false; private bool orbitIgnoreCamera = false; private float orbitMovementRotation = 0.0f; private float orbitDistance = 350.0f; private float orbitY = 150.0f; private bool enableOffsetPerspective = false; private bool offsetPerspective = 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; private bool enableCombo = false; private Button[]? freeCameraCombo = null; private bool disableComboButton1 = false; private bool comboButton1Down = false; private static readonly MtObject sMhSteamController = SingletonManager.GetSingleton("sMhSteamController")!; private nint controllerAddr() => sMhSteamController.Instance; private nint primaryPad = 0x0; private int PadLx, PadLy; private int PadRx, PadRy; private uint lastPadDown = 0u; private uint? prevPadDown = null; private bool unlockInputToggled = false; private bool unlockInputForMenu = false; private bool unlockInputHideMenu = false; //private bool inputBlockedForToggle = false; private bool buttonWasDown(Button button) { return (lastPadDown & (uint)button) == (uint)button; } private bool buttonWasPressed(Button button) { return (lastPadDown & (uint)button) == (uint)button && (prevPadDown & (uint)button) != (uint)button; } private bool buttonWasReleased(Button button) { return (lastPadDown & (uint)button) != (uint)button && (prevPadDown & (uint)button) == (uint)button; } #if MOUSE_AND_KEYBOARD_LAYER private static readonly MtObject sMhMouse = SingletonManager.GetSingleton("sMhMouse")!; private static readonly MtObject sMhKeyboard = SingletonManager.GetSingleton("sMhKeyboard")!; private bool mouseEnabled = false; private float mouseSensitivity; private bool keyboardEnabled = false; private int keyboardLookValue; #endif private float plusRight = 0.0f; private float plusForward = 0.0f; private delegate void ProcessCameraDelegate(nint cameraPointer); private Hook? setCameraHook; private Hook? calculateCameraHook; private Hook? checkCameraHook; private delegate void ViewModeDelegate(nint viewModeObject); private Hook? startViewModeHook; private bool overrideViewMode = false; /* private NativeAction startViewMode; private NativeAction stopViewMode; private NativeAction processViewMode; private Patch viewMode1; private Patch viewMode1_1; private Patch viewMode2; private Patch viewMode3; private Patch viewMode4; private nint psuedoViewModeObject; */ private NativeAction setupGestureMenu; private NativeAction showGestureMenu; private delegate void SetCameraTentDelegate(nint unknownPtr); private Hook? setCameraTentHook; private delegate void SetCameraCutsceneDelegate(nint unknownPtr); private Hook? setCameraCutsceneHook; /* private delegate void CalculateViewDelegate(nint unknownPtr); private Hook? calculateViewHook; */ private delegate void ShadowCascadeDelegate(nint unknownPtr, nint unknownPtr2); private Hook? shadowCascadeHook; private delegate void RendererSetDelegate(nint unknownPtr, nint unknownPtr2, nint unknownPtr3); private Hook? rendererSetHook; private delegate void WritePadInputDelegate(nint unknownPtr, nint unknownPtr2, nint unknownPtr3); private Hook? writePadInputHook; private delegate float CheckMovementDelegate(int stickValue, float alwaysZero); private Hook? checkMovementHook; private delegate void CollisionCheckDelegate(nint unknownPtr, nint unknownPtr2); private Hook? collisionCheckHook; private bool motionBlurDisabled = false; private bool motionBlurWasDisabled; private delegate void MotionBlurDelegate(nint unknownPtr, nint unknownPtr2); private Hook? motionBlurHook; private bool dofDisabled = false; private DOFParameters dofParams; private bool fillOutDofParams = true; private bool applyVignettingParams = false; private bool fillOutVignettingParams = true; private delegate void DofUpdateDelegate(nint unknownPtr); private Hook? dofHook; private delegate void CameraEffectDelegate(nint unknownPtr, nint unknownPtr2, nint unknownPtr3); private Hook? cameraEffectHook; private bool higherVolumeQuality = false; private Patch value2ForVolumeQuality; private bool disableVolumeDownsample = false; private Patch volumeSars1; private Patch volumeSars2; private Patch volumeSars3; private Patch volumeSars4; private Patch volumeSars5; private Patch volumeSars6; private Patch volumeSars7; private Patch volumeSars8; private Patch volumeSars9; private delegate nint CreateLightingObject(nint unknownPtr); private delegate nint DestroyLightingObject(nint unknownPtr, nint unknownPtr2); private Hook? createLightingObject; private Hook? destroyLightingObject; private nint lightingObject = 0x0; private delegate nint CreateFXAAObject(nint unknownPtr, int unknownInt); private delegate nint DestroyFXAAObject(nint unknownPtr, int unknownInt); private Hook? createFXAAObject; private Hook? destroyFXAAObject; private nint fxaaObject = 0x0; private Patch swapMinimapFollowsCamera; private bool uiToggled = false; private Patch jmpOverUi; private Patch jmpOverDof; private bool disableCharacterFade = false; private Patch noopCharacterFade; private bool tripleShadowRes = false; private bool lowShadowDetailOverride = false; private Patch shadowRes1_3x; private Patch shadowRes1_1; private Patch shadowRes1_2; private Patch shadowRes1_3; private Patch shadowRes2; private Patch shadowRes3; //private Patch shadowRes4_Limit; private float shadowBiasOffset = 0.0f; private float shadowRadiusOffset = 0.0f; private bool applyShadowBias = false; private bool applyShadowRadius = false; private float lastShadowBias = -1.0f; private float lastShadowRadius = -1.0f; private nint lastShadowCascadeValue = -1; private bool applyShadowAdjust = false; private float lastShadowDistance; private float lastShadowDistribution; private float lastShadowBackforwardDistance; //private float lastBroadAreaShadowRange; //private float lastShadowFov; private float shadowDistance = 5000.0f; private float shadowDistribution = 0.200000003f; private float shadowBackforwardDistance = 15000.0f; //private float broadAreaShadowRange = 50000.0f; //private float shadowFov = 40.0f; private void tripleShadowResEnable() { shadowRes1_3x.Enable(); shadowRes1_1.Enable(); shadowRes1_2.Enable(); shadowRes1_3.Enable(); shadowRes2.Enable(); shadowRes3.Enable(); //shadowRes4_Limit.Enable(); } private void tripleShadowResDisable() { shadowRes1_3x.Disable(); shadowRes1_1.Disable(); shadowRes1_2.Disable(); shadowRes1_3.Disable(); shadowRes2.Disable(); shadowRes3.Disable(); //shadowRes4_Limit.Disable(); } private int internalShadowSampleNumHQ; // +0xE5CC //private int shadowSampleNumHQ = 32; private bool ssaoAdjustments = false; private bool ssaoB = false; private SSAOParameters internalSSAOParams; //private SSAOParameters aSSAOParams; //private SSAOParameters bSSAOParams; private bool ssrAdjustments = false; private SSLRParameters internalSSRParams; private bool enableHQMode = false; private float foliageLODBias; private float terrainLODBias; private float prevFoliageLODBias = 0.0f; private float prevTerrainLODBias = 0.0f; private float foliageLODFactor; private float terrainLODFactor; private float internalSnowField4GlobalLODParam = 0.0f; // +0x5718 private float snowField4GlobalLODParam = 8.0f; //private float snowField4AllowTesselationHQ; // +0x5741 //private float snowField4LODBiasHQ; // +0x5748 private bool applyLODFactors; private bool disableLODLimits = false; private Patch defaultViewModeLODLimit; private Patch defaultViewModeLODLimit_1; private Patch defaultViewModeLODLimit_2; private void disableLODLimitsEnable() { defaultViewModeLODLimit.Enable(); defaultViewModeLODLimit_1.Enable(); defaultViewModeLODLimit_2.Enable(); } private void disableLODLimitsDisable() { defaultViewModeLODLimit.Disable(); defaultViewModeLODLimit_1.Disable(); defaultViewModeLODLimit_2.Disable(); } private bool largerFoliageSwayRange = false; private Patch addressHigherValueForFoliageSway; private bool disableReducedRateAnimations = false; private Patch zeroFrameSkip; private bool enableUnderwaterCamera = false; private Patch underwaterCamera1; private Patch underwaterCamera2; private Patch underwaterCamera3; private Patch underwaterCamera4; private Patch underwaterCamera5; private delegate void UnderwaterCheckDelegate(nint unknownPtr); private Hook? underwaterCheckHook; private bool cameraIsUnderwater = false; private void underwaterCameraEnable() { underwaterCamera1.Enable(); underwaterCamera2.Enable(); underwaterCamera3.Enable(); underwaterCamera4.Enable(); underwaterCamera5.Enable(); } private void underwaterCameraDisable() { underwaterCamera1.Disable(); underwaterCamera2.Disable(); underwaterCamera3.Disable(); underwaterCamera4.Disable(); underwaterCamera5.Disable(); } private bool hideWeapon = false; private bool disableCollision = false; private bool disableExtraCollision = false; private bool disableGravity = false; private bool disableExtraGravity = false; private Patch disableXCollision; private Patch disableYCollision; private Patch disableSecondaryYCollision; private Patch disableZCollision; private Patch disableExtraYCollision; private Patch disableGravityYUpdate; private Patch disableGravityXZUpdate; private Patch disableGravityEval; private void disableCollisionEnable() { disableXCollision.Enable(); disableYCollision.Enable(); disableSecondaryYCollision.Enable(); disableZCollision.Enable(); } private void disableCollisionDisable() { disableXCollision.Disable(); disableYCollision.Disable(); disableSecondaryYCollision.Disable(); disableZCollision.Disable(); } private void disableExtraCollisionEnable() { disableExtraYCollision.Enable(); } private void disableExtraCollisionDisable() { disableExtraYCollision.Disable(); } private void disableGravityEnable() { disableGravityYUpdate.Enable(); } private void disableGravityDisable() { disableGravityYUpdate.Disable(); } private void disableExtraGravityEnable() { disableGravityEval.Enable(); } private void disableExtraGravityDisable() { disableGravityEval.Disable(); } private bool allowHotSpringsAnywhere = false; private Patch jmpOverHotSpringsEval; private bool disableHotSpringsSteam = false; private Patch jmpOverHotSpringsSteam; #if QUARANTINED_FEATURES private ZoneState forceZoneState = ZoneState.Unknown; private ZoneState lastZoneState = ZoneState.Unknown; private NativeAction setZoneState; private NativeAction setPlayerController1; private NativeAction setPlayerController5; private delegate void ZoneStateDelegate(nint player, int flags); private Hook? setZoneStateHook; private bool zoneStateManualInvoke = false; private bool forcePassiveInCombatZone = false; private Patch zoneStateForcePassive1; private Patch zoneStateForcePassive2; private bool forceCombatInPassiveZone = false; private Patch zoneStateForceCombat1; private Patch zoneStateForceCombat2; #endif private bool enableCrawl = false; private NativeAction procEnvironmentCollision; private nint psuedoObject1; private nint psuedoObject2; private float playerOpacityOverride = 1.0f; private delegate void EntityParamsDelegate(nint entity, nint unknownPtr2); private Hook? refreshEntityParams; private bool applyCharacterWetness = false; private Patch noopCharacterWetnessUpdate; private float wholeBodyWetness = 0.0f; private static readonly MtObject sOtomo = SingletonManager.GetSingleton("sOtomo")!; // Gui strings. private string typedCombo = ""; private string typedPresetName = ""; private string typedPositionName = ""; private string selectedPositionName = ""; #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); disableMod = config.DisableMod; overrideViewMode = config.OverrideViewMode; Config.Settings.Binds binds = config.Binds; enableCombo = binds.EnableCombo; freeCameraCombo = Config.ParseCombo(binds.FreeCameraCombo); typedCombo = binds.FreeCameraCombo.Replace(",", "+"); disableComboButton1 = binds.DisableComboButton1UnlessButton2Held; #if MOUSE_AND_KEYBOARD_LAYER mouseEnabled = binds.EnableMouse; mouseSensitivity = binds.MouseSensitivity; keyboardEnabled = binds.EnableKeyboard; keyboardLookValue = binds.KeyboardLookSensitivity; #endif Config.Settings camera = config.Camera; cameraSpeed = camera.Speed; cameraSpeedModifier = camera.SpeedModifier; cameraSensitivity = camera.Sensitivity; cameraZoomSpeed = camera.ZoomSpeed; cameraPitchLimit = camera.PitchLimit; if (cameraPitchLimit != -1.0f) { cameraPitchLimit = Math.Clamp(cameraPitchLimit, 0.0f, Config.Settings.MAX_PITCH_LIMIT); } stickDeadzone = camera.StickDeadzone; alternateNearClip = camera.AlternateNearClip; // @TODO: offsetPerspective doesn't affect disableCharacterFade when it is supposed to. enableOffsetPerspective = config.PerspectiveCameraEnabled; Config.GraphicalTweaks graphics = config.Graphics; tripleShadowRes = graphics.TripleShadowResolution; shadowBiasOffset = graphics.ShadowRangeOffset; shadowRadiusOffset = graphics.ShadowRadiusOffset; applyShadowBias = graphics.ApplyShadowRange; applyShadowRadius = graphics.ApplyShadowRadius; //lowShadowDetailOverride = graphics.HigherShadowDetailInHoarfrost; enableHQMode = graphics.EnableHQMode; disableVolumeDownsample = graphics.FullResolutionVolumeBlur; higherVolumeQuality = graphics.HigherThanHighestVolumeRendering; ssaoAdjustments = enableHQMode; ssrAdjustments = enableHQMode; disableLODLimits = graphics.DisableLODLimits; largerFoliageSwayRange = graphics.LargerFoliageSwayRange; disableReducedRateAnimations = graphics.DisableReducedRateAnimations; ConfigManager.SaveConfig(this); return config; } public void OnPreMain() { Config config = loadConfig(); #if QUARANTINED_FEATURES // MonsterHunterWorld.exe+20354F7 - call MonsterHunterWorld.exe+1F73850 setZoneState = new NativeAction(0x142035020); setPlayerController1 = new NativeAction(0x141F73850); setPlayerController5 = new NativeAction(0x14118DDC0); setZoneStateHook = Hook.Create(0x142035020, SetZoneStateHook); // nint, int unchecked { zoneStateForcePassive1 = new Patch((nint)0x140256A3F + 0x6, [0x1]); zoneStateForcePassive2 = new Patch((nint)0x141AC2865 + 0x6, [0x1]); zoneStateForceCombat1 = new Patch((nint)0x141AC2938 + 0x6, [0x0]); zoneStateForceCombat2 = new Patch((nint)0x141AC28EC + 0x6, [0x0]); } #endif procEnvironmentCollision = new NativeAction(0x141F737D0); psuedoObject1 = (nint)NativeMemory.AllocZeroed(0x7C); MemoryUtil.WriteBytes(psuedoObject1 + 0x30, [0x03]); psuedoObject2 = (nint)NativeMemory.AllocZeroed(0x7C); MemoryUtil.WriteBytes(psuedoObject2 + 0x30, [0x08]); // Asserts based on version 15.23.00. // @TODO: Handle addr not found. // @TODO: Pick camera functions out of the upper function (they happen in immediate succession). // 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 == 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); checkCameraHook = Hook.Create(0x141FA2130, CheckCameraHook); // nint startViewModeHook = Hook.Create(0x1405842E0, StartViewModeHook); // nint setupGestureMenu = new NativeAction(0x141E12AF0); showGestureMenu = new NativeAction(0x141FB79B0); /* unchecked { // @TODO: View mode collision check here // MonsterHunterWorld.exe+23268DF - call MonsterHunterWorld.exe+2326B10 // can be overridden by the player collision function here // MonsterHunterWorld.exe+23268DF - call MonsterHunterWorld.exe+23269F0 // to evaluate differences. // Other TODOs for View Mode interop. // - Don't colide with water. // - Disable box around player collision. // - View mode fade on close to player. // - Weird LOD differences when in view mode. startViewMode = new NativeAction(0x1405842E0); stopViewMode = new NativeAction(0x1405825A0); processViewMode = new NativeAction(0x140582820); viewMode1 = new Patch((nint)0x141ADFAB9, [0x90, 0x90]); // Check input. viewMode1.Enable(); // rax = 0x73 -> 0x43 //viewMode2 = new Patch((nint)0x1405843F8, [0x48, 0x8B, 0x43, 0x10, 0x90]); //viewMode2.Enable(); viewMode3 = new Patch((nint)0x1405844ED, [0x90, 0x90, 0x90, 0x90, 0x90]); // Screen flash related. viewMode3.Enable(); //viewMode2 = new Patch((nint)0x1405844CB, [0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90]); // Disables view mode from starting. //viewMode2.Enable(); // //viewMode1 = new Patch((nint)0x140582578, [0xEB]); ////viewMode1.Enable(); //viewMode1_1 = new Patch((nint)0x140582F13, [0xEB]); ////viewMode1_1.Enable(); //viewMode2 = new Patch((nint)0x1405831A5, [0x90, 0x90, 0x90, 0x90]); ////viewMode2.Enable(); //viewMode3 = new Patch((nint)0x1405831A5 + 0xC, [0x90, 0x90, 0x90, 0x90, 0x90]); ////viewMode3.Enable(); //viewMode4 = new Patch((nint)0x1405831A5 + 0xC + 0x11, [0x90, 0x90, 0x90, 0x90, 0x90]); ////viewMode4.Enable(); psuedoViewModeObject = (nint)NativeMemory.AllocZeroed(240); MemoryUtil.WriteBytes(psuedoViewModeObject, [0x28, 0x23, 0xFB, 0x42, 0x01, 0x00, 0x00, 0x00]); } */ // 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 Trace.Assert(addr == 0x142106450); // nint #endif setCameraTentHook = Hook.Create(addr, SetCameraTentHook); addr = PatternScanner.FindFirst(Pattern.FromString("48 8B C4 48 89 58 10 48 89 70 18 55 57 41 54 41 56 41 57 48 8D 6C 24 80 48 81 EC 80 01 00 00 0F 29 70 C8 48 8B F9 0F 29 78 B8 0F 57 C9 44 0F 29 40 A8 0F 57 F6 44 0F 29 48 98 44 0F 29 50 88")); #if ADDR_ASSERTS Trace.Assert(addr == 0x141FB12D0); // nint #endif setCameraCutsceneHook = Hook.Create(addr, SetCameraCutsceneHook); /* addr = PatternScanner.FindFirst(Pattern.FromString("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC 90 00 00 00 ?? ?? ?? ?? ?? ?? ?? 48 8B F9")); #if ADDR_ASSERTS Trace.Assert(addr == 0X14228EB60); // nint #endif calculateViewHook = Hook.Create(addr, CalculateViewHook); */ addr = PatternScanner.FindFirst(Pattern.FromString("48 89 5C 24 10 48 89 74 24 18 48 89 7C 24 20 55 41 56 41 57 48 8B EC 48 83 EC 30 48 8B FA 48 8B D9 E8 AA B6 C1 FF 48 8B 47 10 48 8D 57 50")); #if ADDR_ASSERTS Trace.Assert(addr == 0x141AB2260); // nint, nint #endif shadowCascadeHook = Hook.Create(addr, ShadowCascadeHook); rendererSetHook = Hook.Create(0x141ABDED0, RendererSetHook); // nint, nint, nint 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 == 0x1422A1280); // nint, nint, nint #endif writePadInputHook = Hook.Create(addr, WritePadInputHook); // Place where we can change the analog stick value the game uses for player movement. addr = PatternScanner.FindFirst(Pattern.FromString("66 0F 6E C1 0F 5B C0 85 C9 78 11")); #if ADDR_ASSERTS Trace.Assert(addr == 0x142107CB0); // int, float #endif checkMovementHook = Hook.Create(addr, CheckMovementHook); collisionCheckHook = Hook.Create(0x1411C4E50, CollisionCheckHook); // nint, nint motionBlurHook = Hook.Create(0x1424CADF0, MotionBlurHook); // nint, nint dofHook = Hook.Create(0x1412BA6A0, DofHook); // nint cameraEffectHook = Hook.Create(0x141AB6AE0, CameraEffectHook); // nint, nint, nint unchecked { 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 == 0x141E55D9E); #endif swapMinimapFollowsCamera = new Patch(addr + 0x3, [0xE9]); // je -> jmp. 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]); jmpOverDof = new Patch((nint)0x1424233C6, [0xEB]); // je -> jmp. 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); Trace.Assert(MemoryUtil.Read(0x142E4FE5C) == 3.0f); #endif shadowRes1_3x = new Patch(addr + 0x8, [0xD0, 0xFE, 0xA0, 0x02]); // 3.0. shadowRes1_1 = new Patch(addr + 0x65, [0x17]); // Always set "Value is not 1.0" flag. shadowRes1_2 = new Patch(addr + 0x68, [0x59]); // movss -> mulss. shadowRes1_3 = new Patch(addr + 0x77, [0x59]); // movss -> mulss. // shadowRes2/3 control the detail of the infrequently updated fallback shadows. 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, // High. 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xC3, // Mid. 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xC3 // Low. ]); 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 // This value controls the shadow map texture resolution. 16384x16384 is likely the limit for many drivers // and any value higher would crash. Keeping this at the default value *should* work unless the game // does something unpredictable. At 3x Shadow Resolution, the shadow map will be 8448x8448. shadowRes4_Limit = new Patch(addr + 0x29, [ // N/64 = 255, fractional values closer to 256 not tested. 0xB8, 0x40, 0x15, 0x00, 0x00, 0xEB, 0x21 // This case is used for Low, Medium and High in-game. ]); */ if (tripleShadowRes && !disableMod) { tripleShadowResEnable(); } // The game will crash when trying to switch to the FULL_RES path for SSR. It's likley because // it tries to access resources (shader, buffer, texture, etc.) that are not loaded. // Ex: MonsterHunterWorld.exe+228C4A7 - mov rdi,[rdi+00000120] # Attempted read. // MonsterHunterWorld.exe+259329B - lea rcx,[rdi+00000120] # Zero. // The code that zero's these addresses looks like a shell of where they would be loaded. So my assumption // is that it's compiled out and that this method of increasing the SSR resolution will not work. // Though, it may still be possible by finagling the parameters of the half res case. /* // Attempt to forcefully enable FULL_RES path for SSR. ssrRes1 = new Patch((nint)0x14228894D, [0x0F, 0x85, 0xB9, 0xAA, 0x30, 0x00]); ssrRes1_1 = new Patch((nint)0x14259340C, [0xC6, 0x81, 0x28, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90]); ssrRes2 = new Patch((nint)0x14228897D, [0x0F, 0x85, 0x99, 0xAA, 0x30, 0x00]); ssrRes2_1 = new Patch((nint)0x14259341C, [0xC6, 0x81, 0x30, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90]); ssrRes3 = new Patch((nint)0x1422889AD, [0x0F, 0x85, 0x79, 0xAA, 0x30, 0x00]); ssrRes3_1 = new Patch((nint)0x14259342C, [0xC6, 0x81, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90]); ssrRes4 = new Patch((nint)0x14259268C, [0x41, 0xC7, 0x86, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC7, 0x86, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC7, 0x86, 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC7, 0x86, 0x34, 0x02, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0xC7, 0x86, 0x38, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x41, 0xC6, 0x86, 0x3C, 0x02, 0x00, 0x00, 0x01]); */ // None of these work either. /* // Don't scale resolution by SSR Factor. ssrRes10 = new Patch((nint)0x142592DEF, [0x90, 0x90, 0x90, 0x90]); ssrRes11 = new Patch((nint)0x142592E00, [0x90, 0x90, 0x90, 0x90]); // Make SSR Factor 1.0. ssrRes12 = new Patch((nint)0x1425926B8 + 0x7, [0x00, 0x00, 0x80, 0x3F]); */ /* Double width and height (3rd and 4th parameter). initSSRHook = Hook.Create(0x1425924D5, InitSSRHook); // nint, nint, int, int increaseSSRMipSize1 = new Patch((nint)0x142592EBA + 0x2, [0x2]); increaseSSRMipSize2 = new Patch((nint)0x142592ED0 + 0x2, [0x2]); */ // Gameplay. addr = PatternScanner.FindFirst(Pattern.FromString("80 BB 34 EC 00 00 00 88 8B 31 EC 00 00 C6 83 30 EC 00 00 00 74 1C C6 83 34 EC 00 00 00 48 8B 0D 68 4B 4F 03 80 B9 58 02 00 00 00 75 05 E8 5A F5 01 00 48 8B CB E8 E2 05 00 00 83 BB DC EB 00 00 06 74 0A C7 83 DC EB 00 00 06 00 00 00")); #if ADDR_ASSERTS Trace.Assert(addr == 0x141B1A0B4); #endif defaultViewModeLODLimit = new Patch(addr + 0x40, [0x07, 0x74, 0x0A, 0xC7, 0x83, 0xDC, 0xEB, 0x00, 0x00, 0x07]); // In room. addr = PatternScanner.FindFirst(Pattern.FromString("8B 9F CC 00 00 00 81 FB F9 01 00 00 74 0C 8B CB E8 95 3F 65 01 83 F8 05 75 11 48 8B 0D 61 C8 F6 04 BA 02 00 00 00 E8 DF 2D 8C 01 48 8B 0D A0 C7 F6 04 8B D3")); #if ADDR_ASSERTS Trace.Assert(addr == 0x140257AE6); #endif defaultViewModeLODLimit_1 = new Patch(addr + 0x22, [0x07]); // Forging/Changing Equipment. addr = PatternScanner.FindFirst(Pattern.FromString("BA 02 00 00 00 E8 6E C0 80 00 48 8B 74 24 38 48 8B 57 28 48 8D 4F 30 E8 4C 79 B4 FE 48 8B 0D 0D FF A6 03 BA 04 00 00 00 E8 8B 64 3C 00 48 8B 05 D4 01 A7 03 80 B8 FD 46 01 00 00")); #if ADDR_ASSERTS Trace.Assert(addr == 0x141754438); #endif defaultViewModeLODLimit_2 = new Patch(addr + 0x24, [0x07]); if (disableLODLimits && !disableMod) { disableLODLimitsEnable(); } 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(); } // Found using mFrameSkipNum annotation from MHW-DTI-Dumps. zeroFrameSkip = new Patch((nint)0x142246948, [0x31, 0xC0, 0x90, 0x90, 0x90, 0x90]); if (disableReducedRateAnimations && !disableMod) { zeroFrameSkip.Enable(); } underwaterCamera1 = new Patch((nint)0x1412AD54D, [0x90, 0x90, 0x90, 0x90, 0x90, 0x90]); // Nop "Is diving" check. underwaterCamera2 = new Patch((nint)0x1412AD571, [0xB1, 0x01, 0x28, 0xC1, 0x90, 0x90, 0x90]); // Make cl the inverse of al. underwaterCamera3 = new Patch((nint)0x141FA5A7E, [0x90, 0x90]); // Nop check. underwaterCamera4 = new Patch((nint)0x141FA5BA0, [0x40, 0x84, 0xF6, 0x90, 0x74]); // jae -> je. underwaterCamera5 = new Patch((nint)0x141FA5A74, [0x0F, 0x57, 0xF6, 0x31, 0xD2, 0x48, 0x8D, 0x4D, 0x80, 0xE8, 0x9E, 0x41, 0x38, 0xFE, 0xC1, 0xE8, 0x14, 0x66, 0x25, 0xD8, 0x03, 0xFF, 0xC8, 0x66, 0x3D, 0x48, 0x00, 0x77]); underwaterCheckHook = Hook.Create(0x1412AD500, UnderwaterCheckHook); // nint volumeSars1 = new Patch((nint)0x1424D0159, [0x90, 0x90]); volumeSars2 = new Patch((nint)0x1424D01A0, [0x90, 0x90]); volumeSars3 = new Patch((nint)0x1424D01C6, [0x90, 0x90]); volumeSars4 = new Patch((nint)0x1424D0219, [0x90, 0x90]); volumeSars5 = new Patch((nint)0x1424D0242, [0x90, 0x90]); volumeSars6 = new Patch((nint)0x1424D029D, [0x90, 0x90]); volumeSars7 = new Patch((nint)0x1424D02C6, [0x90, 0x90]); volumeSars8 = new Patch((nint)0x1424D0321, [0x90, 0x90]); volumeSars9 = new Patch((nint)0x1424D034A, [0x90, 0x90]); if (disableVolumeDownsample && !disableMod) { volumeSars1.Enable(); volumeSars2.Enable(); volumeSars3.Enable(); volumeSars4.Enable(); volumeSars5.Enable(); volumeSars6.Enable(); volumeSars7.Enable(); volumeSars8.Enable(); volumeSars9.Enable(); } value2ForVolumeQuality = new Patch((nint)0x142389652, [0xB8, 0x02, 0x00, 0x00, 0x00, 0x90]); if (higherVolumeQuality && !disableMod) { value2ForVolumeQuality.Enable(); } createLightingObject = Hook.Create(0x1424CE130, CreateLightingObjectHook); // nint destroyLightingObject = Hook.Create(0x1424CE380, DestroyLightingObjectHook); // nint, nint createFXAAObject = Hook.Create(0x1423936E0, CreateFXAAObjectHook); // nint, int destroyFXAAObject = Hook.Create(0x142393740, DestroyFXAAObjectHook); // nint, int // Player + ECCC = How far underwater is the player. jmpOverHotSpringsEval = new Patch((nint)0x1417C1B03, [0xEB]); jmpOverHotSpringsSteam = new Patch((nint)0x14203A494, [0xE9, 0x8D, 0x00, 0x00, 0x00, 0x90]); refreshEntityParams = Hook.Create(0x141F605F0, RefreshEntityParamsHook); // nint, nint noopCharacterWetnessUpdate = new Patch((nint)0x14203E893, [0x90, 0x90, 0x90, 0x90, 0x90]); // 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); #endif disableXCollision = new Patch(addr, [0x90, 0x90, 0x90, 0x90]); #if ADDR_ASSERTS Trace.Assert(addr + 0xE == 0x141C001C3); #endif disableYCollision = new Patch(addr + 0xE, [0x90, 0x90, 0x90, 0x90, 0x90]); #if ADDR_ASSERTS Trace.Assert(addr + 0x1D == 0x141C001D2); #endif 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); #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); #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); #endif disableGravityYUpdate = new Patch(addr + 0x8, [ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, ]); disableGravityXZUpdate = new Patch(addr, [ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // Will already be applied. 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 ]); 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); #endif disableGravityEval = new Patch(addr + 0x40, [0x90, 0x90, 0x90, 0x90, 0x90]); // call MonsterHunterWorld.exe+1325810. } } private bool getDisableFadingObjects(int viewportIndex) { Viewport vp = CameraSystem.GetViewport(viewportIndex); return MemoryUtil.Read(vp.Instance + 0x21) == 0; } private void setDisableFadingObjects(int viewportIndex, bool disable) { Viewport vp = CameraSystem.GetViewport(viewportIndex); MemoryUtil.WriteBytes(vp.Instance + 0x21, disable ? [0x0] : [0x1]); } private void setDisableCharacterFade(bool disable) { if (disable && !disableCharacterFade) { noopCharacterFade.Enable(); disableCharacterFade = true; } else if (!disable && disableCharacterFade) { noopCharacterFade.Disable(); disableCharacterFade = false; } } private bool areLODFactorsDefault() { return foliageLODBias == 3.0f && terrainLODBias == 3.0f && foliageLODFactor == 1.0f && terrainLODFactor == 1.0f && snowField4GlobalLODParam == 8.0f; } private bool areLODFactorsSet() { nint baseAddr = MemoryUtil.Read(0x1451C4368); float foliageLOD1 = MemoryUtil.Read(baseAddr + 0x21C); float terrainLOD1 = MemoryUtil.Read(baseAddr + 0x220); float foliageLOD2 = MemoryUtil.Read(baseAddr + 0x224); float terrainLOD2 = MemoryUtil.Read(baseAddr + 0x228); float snowLOD1 = MemoryUtil.Read(baseAddr + 0x5718); return foliageLOD1 == foliageLODBias && terrainLOD1 == terrainLODBias && foliageLOD2 == foliageLODFactor && terrainLOD2 == terrainLODFactor && snowLOD1 == snowField4GlobalLODParam; } private void setLODFactors(bool toggleOn) { nint baseAddr = MemoryUtil.Read(0x1451C4368); if (toggleOn) { // Assume in-game setting is "High". if (prevFoliageLODBias <= 0.0f) { prevFoliageLODBias = MemoryUtil.Read(baseAddr + 0x21C); if (prevFoliageLODBias > 3.0f) prevFoliageLODBias = 3.0f; } MemoryUtil.WriteBytes(baseAddr + 0x21C, BitConverter.GetBytes(foliageLODBias)); if (prevTerrainLODBias <= 0.0f) { prevTerrainLODBias = MemoryUtil.Read(baseAddr + 0x220); if (prevTerrainLODBias > 3.0f) prevTerrainLODBias = 3.0f; } MemoryUtil.WriteBytes(baseAddr + 0x220, BitConverter.GetBytes(terrainLODBias)); MemoryUtil.WriteBytes(baseAddr + 0x224, BitConverter.GetBytes(foliageLODFactor)); MemoryUtil.WriteBytes(baseAddr + 0x228, BitConverter.GetBytes(terrainLODFactor)); MemoryUtil.WriteBytes(baseAddr + 0x5718, BitConverter.GetBytes(snowField4GlobalLODParam)); } else { MemoryUtil.WriteBytes(baseAddr + 0x21C, BitConverter.GetBytes(prevFoliageLODBias)); MemoryUtil.WriteBytes(baseAddr + 0x220, BitConverter.GetBytes(prevTerrainLODBias)); MemoryUtil.WriteBytes(baseAddr + 0x224, BitConverter.GetBytes(1.0f)); MemoryUtil.WriteBytes(baseAddr + 0x228, BitConverter.GetBytes(1.0f)); MemoryUtil.WriteBytes(baseAddr + 0x5718, BitConverter.GetBytes(internalSnowField4GlobalLODParam)); } } private void setPerspectivePreset(Config.Preset preset) { cameraFov = preset.FieldOfView; if (restoreFov != null) { restoreFov = cameraFov; } orbitDistance += cameraForward - preset.Forward; cameraForward = preset.Forward; cameraRight = preset.Right; cameraUp = preset.Up; cameraRoll = preset.Roll; if (restoreRoll != null) { restoreRoll = cameraRoll; } disableFading = preset.DisableFading; if (pCameraViewportIndex >= 0) { setDisableFadingObjects(pCameraViewportIndex, disableFading); } setDisableCharacterFade(disableFading); } public void OnLoad() { Config config = ConfigManager.GetConfig(this); if (config.Selected != "") { setPerspectivePreset(config.Presets[config.Selected]); } Config.GraphicalTweaks graphics = config.Graphics; foliageLODBias = graphics.FoliageLODBias; terrainLODBias = graphics.TerrainLODBias; foliageLODFactor = graphics.FoliageLODFactor; terrainLODFactor = graphics.TerrainLODFactor; snowField4GlobalLODParam = graphics.SnowLODBias; applyLODFactors = graphics.ApplyLODFactors; if (applyLODFactors) { setLODFactors(true); } } private void resetStatePerFrame() { primaryPad = 0x0; // Zero pad input in case no controllers are connected. PadLx = 0; PadLy = 0; PadRx = 0; PadRy = 0; cameraOffset.X = 0.0f; cameraOffset.Y = 0.0f; cameraOffset.Z = 0.0f; } public void OnUpdate(float deltaTime) { if (disableMod) { return; } #if HOOK_ORDER_ASSERTS Trace.Assert(hookOrder == 0 || hookOrder == 4); hookOrder = 0; if (frameTick == int.MaxValue) frameTick = 0; else frameTick++; debugLog($"OnUpdate() @ {frameTick}"); #endif #if MOUSE_AND_KEYBOARD_LAYER if (keyboardEnabled) { if (Input.IsPressed(Key.NumPad0)) { enableFreeCamera = !enableFreeCamera; } if (Input.IsPressed(Key.NumPadPeriod)) { uiToggled = !uiToggled; if (uiToggled) { jmpOverUi.Enable(); } else { jmpOverUi.Disable(); } } if (Input.IsPressed(Key.NumPadSlash)) { dofDisabled = !dofDisabled; if (dofDisabled) { jmpOverDof.Enable(); } else { jmpOverDof.Disable(); } } } #endif if (freeCameraFallback) { Player? player = checkPlayerChange(); checkCurrentVisibleCamera(player); // Ensure vCamera is valid. if (vCamera != null) { if (!freeCamera) { Quaternion forward = Quaternion.Normalize(getForward(vCamera.Position, vCamera.Target)); cameraYaw = Single.RadiansToDegrees(MathF.Atan2(forward.Z, forward.X)); cameraPitch = Single.RadiansToDegrees(MathF.Asin(forward.Y)); if (enableFreeCamera) { setupFreeCamera(vCamera, vCameraViewportIndex); } } if (freeCamera) { updateFreeCamera(vCamera); setCameraRoll(vCamera); if (!enableFreeCamera) { disableFreeCamera(); } } } } freeCameraFallback = true; ref float gameSpeed = ref MemoryUtil.GetRef(sMain.Instance + 0xA4); if (freezeGame && gameSpeed != 0.0f) { gameSpeed = 0.0f; } else if (freezeGame && advanceFrame > 0) { gameSpeed = 1.0f; advanceFrame--; } if (hideWeapon) { Player? player = Player.MainPlayer; if (player != null) { nint baseAddr = MemoryUtil.Read(player.Instance + 0x76B0); MemoryUtil.WriteBytes(baseAddr + 0x1A98, [0x1]); int weaponParts = MemoryUtil.Read(baseAddr + 0x2250); for (int i = 0; i < weaponParts; i++) { nint partAddr = MemoryUtil.Read(baseAddr + ((i + 0x16B) * 24)); if (partAddr != 0x0) { MemoryUtil.WriteBytes(partAddr + 0x1A98, [0x1]); } } } } resetStatePerFrame(); } private static Quaternion getForward(Vector3 pos, Vector3 target) { return new Quaternion(target.X - pos.X, target.Y - pos.Y, target.Z - pos.Z, 0.0f); } private static Quaternion getRight(Quaternion q) { return q * Quaternion.CreateFromYawPitchRoll(MathF.PI, 0.0f, 0.0f); } private static Quaternion getReverse(Quaternion q) { return q * Quaternion.CreateFromYawPitchRoll(MathF.PI, 0.0f, 0.0f); } private void setCameraRoll(Camera camera) { // Don't test our luck with precision weirdness if we know we can be exact. if (cameraRoll == 0.0f) { camera.Up.X = 0.0f; camera.Up.Y = 1.0f; camera.Up.Z = 0.0f; } else if (cameraRoll == 180.0f) { camera.Up.X = 0.0f; camera.Up.Y = -1.0f; camera.Up.Z = 0.0f; } else { // yaw + 90.0 = point right. camera.Up.X = MathF.Sin(Single.DegreesToRadians(cameraRoll)) * MathF.Cos(Single.DegreesToRadians(cameraPitch)) * MathF.Cos(Single.DegreesToRadians(cameraYaw + 90.0f)); camera.Up.Y = MathF.Cos(Single.DegreesToRadians(cameraRoll)); camera.Up.Z = MathF.Sin(Single.DegreesToRadians(cameraRoll)) * MathF.Cos(Single.DegreesToRadians(cameraPitch)) * MathF.Sin(Single.DegreesToRadians(cameraYaw + 90.0f)); } } private bool guessAltNearClipSet(Camera camera) { // Try to guard against persisting an adjusted near clip on the player camera after a free camera target change. return (camera.NearClip == alternateNearClip) || (camera == pCamera && camera.NearClip != DEFAULT_NEAR_CLIP); } private void setNearClip(Camera camera, bool alt) { if (alt) { if (restoreNearClip == null) { restoreNearClip = camera.NearClip; } camera.NearClip = alternateNearClip; } else { if (restoreNearClip == null) { camera.NearClip = DEFAULT_NEAR_CLIP; } else { if (camera == pCamera && restoreNearClip != DEFAULT_NEAR_CLIP) { restoreNearClip = DEFAULT_NEAR_CLIP; } camera.NearClip = (float)restoreNearClip; restoreNearClip = null; } } } private void setPerspective(Camera camera) { Quaternion forward = getForward(camera.Position, camera.Target); Quaternion right = getRight(forward); forward = Quaternion.Normalize(forward); right = Quaternion.Normalize(right); Vector3 pos = camera.Position; cameraOffset.X = forward.X * cameraForward; cameraOffset.Y = forward.Y * cameraForward; cameraOffset.Z = forward.Z * cameraForward; cameraOffset.X += right.X * cameraRight; cameraOffset.Z += right.Z * cameraRight; pos.X += cameraOffset.X; pos.Y += cameraOffset.Y; pos.Z += cameraOffset.Z; camera.Position = pos; if (cameraFov != DEFAULT_FOV) { camera.FieldOfView = Math.Clamp((cameraFov * previousFov) / DEFAULT_FOV, 1.0f, 179.0f); } } private void setTentBasePos(Vector3 pos, Vector3 target) { // @TODO: This could 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 } private void setupFreeCamera(Camera camera, int viewportIndex) { freeCamera = true; cameraPosition = camera.Position; cameraTarget = camera.Target; restoreFov = cameraFov; restoreRoll = cameraRoll; restoreNearClip = camera.NearClip; // The value of cameraFov is effectively a new default and scales accordingly // based on the in-game FOV. Take the calculated FOV here because that's what is // actually shown, which avoids a jump when toggling free camera. This is also // why we don't enable free camera until after applying a offset on this update. cameraFov = camera.FieldOfView; setDisableFadingObjects(viewportIndex, true); setDisableCharacterFade(true); swapMinimapFollowsCamera.Enable(); /* //MemoryUtil.WriteBytes(psuedoViewModeObject + 0x10, BitConverter.GetBytes(vCamera.Instance)); Player? player = Player.MainPlayer; if (player != null) { MemoryUtil.WriteBytes(psuedoViewModeObject + 0x118, BitConverter.GetBytes(player.Instance)); } //startViewMode.Invoke(psuedoViewModeObject); */ } private void disableFreeCamera() { freeCamera = false; freeCameraFromViewMode = false; unlockInputToggled = false; unlockInputForMenu = false; unlockInputHideMenu = false; if (restoreFov != null) { cameraFov = (float)restoreFov; restoreFov = null; } if (restoreRoll != null) { cameraRoll = (float)restoreRoll; restoreRoll = null; } if (restoreNearClip != null && vCamera != null) { vCamera.NearClip = (float)restoreNearClip; restoreNearClip = null; } cameraWrapState = 0; setTentBasePos(new Vector3(0.0f, -19850.0f, 270.0f), new Vector3(0.0f, -19830.0f, 0.0f)); setDisableFadingObjects(vCameraViewportIndex, (vCameraViewportIndex == pCameraViewportIndex) ? disableFading : false); setDisableCharacterFade(disableFading); swapMinimapFollowsCamera.Disable(); //stopViewMode.Invoke(psuedoViewModeObject); } private float adjustedZoomSpeed(float deltaTime) { return cameraZoomSpeed * deltaTime * cameraFov; } private void updateFreeCamera(Camera camera) { float deltaTime; if (decoupleDtFromGameTime) { deltaTime = 60.0f / MemoryUtil.Read(sMain.Instance + 0x68); } else { deltaTime = MemoryUtil.Read(sMain.Instance + 0x94); } bool lockVerticalAndModifySpeed = buttonWasDown(Button.L2) || lockVerticalToggled; float adjustedSpeed = cameraSpeed * deltaTime * (lockVerticalAndModifySpeed ? cameraSpeedModifier : 1.0f); cameraFrame.X = 0.0f; cameraFrame.Y = 0.0f; cameraFrame.Z = 0.0f; // PadLx/y is read in WritePadInputHook(). if (buttonWasDown(Button.L2) && buttonWasDown(Button.R2)) // Left stick zoom. { if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0; float Ly = PadLy / (Int16.MaxValue / adjustedZoomSpeed(deltaTime)); cameraFov = Math.Clamp(cameraFov - Ly, 1.0f, 179.0f); } else if (playerMovementLocked || orbitPlayer) // Move camera. { if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0; if (Math.Abs(PadLx) < stickDeadzone) PadLx = 0; #if MOUSE_AND_KEYBOARD_LAYER if (keyboardEnabled) { if (Input.IsDown(Key.Up)) PadLy += Int16.MaxValue; if (Input.IsDown(Key.Down)) PadLy -= Int16.MaxValue; if (Input.IsDown(Key.Left)) PadLx -= Int16.MaxValue; if (Input.IsDown(Key.Right)) PadLx += Int16.MaxValue; } #endif float Ly = PadLy / (Int16.MaxValue / adjustedSpeed); float Lx = PadLx / (Int16.MaxValue / adjustedSpeed); if (orbitPlayer) { if (playerMovementLocked) { orbitDistance -= Ly; if (orbitDistance < 3.00f) { orbitDistance = 3.00f; } } orbitMovementRotation += Lx / 5.0f; if (orbitMovementRotation >= 180.0f) { orbitMovementRotation -= 360.0f; } else if (orbitMovementRotation < -180.0f) { orbitMovementRotation += 360.0f; } } else { Quaternion forward = getForward(cameraPosition, cameraTarget); if (cameraWrapState == 1) { // Invert diagonal directions when upside down for movement consistency. forward.X = -forward.X; forward.Z = -forward.Z; } if (lockVerticalAndModifySpeed) { forward.Y = 0.0f; } Quaternion right = forward; right.Y = 0.0f; right = getRight(right); forward = Quaternion.Normalize(forward); right = Quaternion.Normalize(right); cameraFrame.X += right.X * Lx; cameraFrame.Z += right.Z * Lx; cameraFrame.X += forward.X * Ly; cameraFrame.Y += forward.Y * Ly; cameraFrame.Z += forward.Z * Ly; if (plusForward != 0.0f) { cameraFrame.X += forward.X * plusForward * deltaTime; cameraFrame.Y += forward.Y * plusForward * deltaTime; cameraFrame.Z += forward.Z * plusForward * deltaTime; } } } if (!unlockInputToggled && !comboButton1Down) { if (buttonWasDown(Button.Share)) { if (buttonWasPressed(Button.Square)) { setNearClip(camera, !guessAltNearClipSet(camera)); } } if (buttonWasDown(Button.R1)) { if (buttonWasPressed(Button.Right)) { cameraRoll = (restoreRoll != null) ? (float)restoreRoll : 0.0f; } if (buttonWasPressed(Button.Up)) { if (restoreFov != null) { cameraFov = Math.Clamp((float)restoreFov * (previousFov / DEFAULT_FOV), 1.0f, 179.0f); } else { cameraFov = DEFAULT_FOV; } } } else if (!unlockInputForMenu || unlockInputHideMenu) { if (buttonWasDown(Button.Up)) { cameraFrame.Y += adjustedSpeed / 2.0f; } if (buttonWasDown(Button.Down)) { cameraFrame.Y -= adjustedSpeed / 2.0f; } if (buttonWasDown(Button.Left)) { cameraRoll -= adjustedSpeed / 4.0f; } if (buttonWasDown(Button.Right)) { cameraRoll += adjustedSpeed / 4.0f; } } } #if MOUSE_AND_KEYBOARD_LAYER if (keyboardEnabled) { if (Input.IsDown(Key.NumPadMinus)) { cameraFov = Math.Clamp(cameraFov - adjustedZoomSpeed(deltaTime), 1.0f, 179.0f); } if (Input.IsDown(Key.NumPadPlus)) { cameraFov = Math.Clamp(cameraFov + adjustedZoomSpeed(deltaTime), 1.0f, 179.0f); } if (Input.IsPressed(Key.NumPadEnter)) { if (restoreFov != null) { cameraFov = Math.Clamp((float)restoreFov * (previousFov / DEFAULT_FOV), 1.0f, 179.0f); } else { cameraFov = DEFAULT_FOV; } } if (Input.IsPressed(Key.NumPadStar)) { cameraRoll = (restoreRoll != null) ? (float)restoreRoll : 0.0f; } if (Input.IsDown(Key.NumPad7)) { cameraFrame.Y += adjustedSpeed / 2.0f; } if (Input.IsDown(Key.NumPad1)) { cameraFrame.Y -= adjustedSpeed / 2.0f; } if (Input.IsDown(Key.NumPad9)) { cameraRoll += adjustedSpeed / 4.0f; } if (Input.IsDown(Key.NumPad3)) { cameraRoll -= adjustedSpeed / 4.0f; } } #endif // Camera look. PadRx/y is read in WritePadInputHook(). if (Math.Abs(PadRx) < stickDeadzone) PadRx = 0; if (Math.Abs(PadRy) < stickDeadzone) PadRy = 0; #if MOUSE_AND_KEYBOARD_LAYER if (keyboardEnabled) { if (Input.IsDown(Key.NumPad8)) PadRy += keyboardLookValue; if (Input.IsDown(Key.NumPad2)) PadRy -= keyboardLookValue; if (Input.IsDown(Key.NumPad4)) PadRx -= keyboardLookValue; if (Input.IsDown(Key.NumPad6)) PadRx += keyboardLookValue; } #endif float adjustedSensitivity = cameraSensitivity * deltaTime * cameraFov; float Rx = PadRx / (Int16.MaxValue / adjustedSensitivity); float Ry = PadRy / (Int16.MaxValue / adjustedSensitivity); #if MOUSE_AND_KEYBOARD_LAYER if (mouseEnabled && !playerInMenu()) { Rx += MemoryUtil.GetRef(sMhMouse.Instance + 0xFC) * mouseSensitivity; Ry -= MemoryUtil.GetRef(sMhMouse.Instance + 0x100) * mouseSensitivity; ref int scrollY = ref MemoryUtil.GetRef(sMhMouse.Instance + 0x17C); if (orbitPlayer) { orbitDistance -= scrollY * cameraZoomSpeed * 2.0f; if (orbitDistance < 0.01f) { orbitDistance = 0.01f; } } else { cameraFov = Math.Clamp(cameraFov - scrollY * cameraZoomSpeed, 1.0f, 179.0f); } } #endif cameraYaw += Rx; if (plusRight != 0.0f) { cameraYaw += plusRight * deltaTime; } if (cameraYaw >= 180.0f) { cameraYaw -= 360.0f; } else if (cameraYaw < -180.0f) { cameraYaw += 360.0f; } if (cameraPitchLimit >= 0.0f) { cameraPitch = Math.Clamp(cameraPitch + Ry, -cameraPitchLimit, cameraPitchLimit); } else { cameraPitch += Ry; if (cameraPitch >= 90.0f && cameraWrapState == 0) { cameraRoll += 180.0f; cameraWrapState = 1; } else if (cameraPitch < -90.0f && cameraWrapState == 0) { cameraPitch += 360.0f; cameraRoll += 180.0f; cameraWrapState = 1; } else if (cameraPitch < 90.0f && cameraWrapState == 1) { cameraRoll -= 180.0f; cameraWrapState = 0; } else if (cameraPitch >= 270.0f && cameraWrapState == 1) { cameraPitch -= 360.0f; cameraRoll -= 180.0f; cameraWrapState = 0; } } if (cameraRoll < 0.0f) { cameraRoll += 360.0f; } else if (cameraRoll >= 360.0f) { cameraRoll -= 360.0f; } Player? player = Player.MainPlayer; if (orbitPlayer && player != null) { Vector3 up = new Vector3(0.0f, 1.0f, 0.0f); Quaternion rotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W); up = Vector3.Transform(up, rotation); orbitY += cameraFrame.Y; cameraTarget = player.Position; cameraTarget.X += orbitY * up.X; cameraTarget.Y += orbitY * up.Y; cameraTarget.Z += orbitY * up.Z; float dist = orbitDistance; cameraPosition.X = cameraTarget.X - dist * MathF.Cos(Single.DegreesToRadians(cameraPitch)) * MathF.Cos(Single.DegreesToRadians(cameraYaw)); cameraPosition.Y = cameraTarget.Y - dist * MathF.Sin(Single.DegreesToRadians(cameraPitch)); cameraPosition.Z = cameraTarget.Z - dist * MathF.Cos(Single.DegreesToRadians(cameraPitch)) * MathF.Sin(Single.DegreesToRadians(cameraYaw)); } else { cameraPosition.X += cameraFrame.X; cameraPosition.Y += cameraFrame.Y; cameraPosition.Z += cameraFrame.Z; // 700.0 is the same value the game uses for the player camera. The in-game view mode // uses 1.0 like I did here before, which is really bad for precision. float dist = 700.0f - cameraForward; cameraTarget.X = cameraPosition.X + dist * MathF.Cos(Single.DegreesToRadians(cameraPitch)) * MathF.Cos(Single.DegreesToRadians(cameraYaw)); cameraTarget.Y = cameraPosition.Y + dist * MathF.Sin(Single.DegreesToRadians(cameraPitch)); cameraTarget.Z = cameraPosition.Z + dist * MathF.Cos(Single.DegreesToRadians(cameraPitch)) * MathF.Sin(Single.DegreesToRadians(cameraYaw)); } camera.Position = cameraPosition; camera.Target = cameraTarget; camera.FieldOfView = cameraFov; } private Player? checkPlayerChange() { Player? player = Player.MainPlayer; if (player != lastPlayer) { pCamera = null; pCameraViewportIndex = -1; lastPlayer = player; } return player; } private int getVisibleCamera() { for (int i = 0; i < 8; i++) { Viewport vp = CameraSystem.GetViewport(i); // A viewport can be visible with a null camera. if (vp.Visible && vp.Camera != null) { return i; } } return -1; } private void checkCurrentVisibleCamera(Player? player) { int prevIndex = vCameraViewportIndex; vCameraViewportIndex = getVisibleCamera(); if (vCameraViewportIndex >= 0) { Camera camera = CameraSystem.GetViewport(vCameraViewportIndex).Camera!; // Evaluate potential free camera target change. if (freeCamera) { if (prevIndex != vCameraViewportIndex) { if (prevIndex >= 0) { setDisableFadingObjects(prevIndex, (prevIndex == pCameraViewportIndex) ? disableFading : false); } setDisableFadingObjects(vCameraViewportIndex, true); } if (vCamera != camera) { if (player != null) { // Try to position the camera behind the player. cameraPosition = player.Position; cameraPosition.X -= player.Forward.X * 250.0f; cameraPosition.Y += 200.0f; cameraPosition.Z -= player.Forward.Z * 250.0f; cameraTarget = player.Position; cameraTarget.Y += 150.0f; } else { cameraPosition = camera.Position; cameraTarget = camera.Target; } Quaternion forward = Quaternion.Normalize(getForward(cameraPosition, cameraTarget)); cameraYaw = Single.RadiansToDegrees(MathF.Atan2(forward.Z, forward.X)); cameraPitch = Single.RadiansToDegrees(MathF.Asin(forward.Y)); } } vCamera = camera; // Assume that after a player is set the visible camera is the player camera. if (pCamera == null && player != null) { pCamera = vCamera; pCameraViewportIndex = vCameraViewportIndex; setDisableFadingObjects(pCameraViewportIndex, disableFading); } } else { vCamera = null; pCamera = null; pCameraViewportIndex = -1; } } private void checkCameraAnimState() { if (pCamera != null) { previousCameraAnimState = MemoryUtil.Read(pCamera.Instance + 0x240); if (previousCameraAnimState == 5) { Player player = Player.MainPlayer!; ActionInfo currentActionInfo = player.ActionController.CurrentAction; // 1:314 = Wingdrake landing on area enter. // 1:319 = Disoriented wingdrake landing next to monster. if (currentActionInfo.ActionSet == 1 && (currentActionInfo.ActionId == 314 || currentActionInfo.ActionId == 319)) { // Temporarily disable evaluation of cameraAnimState != 5. ignoreAnimState = true; } } else if (ignoreAnimState) { // Once cameraAnimState is no longer 5, resume default logic. ignoreAnimState = false; } } else { previousCameraAnimState = 0; } } private void SetCameraHook(nint cameraPointer) { if (disableMod) { setCameraHook!.Original(cameraPointer); return; } #if HOOK_ORDER_ASSERTS debugLog($"SetCameraHook({cameraPointer:x}) @ {frameTick}"); Trace.Assert(hookOrder == 0); hookOrder = 1; #endif Player? player = checkPlayerChange(); checkCurrentVisibleCamera(player); checkCameraAnimState(); // CalculateCameraHook() is within this function. setCameraHook!.Original(cameraPointer); #if HOOK_ORDER_ASSERTS Trace.Assert(hookOrder == 3); hookOrder = 4; #endif if (applyPerspective) { setCameraRoll(pCamera!); } if (freeCamera && vCamera != null) { setCameraRoll(vCamera); if (!enableFreeCamera) { // Disable free camera only after applying all possible // offsets for this frame. This is to hopefully avoid any // visual jumps. disableFreeCamera(); } } } private static bool assumeInQuestBoard(float fov) { return fov == 20.000038f || fov == 20.017189f || fov == 20.00004f; } // If camera.Move = false, this hook won't run. private void CalculateCameraHook(nint cameraPointer) { if (disableMod) { calculateCameraHook!.Original(cameraPointer); return; } #if HOOK_ORDER_ASSERTS debugLog($"CalculateCameraHook({cameraPointer:x}) @ {frameTick}"); Trace.Assert(hookOrder == 2); hookOrder = 3; #endif if (enableOffsetPerspective && !offsetPerspective) { offsetPerspective = true; } else if (!enableOffsetPerspective && offsetPerspective) { offsetPerspective = false; } applyPerspective = offsetPerspective && !freeCamera && pCamera != null; if (applyPerspective) { previousFov = pCamera!.FieldOfView; // Pre-offset FOV value. } bool perspectiveFovOnly = false; if (applyPerspective) { applyPerspective &= !assumeInQuestBoard(previousFov); perspectiveFovOnly = applyPerspective; applyPerspective &= (previousCameraAnimState != 5 || ignoreAnimState) && previousCameraAnimState != 4 && previousCameraAnimState != 8; } if (applyPerspective) { // Applying Y offset here keeps crosshair UI centered, but affects the angle of the camera. pCamera!.Position.Y += cameraUp; } if (perspectiveFovOnly && cameraFov != DEFAULT_FOV) { pCamera!.FieldOfView = Math.Clamp((cameraFov * previousFov) / DEFAULT_FOV, 1.0f, 179.0f); } calculateCameraHook!.Original(cameraPointer); // Setting the perspective after calculateCameraHook.Original() allows the offset to not // negatively affect the right stick camera movement. If set earlier, camera movement // would be too snappy and incorrectly smoothed. If set later, it may not be // considered by lower-level functions like culling. if (applyPerspective) { setPerspective(pCamera!); } if (vCamera != null) { if (!freeCamera) { // We need pitch and yaw to apply cameraRoll and avoid a jump if applyPerspective = false. // @TODO: These values could just be read from the in-game camera. Quaternion forward = Quaternion.Normalize(getForward(vCamera.Position, vCamera.Target)); cameraYaw = Single.RadiansToDegrees(MathF.Atan2(forward.Z, forward.X)); cameraPitch = Single.RadiansToDegrees(MathF.Asin(forward.Y)); if (enableFreeCamera) { setupFreeCamera(vCamera, vCameraViewportIndex); } } // No else if because we want to updateFreeCamera() if freeCamera was enabled above. if (freeCamera) { updateFreeCamera(vCamera); } } freeCameraFallback = false; } private void CheckCameraHook(nint cameraPointer) { if (disableMod) { checkCameraHook!.Original(cameraPointer); return; } #if HOOK_ORDER_ASSERTS debugLog($"CheckCameraHook({cameraPointer:x}) @ {frameTick}"); Trace.Assert(hookOrder == 1); hookOrder = 2; #endif /* if (vCamera != null && freeCamera) { updateFreeCamera(vCamera); MemoryUtil.WriteBytes(psuedoViewModeObject + 0xE0, BitConverter.GetBytes(cameraFrame.X)); MemoryUtil.WriteBytes(psuedoViewModeObject + 0xE4, BitConverter.GetBytes(cameraFrame.Y)); MemoryUtil.WriteBytes(psuedoViewModeObject + 0xE8, BitConverter.GetBytes(cameraFrame.Z)); processViewMode.Invoke(psuedoViewModeObject); cameraPosition.X = MemoryUtil.Read(psuedoViewModeObject + 0x90); cameraPosition.Y = MemoryUtil.Read(psuedoViewModeObject + 0x94); cameraPosition.Z = MemoryUtil.Read(psuedoViewModeObject + 0x98); } */ if (!freeCamera) { checkCameraHook!.Original(cameraPointer); } } private void StartViewModeHook(nint viewModeObject) { if (disableMod || !overrideViewMode) { startViewModeHook!.Original(viewModeObject); return; } #if HOOK_ORDER_ASSERTS debugLog($"StartViewMode({viewModeObject:x}) @ {frameTick}"); #endif if (vCamera != null) { enableFreeCamera = true; freeCameraFromViewMode = true; } } private void SetCameraTentHook(nint unknownPtr) { if (disableMod) { setCameraTentHook!.Original(unknownPtr); return; } #if HOOK_ORDER_ASSERTS // The order of this hook between SetCameraHook() and CalculateCameraHook() is inconsistent. debugLog($"SetCameraTentHook({unknownPtr:x}) @ {frameTick}"); #endif if (freeCamera && vCamera != null) { setTentBasePos(cameraPosition, cameraTarget); } setCameraTentHook!.Original(unknownPtr); if (freeCamera && vCamera != null) { vCamera.Position = cameraPosition; vCamera.Target = cameraTarget; vCamera.FieldOfView = cameraFov; setCameraRoll(vCamera); } freeCameraFallback = false; } private void SetCameraCutsceneHook(nint unknownPtr) { if (disableMod) { setCameraCutsceneHook!.Original(unknownPtr); return; } #if HOOK_ORDER_ASSERTS debugLog($"SetCameraCutsceneHook({unknownPtr:x}) @ {frameTick}"); #endif setCameraCutsceneHook!.Original(unknownPtr); if (freeCamera && vCamera != null) { vCamera.Position = cameraPosition; vCamera.Target = cameraTarget; vCamera.FieldOfView = cameraFov; setCameraRoll(vCamera); } freeCameraFallback = false; } /* private void CalculateViewHook(nint unknownPtr) { calculateViewHook!.Original(unknownPtr); if (disableMod) { return; } if (vCameraViewportIndex >= 0 && cameraRoll != 0.0f) { Viewport vp = CameraSystem.GetViewport(vCameraViewportIndex); vp.ViewMatrix *= Matrix4x4.CreateRotationZ(Single.DegreesToRadians(cameraRoll)); } } */ private void ShadowCascadeHook(nint unknownPtr, nint unknownPtr2) { if (disableMod) { shadowCascadeHook!.Original(unknownPtr, unknownPtr2); return; } #if HOOK_ORDER_ASSERTS debugLog($"ShadowCascadeHook({unknownPtr:x}, {unknownPtr2:x}) @ {frameTick}"); #endif ref nint rax = ref MemoryUtil.GetRef(unknownPtr2 + 0x170); nint shadowCascadeValue = rax >> 32; if (shadowCascadeValue != 3) { lastShadowCascadeValue = shadowCascadeValue; lastShadowBias = MemoryUtil.Read(unknownPtr2 + 0x17C); lastShadowRadius = MemoryUtil.Read(unknownPtr2 + 0x1EC); } float biasOverride = lastShadowBias + shadowBiasOffset; if (lowShadowDetailOverride && shadowCascadeValue == 1) { shadowCascadeValue++; rax = (nint)((shadowCascadeValue << 32) | (rax & 0x00000000FFFFFFFF)); biasOverride += shadowBiasOffset; } if (shadowCascadeValue != 3) { if (applyShadowBias) { // If HQ Mode is enabled, this value will be maxss'd with the HQ value before use. MemoryUtil.GetRef(unknownPtr2 + 0x17C) = biasOverride; } if (applyShadowRadius) { MemoryUtil.GetRef(unknownPtr2 + 0x1EC) = lastShadowRadius + shadowRadiusOffset; } } if (applyLODFactors) { // @TODO: Find a more proper place where we can update snow parameters. nint baseAddr = MemoryUtil.Read(0x1451C4368); MemoryUtil.GetRef(baseAddr + 0x5718) = snowField4GlobalLODParam; } shadowCascadeHook!.Original(unknownPtr, unknownPtr2); if (shadowCascadeValue != 3) { lastShadowDistance = MemoryUtil.GetRef(unknownPtr + 0x6C); lastShadowDistribution = MemoryUtil.GetRef(unknownPtr + 0x74); lastShadowBackforwardDistance = MemoryUtil.GetRef(unknownPtr + 0x7C); //lastBroadAreaShadowRange = MemoryUtil.GetRef(unknownPtr + 0x1B0); //lastShadowFov = MemoryUtil.GetRef(unknownPtr + 0x1F4); /* if (Area.CurrentStage == Stage.Astera) { // @TODO: Account for moving values. } */ if (applyShadowAdjust) { MemoryUtil.GetRef(unknownPtr + 0x6C) = shadowDistance; MemoryUtil.GetRef(unknownPtr + 0x74) = shadowDistribution; MemoryUtil.GetRef(unknownPtr + 0x7C) = shadowBackforwardDistance; //MemoryUtil.GetRef(unknownPtr + 0x1B0) = broadAreaShadowRange; //MemoryUtil.GetRef(unknownPtr + 0x1F4) = shadowFov; } } } private void setSSAOAdjustements(bool enable, bool b) { nint baseAddr = MemoryUtil.Read(0x1451C4368); if (enable) { MemoryUtil.WriteBytes(baseAddr + 0xB4BC, BitConverter.GetBytes(1.75f)); MemoryUtil.WriteBytes(baseAddr + 0xB4D0, BitConverter.GetBytes(16)); if (b) { MemoryUtil.WriteBytes(baseAddr + 0xB430, BitConverter.GetBytes(0.0f)); MemoryUtil.WriteBytes(baseAddr + 0xB434, BitConverter.GetBytes(0.0f)); MemoryUtil.WriteBytes(baseAddr + 0xB4E0, BitConverter.GetBytes(0.0f)); } else { MemoryUtil.WriteBytes(baseAddr + 0xB430, BitConverter.GetBytes(internalSSAOParams.effect)); MemoryUtil.WriteBytes(baseAddr + 0xB434, BitConverter.GetBytes(internalSSAOParams.effectGI)); MemoryUtil.WriteBytes(baseAddr + 0xB4E0, BitConverter.GetBytes(internalSSAOParams.intensity)); } } else { MemoryUtil.WriteBytes(baseAddr + 0xB4BC, BitConverter.GetBytes(internalSSAOParams.dispersion)); MemoryUtil.WriteBytes(baseAddr + 0xB430, BitConverter.GetBytes(internalSSAOParams.effect)); MemoryUtil.WriteBytes(baseAddr + 0xB434, BitConverter.GetBytes(internalSSAOParams.effectGI)); MemoryUtil.WriteBytes(baseAddr + 0xB4D0, BitConverter.GetBytes(internalSSAOParams.maxSampleNumHQ)); MemoryUtil.WriteBytes(baseAddr + 0xB4E0, BitConverter.GetBytes(internalSSAOParams.intensity)); } } private void setSSRAdjustements(bool enable) { nint baseAddr = MemoryUtil.Read(0x1451C4368); if (enable) { MemoryUtil.WriteBytes(baseAddr + 0xE644, BitConverter.GetBytes(0.2f)); MemoryUtil.WriteBytes(baseAddr + 0xE64C, BitConverter.GetBytes(0.2f)); } else { MemoryUtil.WriteBytes(baseAddr + 0xE644, BitConverter.GetBytes(internalSSRParams.accurateThreshold)); MemoryUtil.WriteBytes(baseAddr + 0xE64C, BitConverter.GetBytes(internalSSRParams.accurateThresholdHQ)); } } private void setHQMode(bool enable) { nint baseAddr = MemoryUtil.Read(0x1451C4368); MemoryUtil.WriteBytes(baseAddr + 0xE9A3, enable ? [0x1] : [0x0]); } private void RendererSetHook(nint unknownPtr, nint unknownPtr2, nint unknownPtr3) { if (disableMod) { rendererSetHook!.Original(unknownPtr, unknownPtr2, unknownPtr3); return; } bool doSet = MemoryUtil.Read(unknownPtr + 0x530) == 0x0; rendererSetHook!.Original(unknownPtr, unknownPtr2, unknownPtr3); nint baseAddr = MemoryUtil.Read(0x1451C4368); internalShadowSampleNumHQ = MemoryUtil.Read(baseAddr + 0xE5CC); MemoryUtil.WriteBytes(baseAddr + 0xE5CC, BitConverter.GetBytes(16)); internalSSAOParams.depthBias = MemoryUtil.Read(baseAddr + 0xB4B0); internalSSAOParams.slopedDepthBias = MemoryUtil.Read(baseAddr + 0xB4B4); internalSSAOParams.maxDepthBias = MemoryUtil.Read(baseAddr + 0xB4B8); internalSSAOParams.dispersion = MemoryUtil.Read(baseAddr + 0xB4BC); internalSSAOParams.effect = MemoryUtil.Read(baseAddr + 0xB430); internalSSAOParams.effectGI = MemoryUtil.Read(baseAddr + 0xB434); internalSSAOParams.depthDifference = MemoryUtil.Read(baseAddr + 0xB4C0); internalSSAOParams.samplesPerPixel = MemoryUtil.Read(baseAddr + 0xB4C4); internalSSAOParams.maxSampleNum = MemoryUtil.Read(baseAddr + 0xB4C8); internalSSAOParams.maxSampleNumHQ = MemoryUtil.Read(baseAddr + 0xB4D0); internalSSAOParams.radius = MemoryUtil.Read(baseAddr + 0xB4D4); internalSSAOParams.bias = MemoryUtil.Read(baseAddr + 0xB4D8); internalSSAOParams.intensity = MemoryUtil.Read(baseAddr + 0xB4E0); internalSSAOParams.useHiZ = MemoryUtil.Read(baseAddr + 0xB4E5) == 0x1; internalSSAOParams.edgeAttenRate = MemoryUtil.Read(baseAddr + 0xB4DC); internalSSRParams.loopCount = MemoryUtil.Read(baseAddr + 0xE628); internalSSRParams.loopCountFactorForCBR = MemoryUtil.Read(baseAddr + 0xE62C); internalSSRParams.eliminateDepth = MemoryUtil.Read(baseAddr + 0xE630); internalSSRParams.accurateThreshold = MemoryUtil.Read(baseAddr + 0xE644); internalSSRParams.accurateThresholdHQ = MemoryUtil.Read(baseAddr + 0xE64C); internalSSRParams.ditherRadius = MemoryUtil.Read(baseAddr + 0xE634); internalSSRParams.importanceBias = MemoryUtil.Read(baseAddr + 0xE638); internalSSRParams.mipScale = MemoryUtil.Read(baseAddr + 0xE63C); internalSSRParams.mipBias = MemoryUtil.Read(baseAddr + 0xE640); internalSSRParams.ditherResolve = MemoryUtil.Read(baseAddr + 0xB43F) == 0x1; internalSSRParams.edgeAttenRate = MemoryUtil.Read(baseAddr + 0xB428); internalSSRParams.mip0CountThreshold = MemoryUtil.Read(baseAddr + 0xB438); internalSSRParams.depthEliminateRate = MemoryUtil.Read(baseAddr + 0xB42C); internalSSRParams.useMipmap = MemoryUtil.Read(baseAddr + 0xE650) == 0x1; internalSSRParams.gBufferJitter = MemoryUtil.Read(baseAddr + 0xB440) == 0x1; internalSnowField4GlobalLODParam = MemoryUtil.Read(baseAddr + 0x5718); if (doSet) { if (ssaoAdjustments) { setSSAOAdjustements(true, ssaoB); } if (ssrAdjustments) { setSSRAdjustements(true); } setHQMode(enableHQMode); if (applyLODFactors) { setLODFactors(true); } } } private bool playerInMenu() { // https://github.com/HunterPie/HunterPie/blob/fa73f81ed0cdc921a6cf63f96c0fcff3688d88c2/HunterPie.Integrations/Datasources/MonsterHunterWorld/Entity/Game/MHWGame.cs#L74 bool inMenu = false; nint baseAddr = MemoryUtil.Read(0x1451C4640); if (baseAddr != 0x0) { baseAddr = MemoryUtil.Read(baseAddr + 0x13FD0); if (baseAddr != 0x0) { inMenu = MemoryUtil.Read(baseAddr + 0xB734) == 1; } } return inMenu; } // This can undoubtedly be simplified. private void WritePadInputHook(nint unknownPtr, nint unknownPtr2, nint unknownPtr3) { // Assume the primary pad always comes first. if (primaryPad == 0x0) { primaryPad = unknownPtr2; } if (disableMod || unknownPtr2 != primaryPad) { writePadInputHook!.Original(unknownPtr, unknownPtr2, unknownPtr3); return; } #if HOOK_ORDER_ASSERTS debugLog($"WritePadInputHook({unknownPtr:x}, {unknownPtr2:x}, {unknownPtr3:x}) @ {frameTick}"); #endif Button b1 = 0u, b2 = 0u; uint PadDown = 0u, PadTrg = 0u, PadRel = 0u, PadChg = 0u; if (enableCombo && freeCameraCombo != null) { b1 = freeCameraCombo[0]; b2 = freeCameraCombo[1]; if (disableComboButton1 && comboButton1Down) { uint b1u = (uint)b1; PadDown = MemoryUtil.Read(controllerAddr() + 0x198); PadDown |= b1u; MemoryUtil.WriteBytes(controllerAddr() + 0x198, BitConverter.GetBytes(PadDown)); } } writePadInputHook!.Original(unknownPtr, unknownPtr2, unknownPtr3); bool readInputsPostHook = false; PadLx = MemoryUtil.Read(controllerAddr() + 0x1B8); PadLy = MemoryUtil.Read(controllerAddr() + 0x1BC); PadRx = MemoryUtil.Read(controllerAddr() + 0x1B0); PadRy = MemoryUtil.Read(controllerAddr() + 0x1B4); if (enableCombo && freeCameraCombo != null) { if (disableComboButton1) { if (!readInputsPostHook) { PadDown = MemoryUtil.Read(controllerAddr() + 0x198); //PadOld = MemoryUtil.Read(controllerAddr() + 0x19C); PadTrg = MemoryUtil.Read(controllerAddr() + 0x1A0); PadRel = MemoryUtil.Read(controllerAddr() + 0x1A4); PadChg = MemoryUtil.Read(controllerAddr() + 0x1A8); prevPadDown = (prevPadDown == null) ? PadDown : lastPadDown; lastPadDown = PadDown; readInputsPostHook = true; } uint b1u = (uint)b1; if (comboButton1Down || enableFreeCamera || !buttonWasDown(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 (!readInputsPostHook) { PadDown = MemoryUtil.Read(controllerAddr() + 0x198); prevPadDown = (prevPadDown == null) ? PadDown : lastPadDown; lastPadDown = PadDown; } if ((comboButton1Down || (!disableComboButton1 && buttonWasDown(b1)))) { if (buttonWasPressed(b2)) { enableFreeCamera = !enableFreeCamera; } if (buttonWasPressed(Button.Share)) { uiToggled = !uiToggled; if (uiToggled) { jmpOverUi.Enable(); } else { jmpOverUi.Disable(); } if (unlockInputForMenu) { unlockInputHideMenu = uiToggled; } } if (buttonWasPressed(Button.L1)) { unlockInputToggled = !unlockInputToggled; } int presetSelect = (buttonWasPressed(Button.Up) ? -1 : 0) + (buttonWasPressed(Button.Down) ? 1 : 0); if (presetSelect != 0) { Config config = ConfigManager.GetConfig(this); Dictionary.KeyCollection presetKeys = config.Presets.Keys; if (presetKeys.Count > 0) { if (config.Selected != "") { int selectedIndex; for (selectedIndex = 0; selectedIndex < presetKeys.Count; selectedIndex++) { string presetKey = presetKeys.ElementAt(selectedIndex); if (presetKey == config.Selected) { break; } } selectedIndex += presetSelect; if (selectedIndex >= presetKeys.Count) { selectedIndex -= presetKeys.Count; } else if (selectedIndex < 0) { selectedIndex += presetKeys.Count; } config.Selected = presetKeys.ElementAt(selectedIndex); } else { config.Selected = presetKeys.ElementAt((presetSelect == 1) ? 0 : presetKeys.Count - 1); } setPerspectivePreset(config.Presets[config.Selected]); ConfigManager.SaveConfig(this); } } } if (unlockMovementHeld && buttonWasReleased(Button.R2)) { unlockMovementHeld = false; unlockMovementPause = false; } bool blockInput = comboButton1Down || (enableFreeCamera && !unlockInputToggled); /* if (enableFreeCamera) { // Hold both buttons and release either. We have to block until // release or it will get annoying to toggle input while on a menu. if (buttonWasDown(Button.R2)) { if (buttonWasReleased(Button.R1)) { unlockInputToggled = !unlockInputToggled; inputBlockedForToggle = false; blockInput = true; } else if (buttonWasDown(Button.R1)) { inputBlockedForToggle = true; blockInput = true; } } else if (buttonWasReleased(Button.R2) && inputBlockedForToggle) { unlockInputToggled = !unlockInputToggled; inputBlockedForToggle = false; blockInput = true; } } */ if (blockInput) { if (!readInputsPostHook) { //PadOld = MemoryUtil.Read(controllerAddr() + 0x19C); PadTrg = MemoryUtil.Read(controllerAddr() + 0x1A0); PadRel = MemoryUtil.Read(controllerAddr() + 0x1A4); PadChg = MemoryUtil.Read(controllerAddr() + 0x1A8); readInputsPostHook = true; } uint Mask = 0u; uint StartSelectMask = (uint)Button.Options | (uint)Button.Share; uint DPadMask = (uint)Button.Up | (uint)Button.Down | (uint)Button.Left | (uint)Button.Right; uint BumperMask = (uint)Button.L1 | (uint)Button.R1; uint StickMask = (uint)Button.LsUp | (uint)Button.LsDown | (uint)Button.LsLeft | (uint)Button.LsRight | (uint)Button.RsUp | (uint)Button.RsDown | (uint)Button.RsLeft | (uint)Button.RsRight; if (unlockInputForMenu) { // Idealy we wouldn't block Y or X here but triggering Rearrange or Edit Shoutout in // the gesture menu can desync our primitive "still in menu" handling when B is pressed. uint FaceButtonMask = (uint)Button.Triangle | (uint)Button.Square; Mask = FaceButtonMask | StartSelectMask; if (unlockInputHideMenu) { Mask |= (uint)Button.Circle; // Still allow A/Cross. Mask |= DPadMask | BumperMask | StickMask; } else if (buttonWasReleased(Button.Circle)) { unlockInputForMenu = false; unlockInputHideMenu = false; } } else { uint FaceButtonMask = (uint)Button.Cross | (uint)Button.Circle | (uint)Button.Square | (uint)Button.Triangle; Mask = FaceButtonMask | StartSelectMask | DPadMask | BumperMask | StickMask; } if (enableCombo && freeCameraCombo != null) { Mask &= ~((uint)b1 | (uint)b2); } PadDown &= ~Mask; //PadOld &= ~Mask; PadTrg &= ~Mask; PadRel &= ~Mask; PadChg &= ~Mask; MemoryUtil.WriteBytes(controllerAddr() + 0x198, BitConverter.GetBytes(PadDown)); //MemoryUtil.WriteBytes(controllerAddr() + 0x19C, BitConverter.GetBytes(PadOld)); MemoryUtil.WriteBytes(controllerAddr() + 0x1A0, BitConverter.GetBytes(PadTrg)); MemoryUtil.WriteBytes(controllerAddr() + 0x1A4, BitConverter.GetBytes(PadRel)); MemoryUtil.WriteBytes(controllerAddr() + 0x1A8, BitConverter.GetBytes(PadChg)); MemoryUtil.WriteBytes(controllerAddr() + 0x1C0, BitConverter.GetBytes(0)); // Left and right trigger. MemoryUtil.WriteBytes(controllerAddr() + 0x1C1, BitConverter.GetBytes(0)); MemoryUtil.WriteBytes(controllerAddr() + 0x1B0, BitConverter.GetBytes(0)); // Rx/y. MemoryUtil.WriteBytes(controllerAddr() + 0x1B4, BitConverter.GetBytes(0)); } if (enableFreeCamera) { if (playerMovementLocked) { MemoryUtil.WriteBytes(controllerAddr() + 0x1B8, BitConverter.GetBytes(0)); // Lx/y. MemoryUtil.WriteBytes(controllerAddr() + 0x1BC, BitConverter.GetBytes(0)); } if (orbitPlayer) { if (plusRight != 0.0f && !playerMovementLocked) { int Lx = (int)(Int16.MaxValue * Math.Clamp(plusRight, -1.0f, 1.0f)); MemoryUtil.WriteBytes(controllerAddr() + 0x1B8, BitConverter.GetBytes(Lx)); } if (plusForward != 0.0f) { int Ly = (int)(Int16.MaxValue * Math.Clamp(plusForward, -1.0f, 1.0f)); MemoryUtil.WriteBytes(controllerAddr() + 0x1BC, BitConverter.GetBytes(Ly)); } } if (!unlockMovementHeld && buttonWasPressed(Button.R2)) { unlockMovementHeld = true; } if (unlockMovementHeld) { if (buttonWasPressed(Button.L1)) { unlockMovementToggled = !unlockMovementToggled; } // Temporarily disable for zoom mode. if (buttonWasDown(Button.L2)) { unlockMovementPause = true; } else if (buttonWasReleased(Button.L2)) { unlockMovementPause = false; } } if (buttonWasDown(Button.L2) && buttonWasPressed(Button.L1)) { lockVerticalToggled = !lockVerticalToggled; } if (blockInput) { if (buttonWasDown(Button.R1)) { if (buttonWasPressed(Button.Down)) { Player? player = Player.MainPlayer; if (player != null) { // Y - 150 to approximately align the players head with the camera. player.Position = new Vector3(cameraPosition.X, cameraPosition.Y - 150.0f, cameraPosition.Z); } } if (buttonWasPressed(Button.Left)) { toggleFreezeGame(); } } if (buttonWasDown(Button.Share)) { if (buttonWasPressed(Button.Cross)) { ssaoB = !ssaoB; if (ssaoAdjustments) { setSSAOAdjustements(ssaoAdjustments, ssaoB); } } if (buttonWasPressed(Button.Circle)) { dofParams.nearEnable = !dofParams.nearEnable; /* dofDisabled = !dofDisabled; if (dofDisabled) { jmpOverDof.Enable(); } else { jmpOverDof.Disable(); } */ } } else if (freeCameraFromViewMode && !unlockInputForMenu && buttonWasPressed(Button.Circle)) { enableFreeCamera = false; } if (buttonWasPressed(Button.Options) && (plusRight != 0.0f || plusForward != 0.0f)) { if (buttonWasDown(Button.Share)) { plusRight = 0.0f; plusForward = 0.0f; } else { if (plusRight != 0.0f) { plusRight = -plusRight; } if (plusForward != 0.0f) { plusForward = -plusForward; } } } if (!unlockInputForMenu && buttonWasPressed(Button.Triangle)) { nint baseAddr = MemoryUtil.Read(0x1451C4640); // MonsterHunterWorld.exe+1ADA26A - 48 8B 83 18400100 - mov rax,[rbx+00014018] nint gesturesAddr = MemoryUtil.Read(baseAddr + 0x14018); if (buttonWasDown(Button.Share)) // MonsterHunterWorld.exe+1EC8000 { setupGestureMenu.Invoke(gesturesAddr, 0x0, 0x1); // Poses. } else // MonsterHunterWorld.exe+1EC7D10 { setupGestureMenu.Invoke(gesturesAddr, 0x0, 0x0); // Gestures. } showGestureMenu.Invoke(gesturesAddr); unlockInputForMenu = true; } } } } private float CheckMovementHook(int stickValue, float alwaysZero) { if (disableMod) { return checkMovementHook!.Original(stickValue, alwaysZero); } #if HOOK_ORDER_ASSERTS debugLog($"CheckMovementHook({stickValue:x}, {alwaysZero}) @ {frameTick}"); #endif if (freeCamera) { if (orbitPlayer && orbitIgnoreCamera && vCamera != null) { // Control the camera's influence on player movement separately. float dist = 700.0f - cameraForward; vCamera.Target.X = cameraPosition.X + dist * MathF.Cos(Single.DegreesToRadians(orbitMovementRotation)); vCamera.Target.Y = cameraPosition.Y; vCamera.Target.Z = cameraPosition.Z + dist * MathF.Sin(Single.DegreesToRadians(orbitMovementRotation)); } if (playerMovementLocked && (plusRight == 0.0f && plusForward == 0.0f)) { stickValue = 0; } } return checkMovementHook!.Original(stickValue, alwaysZero); } private void CollisionCheckHook(nint unknownPtr, nint unknownPtr2) { if (disableMod) { collisionCheckHook!.Original(unknownPtr, unknownPtr2); return; } #if HOOK_ORDER_ASSERTS debugLog($"CollisionCheckHook({unknownPtr:x}, {unknownPtr2:x}) @ {frameTick}"); #endif Player? player = Player.MainPlayer; if (enableCrawl && player != null) { nint controlsAddr = MemoryUtil.Read(player.Instance + 0x12608); bool combatControls = false; if (controlsAddr != 0x0) { combatControls = MemoryUtil.Read(controlsAddr + 0xB18) == 0x80; } if (combatControls) { procEnvironmentCollision.Invoke(player.Instance, psuedoObject1); procEnvironmentCollision.Invoke(player.Instance, psuedoObject2); } else { enableCrawl = false; } } collisionCheckHook!.Original(unknownPtr, unknownPtr2); } #if QUARANTINED_FEATURES private void SetZoneStateHook(nint player, int flags) { nint zoneStateAddr = MemoryUtil.Read(0x1451C42B8); ref byte zoneState = ref MemoryUtil.GetRef(zoneStateAddr + 0xD2EA); if (!zoneStateManualInvoke) { lastZoneState = (zoneState == 0x1) ? ZoneState.Hub : ZoneState.Combat; } else { zoneStateManualInvoke = false; } ZoneState overrideZoneState = forceZoneState; if (overrideZoneState == ZoneState.Unknown) { overrideZoneState = lastZoneState; } if (overrideZoneState != ZoneState.Unknown) { zoneState = byteFlag(overrideZoneState == ZoneState.Hub); } setZoneStateHook!.Original(player, flags); } #endif private void RefreshEntityParamsHook(nint entity, nint unknownPtr2) { refreshEntityParams!.Original(entity, unknownPtr2); if (disableMod || playerOpacityOverride == 1.0f) { return; } Player? player = Player.MainPlayer; if (player != null && entity == player.Instance) { MemoryUtil.GetRef(player.Instance + 0x78E0) = playerOpacityOverride; } } private void toggleFreezeGame() { freezeGame = !freezeGame; if (freezeGame) { motionBlurWasDisabled = motionBlurDisabled; motionBlurDisabled = true; decoupleDtFromGameTime = true; } else { motionBlurDisabled = motionBlurWasDisabled; decoupleDtFromGameTime = false; } MemoryUtil.WriteBytes(sMain.Instance + 0xA4, BitConverter.GetBytes(freezeGame ? 0.0f : 1.0f)); } private void MotionBlurHook(nint unknownPtr, nint unknownPtr2) { if (disableMod) { motionBlurHook!.Original(unknownPtr, unknownPtr2); return; } #if HOOK_ORDER_ASSERTS debugLog($"MotionBlurHook({unknownPtr:x}, {unknownPtr2:x}) @ {frameTick}"); #endif if (motionBlurDisabled) { MemoryUtil.WriteBytes(unknownPtr + 0x184, BitConverter.GetBytes(0.0f)); } motionBlurHook!.Original(unknownPtr, unknownPtr2); } private void DofHook(nint unknownPtr) { dofHook!.Original(unknownPtr); if (disableMod) { return; } #if HOOK_ORDER_ASSERTS debugLog($"DofHook({unknownPtr:x}) @ {frameTick}"); #endif nint unknownObj = MemoryUtil.Read(unknownPtr + 0x230); nint dofFilter = MemoryUtil.Read(unknownObj + 0x58); if (dofFilter != 0x0) { ref byte dofEnabled = ref MemoryUtil.GetRef(dofFilter + 0x1DD); ref byte newVersion = ref MemoryUtil.GetRef(dofFilter + 0x1DC); ref float fNumber = ref MemoryUtil.GetRef(dofFilter + 0x1A0); ref float sensorSize = ref MemoryUtil.GetRef(dofFilter + 0x1A4); ref float focusDistance = ref MemoryUtil.GetRef(dofFilter + 0x1A8); ref float nearCoef = ref MemoryUtil.GetRef(dofFilter + 0x1CC); ref float farCoef = ref MemoryUtil.GetRef(dofFilter + 0x1C8); ref byte nearEnable = ref MemoryUtil.GetRef(dofFilter + 0x1DE); ref byte farEnable = ref MemoryUtil.GetRef(dofFilter + 0x1DF); ref byte debugDraw = ref MemoryUtil.GetRef(dofFilter + 0x1E0); ref float radius = ref MemoryUtil.GetRef(dofFilter + 0x1D0); ref float depthScaleForeground = ref MemoryUtil.GetRef(dofFilter + 0x1D4); ref float aspect = ref MemoryUtil.GetRef(dofFilter + 0x1D8); ref byte vignettingEnabled = ref MemoryUtil.GetRef(dofFilter + 0x200); ref byte vignettingEllipse = ref MemoryUtil.GetRef(dofFilter + 0x201); ref float vignettingEllipticity = ref MemoryUtil.GetRef(dofFilter + 0x204); ref float vignettingOffset = ref MemoryUtil.GetRef(dofFilter + 0x1F8); ref float vignettingPow = ref MemoryUtil.GetRef(dofFilter + 0x1FC); ref int vignettingColor = ref MemoryUtil.GetRef(dofFilter + 0x208); if (fillOutDofParams) { dofParams.enabled = dofEnabled == 0x1; dofParams.newVersion = newVersion == 0x1; dofParams.fNumber = fNumber; dofParams.sensorSize = sensorSize; dofParams.focusDistance = focusDistance; dofParams.nearCoef = nearCoef; dofParams.farCoef = farCoef; dofParams.nearEnable = nearEnable == 0x1; dofParams.farEnable = farEnable == 0x1; dofParams.debugDraw = debugDraw == 0x1; dofParams.radius = radius; dofParams.depthScaleForeground = depthScaleForeground; dofParams.aspect = aspect; fillOutDofParams = false; } if (fillOutVignettingParams) { dofParams.vignettingEnabled = vignettingEnabled == 0x1; dofParams.vignettingEllipse = vignettingEllipse == 0x1; dofParams.vignettingEllipticity = vignettingEllipticity; dofParams.vignettingOffset = vignettingOffset; dofParams.vignettingPow = vignettingPow; dofParams.vignettingColor = vignettingColor; fillOutVignettingParams = false; } /* if ((dofEnabled == 0x0) != dofDisabled) { dofEnabled = byteFlag(!dofDisabled); } */ dofEnabled = byteFlag(dofParams.enabled); newVersion = byteFlag(dofParams.newVersion); fNumber = dofParams.fNumber; sensorSize = dofParams.sensorSize; focusDistance = dofParams.focusDistance; nearCoef = dofParams.nearCoef; farCoef = dofParams.farCoef; nearEnable = byteFlag(dofParams.nearEnable); farEnable = byteFlag(dofParams.farEnable); debugDraw = byteFlag(dofParams.debugDraw); radius = dofParams.radius; depthScaleForeground = dofParams.depthScaleForeground; aspect = dofParams.aspect; if (applyVignettingParams) { vignettingEnabled = byteFlag(dofParams.vignettingEnabled); vignettingEllipse = byteFlag(dofParams.vignettingEllipse); vignettingEllipticity = dofParams.vignettingEllipticity; vignettingOffset = dofParams.vignettingOffset; vignettingPow = dofParams.vignettingPow; vignettingColor = dofParams.vignettingColor; } } } private void UnderwaterCheckHook(nint unknownPtr) { underwaterCheckHook!.Original(unknownPtr); if (disableMod || !enableUnderwaterCamera) { return; } #if HOOK_ORDER_ASSERTS debugLog($"UnderwaterCheckHook({unknownPtr:x}) @ {frameTick}"); #endif cameraIsUnderwater = MemoryUtil.Read(unknownPtr + 0x1E83) == 0x1; } private void CameraEffectHook(nint unknownPtr, nint unknownPtr2, nint unknownPtr3) { if (disableMod || !enableUnderwaterCamera) { cameraEffectHook!.Original(unknownPtr, unknownPtr2, unknownPtr3); return; } #if HOOK_ORDER_ASSERTS debugLog($"CameraEffectHook({unknownPtr:x}, {unknownPtr2:x}, {unknownPtr3:x}) @ {frameTick}"); #endif byte[]? underwaterValues = null; nint targetAddr = 0x0; nint rax = MemoryUtil.Read(unknownPtr + 0x550); int index1 = MemoryUtil.Read(unknownPtr + 0xA50); rax = MemoryUtil.Read(rax + (index1 * 0x8)); if (rax != 0x0) { rax = MemoryUtil.Read(rax + 0x188); if (rax != 0x0) { targetAddr = rax + 0x140; } } if (cameraIsUnderwater) { underwaterValues = MemoryUtil.ReadArray(targetAddr + 0x8, 120); // Straight copy-paste from The Great Forest. MemoryUtil.WriteBytes(targetAddr + 0x8, [0x01, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6F, 0x12, 0x03, 0x3B, 0x01, 0x00, 0x00, 0x00, 0xCE, 0xCC, 0xCC, 0x3E, 0x01, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x3F, 0x8F, 0xC2, 0xF5, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x60, 0xEA, 0x46, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x42]); } cameraEffectHook!.Original(unknownPtr, unknownPtr2, unknownPtr3); if (cameraIsUnderwater && underwaterValues != null) { MemoryUtil.WriteBytes(targetAddr + 0x8, underwaterValues); } } private nint CreateLightingObjectHook(nint unknownPtr) { lightingObject = createLightingObject!.Original(unknownPtr); return lightingObject; } private nint DestroyLightingObjectHook(nint unknownPtr, nint unknownPtr2) { lightingObject = 0x0; return destroyLightingObject!.Original(unknownPtr, unknownPtr2); } private nint CreateFXAAObjectHook(nint unknownPtr, int unknownInt) { fxaaObject = createFXAAObject!.Original(unknownPtr, unknownInt); return fxaaObject; } private nint DestroyFXAAObjectHook(nint unknownPtr, int unknownInt) { fxaaObject = 0x0; return destroyFXAAObject!.Original(unknownPtr, unknownInt); } private void drawViewportInfo(int i, float width, Config config, bool debug) { Viewport vp = CameraSystem.GetViewport(i); if (debug) { ImGui.Text($"Address: {vp.Instance:x}"); ImGui.Text($"Visible: {vp.Visible}"); ImGui.Text($"Region: {vp.Region.X} {vp.Region.Y} {vp.Region.Width} {vp.Region.Height}"); } else { ImGui.Text($"Resolution: {vp.Region.Width}x{vp.Region.Height}"); } if (vp.Visible) { bool disableFadingObjects = getDisableFadingObjects(i); if (ImGui.Checkbox("Disable Fading Objects When Close to Camera", ref disableFadingObjects)) { setDisableFadingObjects(i, disableFadingObjects); } } if (vp.Camera != null) { Camera camera = vp.Camera; bool usedByFreeCamera = freeCamera && enableFreeCamera && camera == vCamera; if (debug) ImGui.Text($"Camera Pointer: {camera.Instance:x}"); if (ImGui.DragFloat("Field of View", ref camera.FieldOfView, 0.1f)) { if (usedByFreeCamera) { cameraFov = camera.FieldOfView; } } if (camera == pCamera) { ImGui.Text($"Internal FOV: {previousFov}"); if (ImGui.BeginItemTooltip()) { ImGui.Text("What the FOV would be if not set by us."); ImGui.EndTooltip(); } } if (debug) ImGui.InputFloat("Aspect Ratio", ref camera.AspectRatio); ImGui.InputFloat("Near Clip", ref camera.NearClip); ImGui.InputFloat("Far Clip", ref camera.FarClip); if (usedByFreeCamera) { ImGui.DragFloat3("Position", ref cameraPosition, 0.425f); } else { ImGui.DragFloat3("Position", ref camera.Position, 0.425f); } ImGui.DragFloat3("Target", ref camera.Target, 0.425f); ImGui.DragFloat3("Up", ref camera.Up, 0.425f); ImGui.PushItemWidth(width * 0.15f); ImGui.InputText("##Position Name", ref typedPositionName, 99); ImGui.SameLine(); if (ImGui.Button("Save")) { string name = typedPositionName; if (name != "") { Config.Position pos = new Config.Position(); pos.FieldOfView = camera.FieldOfView; pos.PosX = camera.Position.X; pos.PosY = camera.Position.Y; pos.PosZ = camera.Position.Z; pos.TargetX = camera.Target.X; pos.TargetY = camera.Target.Y; pos.TargetZ = camera.Target.Z; pos.Roll = cameraRoll; if (config.Positions.ContainsKey(name)) { config.Positions[name] = pos; } else { config.Positions.Add(name, pos); } ConfigManager.SaveConfig(this); } } ImGui.SameLine(); if (ImGui.BeginCombo("##Positions", selectedPositionName)) { Dictionary.KeyCollection positionKeys = config.Positions.Keys; for (int j = 0; j < positionKeys.Count + 1; j++) { if (j == 0) { if (ImGui.Selectable("(Deselect)")) { selectedPositionName = ""; } continue; } string positionKey = positionKeys.ElementAt(j - 1); if (ImGui.Selectable(positionKey)) { Config.Position pos = config.Positions[positionKey]; selectedPositionName = positionKey; camera.FieldOfView = pos.FieldOfView; cameraPosition = new Vector3(pos.PosX, pos.PosY, pos.PosZ); cameraTarget = new Vector3(pos.TargetX, pos.TargetY, pos.TargetZ); Quaternion forward = Quaternion.Normalize(getForward(cameraPosition, cameraTarget)); cameraYaw = Single.RadiansToDegrees(MathF.Atan2(forward.Z, forward.X)); cameraPitch = Single.RadiansToDegrees(MathF.Asin(forward.Y)); camera.Position = cameraPosition; camera.Target = cameraTarget; cameraRoll = pos.Roll; } } ImGui.EndCombo(); } ImGui.PopItemWidth(); ImGui.SameLine(); if (ImGui.Button("Delete")) { if (selectedPositionName != "") { config.Positions.Remove(selectedPositionName); selectedPositionName = ""; ConfigManager.SaveConfig(this); } } if (debug) { bool move = camera.Move; if (ImGui.Checkbox("Move", ref move)) { camera.Move = move; } if (ImGui.BeginItemTooltip()) { ImGui.Text("Uncheck this to allow manually overriding the camera position.\nIf your camera is frozen, make sure this is checked."); ImGui.EndTooltip(); } ImGui.SameLine(); bool fix = camera.Fix; if (ImGui.Checkbox("Fix", ref fix)) { camera.Fix = fix; } } if (camera == vCamera) { if (!usedByFreeCamera) { ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); } // If our camera hooks aren't being run, these values won't be updated. ImGui.DragFloat("Yaw", ref cameraYaw, 0.2f); ImGui.DragFloat("Pitch", ref cameraPitch, 0.2f); ImGui.DragFloat("Roll", ref cameraRoll, 0.2f); if (!usedByFreeCamera) { ImGui.PopItemFlag(); } // Try to grey out offsets when they probably have no effect. if ((camera == pCamera && !usedByFreeCamera) && camera.Move) { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } ImGui.Text("Offsets"); float offsetForward = 0.0f; if (ImGui.DragFloat("Forward", ref offsetForward, 0.425f)) { Quaternion forward = getForward(camera.Position, camera.Target); forward = Quaternion.Normalize(forward); camera.Position.X += forward.X * offsetForward; camera.Position.Y += forward.Y * offsetForward; camera.Position.Z += forward.Z * offsetForward; if (usedByFreeCamera) cameraPosition = camera.Position; } float offsetRight = 0.0f; if (ImGui.DragFloat("Right", ref offsetRight, 0.425f)) { Quaternion forward = getForward(camera.Position, camera.Target); Quaternion right = getRight(forward); forward = Quaternion.Normalize(forward); right = Quaternion.Normalize(right); camera.Position.X += right.X * offsetRight; camera.Position.Z += right.Z * offsetRight; if (usedByFreeCamera) cameraPosition = camera.Position; } float offsetUp = 0.0f; if (ImGui.DragFloat("Up", ref offsetUp, 0.425f)) { camera.Position.Y += offsetUp; if (usedByFreeCamera) cameraPosition = camera.Position; } if (camera == pCamera && !(freeCamera || enableFreeCamera)) { ImGui.PopStyleVar(); } } } } private void drawAnimationInfo(Entity entity) { ActionInfo currentActionInfo = entity.ActionController.CurrentAction; SharpPluginLoader.Core.Actions.Action? currentAction = null; if (currentActionInfo.ActionSet >= 0 && currentActionInfo.ActionSet <= 3) { ActionList actionList = entity.ActionController.GetActionList(currentActionInfo.ActionSet); if (currentActionInfo.ActionId >= 0 && currentActionInfo.ActionId < actionList.Count) { currentAction = actionList[currentActionInfo.ActionId]; } } AnimationId currentAnimation = entity.CurrentAnimation; ImGui.Text("Action/Animation:"); ImGui.Text($"ActionController: {entity.ActionController.Instance:x}"); ImGui.Text($" Current: {currentAction} {currentActionInfo}, {currentAnimation}"); if (currentAction != null) { ImGui.Text($" Active Time: {currentAction.ActiveTime}"); ImGui.Text($" Delta Sec: {currentAction.DeltaSec}"); } AnimationLayerComponent? animationLayer = entity.AnimationLayer; if (animationLayer != null) { ImGui.Text($"AnimationLayer: {animationLayer.Instance:x}"); ImGui.Text($" Speed: {animationLayer.Speed:0.000}"); ImGui.Text($" Frame: {animationLayer.CurrentFrame:0.000}/{animationLayer.MaxFrame:0.000}"); } } private static T drawRenderParameter(string name, nint baseAddr = 0x0, nint offset = 0x0, bool zeroToOne = false, float step = 0.0f) where T : unmanaged { nint addr = baseAddr + offset; T? currentValue = null; if (currentValue == null) { currentValue = MemoryUtil.Read(addr); } if (typeof(T) == typeof(float)) { float valueF = Convert.ToSingle(currentValue); if (zeroToOne) { if (ImGui.DragFloat(name, ref valueF, 0.01f, 0.0f, 1.0f, "%.6f")) { MemoryUtil.WriteBytes(addr, BitConverter.GetBytes(valueF)); } } else { if (ImGui.InputFloat(name, ref valueF, 0.0f, 0.0f, "%.6f", ImGuiInputTextFlags.EnterReturnsTrue)) { MemoryUtil.WriteBytes(addr, BitConverter.GetBytes(valueF)); } } return (T)Convert.ChangeType(valueF, typeof(T)); } else if (typeof(T) == typeof(int)) { int valueI = Convert.ToInt32(currentValue); int stepI = (int)Math.Round(step); if (ImGui.InputInt(name, ref valueI, stepI, 0, ImGuiInputTextFlags.EnterReturnsTrue)) { MemoryUtil.WriteBytes(addr, BitConverter.GetBytes(valueI)); } return (T)Convert.ChangeType(valueI, typeof(T)); } else if (typeof(T) == typeof(byte)) { bool valueSwitch = Convert.ToByte(currentValue) == 0x1; if (ImGui.Checkbox(name, ref valueSwitch)) { MemoryUtil.WriteBytes(addr, valueSwitch ? [0x1] : [0x0]); } return (T)Convert.ChangeType(valueSwitch, typeof(T)); } return (T)currentValue; } private static void inputSSAOParameters(SSAOParameters? parameters, nint baseAddr) { if (parameters == null) { drawRenderParameter("SSAO Depth Bias", baseAddr, 0xB4B0); drawRenderParameter("SSAO Sloped Depth Bias", baseAddr, 0xB4B4); drawRenderParameter("SSAO Max Depth Bias", baseAddr, 0xB4B8); drawRenderParameter("SSAO Dispersion", baseAddr, 0xB4BC); drawRenderParameter("SSAO Effect", baseAddr, 0xB430); drawRenderParameter("SSAO Effect GI", baseAddr, 0xB434); drawRenderParameter("SSAO Depth Difference", baseAddr, 0xB4C0); drawRenderParameter("SSAO Samples Per Pixel", baseAddr, 0xB4C4); drawRenderParameter("SSAO Max Sample Num", baseAddr, 0xB4C8); drawRenderParameter("SSAO Max Sample Num HQ", baseAddr, 0xB4D0); drawRenderParameter("SSAO Radius", baseAddr, 0xB4D4); drawRenderParameter("SSAO Bias", baseAddr, 0xB4D8); drawRenderParameter("SSAO Intensity", baseAddr, 0xB4E0); drawRenderParameter("SSAO Use HiZ", baseAddr, 0xB4E5); drawRenderParameter("SSAO Edge Atten Rate", baseAddr, 0xB4DC); } } private void disableAllCollisionHooks() { if (disableExtraGravity) { disableExtraGravity = false; disableExtraGravityDisable(); } if (disableGravity) { disableGravity = false; disableGravityDisable(); } if (disableExtraCollision) { disableExtraCollision = false; disableExtraCollisionDisable(); } if (disableCollision) { disableCollision = false; disableCollisionDisable(); } } private void tryToDisableMod(Player? player) { disableAllCollisionHooks(); if (freeCamera) { disableFreeCamera(); } for (int i = 0; i < 8; i++) { Viewport vp = CameraSystem.GetViewport(i); if (vp.Camera != null) { vp.Camera.Move = true; } setDisableFadingObjects(i, false); } if (player != null) { player.Rotation.X = 0.0f; player.Rotation.Z = 0.0f; } if (tripleShadowRes) { tripleShadowResDisable(); } if (ssaoAdjustments) { setSSAOAdjustements(false, ssaoB); } if (ssrAdjustments) { setSSRAdjustements(false); } if (enableHQMode) { setHQMode(false); } if (disableLODLimits) { disableLODLimitsDisable(); } if (areLODFactorsSet() && !areLODFactorsDefault()) { setLODFactors(false); } if (largerFoliageSwayRange) { addressHigherValueForFoliageSway.Disable(); } if (disableReducedRateAnimations) { zeroFrameSkip.Disable(); } // @TODO: Volume rendering. if (disableCharacterFade) { noopCharacterFade.Disable(); } if (dofDisabled) { jmpOverDof.Disable(); } if (enableUnderwaterCamera) { underwaterCameraDisable(); } if (allowHotSpringsAnywhere) { jmpOverHotSpringsEval.Disable(); } if (disableHotSpringsSteam) { jmpOverHotSpringsSteam.Disable(); } } private void tryToEnableMod() { if (tripleShadowRes) { tripleShadowResEnable(); } if (ssaoAdjustments) { setSSAOAdjustements(true, ssaoB); } if (ssrAdjustments) { setSSRAdjustements(true); } if (enableHQMode) { setHQMode(true); } if (disableLODLimits) { disableLODLimitsEnable(); } if (applyLODFactors && !areLODFactorsDefault()) { setLODFactors(true); } if (largerFoliageSwayRange) { addressHigherValueForFoliageSway.Enable(); } if (disableReducedRateAnimations) { zeroFrameSkip.Enable(); } if (pCameraViewportIndex >= 0) { setDisableFadingObjects(pCameraViewportIndex, disableFading); } if (disableCharacterFade) { noopCharacterFade.Enable(); } if (dofDisabled) { jmpOverDof.Enable(); } if (enableUnderwaterCamera) { underwaterCameraEnable(); } if (allowHotSpringsAnywhere) { jmpOverHotSpringsEval.Enable(); } if (disableHotSpringsSteam) { jmpOverHotSpringsSteam.Enable(); } } #if SHADER_FEATURES private bool shadersLoadedOnce = false; public unsafe void OnCreateShader(ShaderInfo *info) { if (shadersLoadedOnce) { return; } string hash = new string(info->DxbcHash); if (hash == "2e4e18fd-6ea5eeae-2de3d65c-26ab36dd") { byte[] shaderData; try { shaderData = System.IO.File.ReadAllBytes("./volume_upsample_edit.shdr"); } catch (Exception) { return; } info->NewSourceType = SourceType.BINARY; info->NewSourceLength = shaderData.Length; info->NewSource = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(shaderData, 0); Log.Info("Replaced volume upsample shader 1."); } else if (hash == "e2c8c13e-45bc99b2-4c3d7699-3d66188e") { byte[] shaderData; try { shaderData = System.IO.File.ReadAllBytes("./volume_upsample2_edit.shdr"); } catch (Exception) { return; } info->NewSourceType = SourceType.BINARY; info->NewSourceLength = shaderData.Length; info->NewSource = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(shaderData, 0); Log.Info("Replaced volume upsample shader 2."); // This interestingly allows us to A/B using the volume rendering value 2 switch. shadersLoadedOnce = true; } } #endif public void OnImGuiRender() { #if HOOK_ORDER_ASSERTS debugLog($"OnImGuiRender() @ {frameTick}"); #endif Config config = ConfigManager.GetConfig(this); float width = ImGui.GetWindowWidth(); // If we use vCamera or pCamera here, we need to ensure they're not invalid. Player? player = checkPlayerChange(); checkCurrentVisibleCamera(player); if (ImGui.Checkbox("Disable Mod", ref disableMod)) { if (disableMod) { tryToDisableMod(player); } else { tryToEnableMod(); } config.DisableMod = disableMod; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Try to disable as much as possible."); ImGui.EndTooltip(); } if (disableMod) { return; } ImGui.Separator(); ImGui.Checkbox("Enable Free Camera", ref enableFreeCamera); if (enableFreeCamera) { ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } if (ImGui.Checkbox("Enable Perspective Camera", ref enableOffsetPerspective)) { config.PerspectiveCameraEnabled = enableOffsetPerspective; ConfigManager.SaveConfig(this); } if (enableFreeCamera) { ImGui.PopItemFlag(); ImGui.PopStyleVar(); } ImGui.PushID("Perspective"); ImGui.PushItemWidth(width * 0.575f); ImGui.DragFloat("Field of View", ref cameraFov, 0.4f, 1.0f, 179.0f); ImGui.DragFloat("Forward", ref cameraForward, 0.25f); ImGui.DragFloat("Right", ref cameraRight, 0.25f); ImGui.DragFloat("Up", ref cameraUp, 0.025f); if (ImGui.DragFloat("Roll", ref cameraRoll, 0.25f)) { if (restoreRoll != null) { restoreRoll = cameraRoll; } } if (freeCamera) { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } ImGui.PopItemWidth(); if (ImGui.Checkbox("Disable Fading", ref disableFading)) { if (pCameraViewportIndex >= 0) { setDisableFadingObjects(pCameraViewportIndex, disableFading); } setDisableCharacterFade(disableFading); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Disable transparency fading when the camera gets close to something.\nApplies to Objects, Players, Palicos and NPCs.\nEnabled by default while in free camera."); ImGui.EndTooltip(); } if (freeCamera) { ImGui.PopStyleVar(); } if (ImGui.Button("Default")) { cameraFov = DEFAULT_FOV; cameraForward = 0.0f; cameraRight = 0.0f; cameraUp = 0.0f; cameraRoll = 0.0f; if (restoreRoll != null) { restoreRoll = cameraRoll; } disableFading = false; if (pCameraViewportIndex >= 0) { setDisableFadingObjects(pCameraViewportIndex, false); } setDisableCharacterFade(false); config.Selected = ""; ConfigManager.SaveConfig(this); } ImGui.SameLine(); ImGui.PushItemWidth(width * 0.2f); ImGui.InputText("##Preset Name", ref typedPresetName, 99); ImGui.SameLine(); if (ImGui.Button("Save")) { string name = typedPresetName; if (name != "") { Config.Preset preset = new Config.Preset(); preset.FieldOfView = cameraFov; preset.Forward = cameraForward; preset.Right = cameraRight; preset.Up = cameraUp; preset.Roll = cameraRoll; preset.DisableFading = (pCameraViewportIndex >= 0) ? getDisableFadingObjects(pCameraViewportIndex) : false; if (config.Presets.ContainsKey(name)) { config.Presets[name] = preset; } else { config.Presets.Add(name, preset); } config.Selected = name; ConfigManager.SaveConfig(this); } } ImGui.SameLine(); if (ImGui.BeginCombo("##Preset", config.Selected)) { Dictionary.KeyCollection presetKeys = config.Presets.Keys; for (int i = 0; i < presetKeys.Count; i++) { string presetKey = presetKeys.ElementAt(i); bool isSelected = presetKey == config.Selected; if (ImGui.Selectable(presetKey, isSelected)) { config.Selected = presetKey; setPerspectivePreset(config.Presets[config.Selected]); ConfigManager.SaveConfig(this); } if (isSelected) ImGui.SetItemDefaultFocus(); } ImGui.EndCombo(); } ImGui.PopItemWidth(); ImGui.SameLine(); if (ImGui.Button("Delete")) { if (config.Selected != "") { config.Presets.Remove(config.Selected); config.Selected = ""; ConfigManager.SaveConfig(this); } } ImGui.PopID(); ImGui.PushID("Settings"); ImGui.PushItemWidth(width * 0.575f); ImGui.DragFloat("Camera Speed", ref cameraSpeed, 0.01f, 0.0f, 0.0f, "%.4f"); if (ImGui.BeginItemTooltip()) { ImGui.Text("Movement speed in free camera."); ImGui.EndTooltip(); } ImGui.DragFloat("Speed Modifier", ref cameraSpeedModifier, 0.01f, 0.0f, 0.0f, "%.4f"); if (ImGui.BeginItemTooltip()) { ImGui.Text("Value to multiply speed by when LT is held."); ImGui.EndTooltip(); } ImGui.DragFloat("Camera Sensitivity", ref cameraSensitivity, 0.001f, 0.0f, 0.0f, "%.4f"); if (ImGui.BeginItemTooltip()) { ImGui.Text("Look sensitivity in free camera."); ImGui.EndTooltip(); } ImGui.DragFloat("Zoom Speed", ref cameraZoomSpeed, 0.01f, 0.0f, 0.0f, "%.4f"); if (ImGui.InputFloat("Pitch Limit", ref cameraPitchLimit, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue)) { if (cameraPitchLimit != -1.0f) { cameraPitchLimit = Math.Clamp(cameraPitchLimit, 0.0f, Config.Settings.MAX_PITCH_LIMIT); } } if (ImGui.BeginItemTooltip()) { ImGui.Text($"-1.0 = Wrap around (go upside down), Max: {Config.Settings.MAX_PITCH_LIMIT:0.00}."); ImGui.EndTooltip(); } ImGui.DragInt("Stick Deadzone", ref stickDeadzone, 5, 0); ImGui.PopItemWidth(); /* if (ImGui.Button("Default")) { cameraSpeed = Config.Settings.DEFAULT_SPEED; cameraSpeedModifier = Config.Settings.DEFAULT_SPEED_MODIFIER; cameraSensitivity = Config.Settings.DEFAULT_SENSITIVITY; cameraZoomSpeed = Config.Settings.DEFAULT_ZOOM_SPEED; cameraPitchLimit = Config.Settings.DEFAULT_PITCH_LIMIT; stickDeadzone = Config.Settings.DEFAULT_DEADZONE; alternateNearClip = Config.Settings.DEFAULT_ALT_NEAR_CLIP; } ImGui.SameLine(); */ if (ImGui.Button("Reset")) { Config.Settings camera = config.Camera; cameraSpeed = camera.Speed; cameraSpeedModifier = camera.SpeedModifier; cameraSensitivity = camera.Sensitivity; cameraZoomSpeed = camera.ZoomSpeed; cameraPitchLimit = camera.PitchLimit; stickDeadzone = camera.StickDeadzone; alternateNearClip = camera.AlternateNearClip; } ImGui.SameLine(); if (ImGui.Button("Save")) { Config.Settings camera = config.Camera; camera.Speed = cameraSpeed; camera.SpeedModifier = cameraSpeedModifier; camera.Sensitivity = cameraSensitivity; camera.ZoomSpeed = cameraZoomSpeed; camera.PitchLimit = cameraPitchLimit; camera.StickDeadzone = stickDeadzone; config.Camera = camera; ConfigManager.SaveConfig(this); } ImGui.PopID(); ImGui.Separator(); ImGui.PushID("Toggles"); ImGui.Text("Toggles"); if (ImGui.Checkbox("Disable UI", ref uiToggled)) { if (uiToggled) { jmpOverUi.Enable(); } else { jmpOverUi.Disable(); } } if (ImGui.BeginItemTooltip()) { ImGui.Text("The scoutfly marker on menus will still be visible."); ImGui.EndTooltip(); } if (!freeCamera || freeCameraFallback) { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } ImGui.SameLine(); ImGui.Checkbox("Unlock Input", ref unlockInputToggled); ImGui.Checkbox("Unlock Player Movement", ref unlockMovementToggled); ImGui.Checkbox("Lock Vertical Movement and Apply Speed Modifier", ref lockVerticalToggled); ImGui.Checkbox("Orbit Player", ref orbitPlayer); if (ImGui.BeginItemTooltip()) { ImGui.Text("Use left stick up/down to move the camera forward/back and d-pad up/down to set the Y target."); ImGui.EndTooltip(); } ImGui.SameLine(); ImGui.Checkbox("Ignore Camera Direction", ref orbitIgnoreCamera); if (ImGui.BeginItemTooltip()) { ImGui.Text("Left stick right/left will gradually shift your forward direction."); ImGui.EndTooltip(); } if (!freeCamera || freeCameraFallback) { ImGui.PopStyleVar(); } if (ImGui.Checkbox("Disable Depth of Field", ref dofDisabled)) { if (dofDisabled) { jmpOverDof.Enable(); } else { jmpOverDof.Disable(); } } if (ImGui.BeginItemTooltip()) { ImGui.Text("Works to disable depth of field in cutscenes."); ImGui.EndTooltip(); } ImGui.SameLine(); float alignCursorX = ImGui.GetCursorPosX(); ImGui.Checkbox("Disable Motion Blur", ref motionBlurDisabled); if (ImGui.BeginItemTooltip()) { ImGui.Text("Motion blur completely breaks when freezing the game."); ImGui.EndTooltip(); } if (!ssaoAdjustments) { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } if (ImGui.Checkbox("Disable SSAO", ref ssaoB)) { if (ssaoAdjustments) { setSSAOAdjustements(ssaoAdjustments, ssaoB); } } if (!ssaoAdjustments) { ImGui.PopStyleVar(); } if (ImGui.BeginItemTooltip()) { if (!ssaoAdjustments) { ImGui.Text("Enable SSAO Adjustments under Graphical Tweaks for this to apply."); } else { ImGui.Text("Currently doesn't work in cutscenes."); } ImGui.EndTooltip(); } if (vCamera != null) { ImGui.SameLine(); ImGui.SetCursorPosX(alignCursorX); ImGui.PushItemWidth(width * 0.12f); bool altNearClipSet = guessAltNearClipSet(vCamera); if (ImGui.Checkbox("Alternate Near Clip", ref altNearClipSet)) { setNearClip(vCamera, altNearClipSet); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Changing the near clip will subtly break rendering of various effects.\nTemporarily lowering the near clip can allow you to get the camera closer to things without clipping."); ImGui.EndTooltip(); } ImGui.SameLine(); if (ImGui.DragFloat("##Alternate Near Clip", ref alternateNearClip, 0.05f, 0.001f, 0.0f)) { if (altNearClipSet) { vCamera.NearClip = alternateNearClip; } } ImGui.SameLine(); if (ImGui.Button("Save")) { Config.Settings camera = config.Camera; camera.AlternateNearClip = alternateNearClip; config.Camera = camera; ConfigManager.SaveConfig(this); } ImGui.PopItemWidth(); } ImGui.Separator(); ImGui.Text("When Close to the Camera"); if (ImGui.BeginItemTooltip()) { ImGui.Text("Set Disable Fading in the camera preset above for these to persist."); ImGui.EndTooltip(); } if (vCameraViewportIndex >= 0) { bool disableFadingObjects = getDisableFadingObjects(vCameraViewportIndex); if (ImGui.Checkbox("Disable Fading Objects", ref disableFadingObjects)) { setDisableFadingObjects(vCameraViewportIndex, disableFadingObjects); } } if (ImGui.Checkbox("Disable Fading Player/Palico/NPCs", ref disableCharacterFade)) { if (disableCharacterFade) { noopCharacterFade.Enable(); } else { noopCharacterFade.Disable(); } } ImGui.PopID(); ImGui.Separator(); ImGui.PushID("Binds"); if (ImGui.CollapsingHeader("Binds")) { if (ImGui.Checkbox("Toggle Free Camera", ref enableCombo)) { Config.Settings.Binds binds = config.Binds; binds.EnableCombo = enableCombo; config.Binds = binds; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Hold the first button (Button1) then press the second (Button2)."); ImGui.EndTooltip(); } ImGui.SameLine(); if (freeCameraCombo == null) { ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0000FF); } ImGui.PushItemWidth(width * 0.15f); ImGui.InputText("##Toggle Free Camera", ref typedCombo, 12); if (freeCameraCombo == null) { ImGui.PopStyleColor(); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Form: RT+LB, R3+L2, A+LStick, Up+RT, Cross+Triangle, etc."); ImGui.EndTooltip(); } ImGui.PopItemWidth(); ImGui.SameLine(); if (ImGui.Button("Save")) { string comboString = typedCombo.Replace("+", ","); freeCameraCombo = Config.ParseCombo(comboString); if (freeCameraCombo != null) { Config.Settings.Binds binds = config.Binds; binds.FreeCameraCombo = comboString; config.Binds = binds; ConfigManager.SaveConfig(this); } } ImGui.SameLine(); if (ImGui.Checkbox("Disable Button1 Unless Button2 is Held", ref disableComboButton1)) { comboButton1Down = false; Config.Settings.Binds binds = config.Binds; binds.DisableComboButton1UnlessButton2Held = disableComboButton1; config.Binds = binds; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("For example, if bound to RStick+LT, right stick presses will ignored by the game unless you're holding the left trigger.\nIn that case, it can let you avoid switching the targeted monster when toggling free camera."); ImGui.EndTooltip(); } ImGui.Text("Global"); if (ImGui.BeginItemTooltip()) { ImGui.Text("Button1 refers to the first button of the Toggle Free Camera bind."); ImGui.EndTooltip(); } if (ImGui.BeginTable("Global Binds", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) { ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Hold Button1 + Press Select"); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle UI"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Hold Button1 + Press D-Pad Up/Down"); ImGui.TableSetColumnIndex(1); ImGui.Text("Select Perspective Camera Preset"); ImGui.EndTable(); } ImGui.Text("While in Free Camera | ( ) = Toggle"); if (ImGui.BeginTable("Binds", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) { ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Hold Button1 + Press LB"); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle Unlock Input"); if (ImGui.BeginItemTooltip()) { ImGui.Text("Attempts to apply to every controller input except left stick player movement."); ImGui.EndTooltip(); } ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Hold RT (+ Press LB)"); ImGui.TableSetColumnIndex(1); ImGui.Text("Unlock Player Movement and Freeze Camera Movement"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Hold LT (+ Press LB)"); ImGui.TableSetColumnIndex(1); ImGui.Text("Lock Vertical Camera Movement and Apply Speed Modifier"); ImGui.EndTable(); } ImGui.Text("Disabled While Input to the Game is Unlocked"); if (ImGui.BeginTable("More Binds", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) { ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("D-Pad Up/Down"); ImGui.TableSetColumnIndex(1); ImGui.Text("Translate Camera Up/Down"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("D-Pad Left/Right"); ImGui.TableSetColumnIndex(1); ImGui.Text("Roll Camera"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Hold LT + RT"); ImGui.TableSetColumnIndex(1); ImGui.Text("Zoom with Left Stick Up/Down"); if (ImGui.BeginItemTooltip()) { ImGui.Text("If you have Depth of Field enabled in Advanced Graphics Settings, this will also move the focal point."); ImGui.EndTooltip(); } ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Press Y"); ImGui.TableSetColumnIndex(1); ImGui.Text("Open Gestures Menu"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Hold Select"); ImGui.TableSetColumnIndex(1); ImGui.Text(""); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text(" + Press Y"); ImGui.TableSetColumnIndex(1); ImGui.Text("Open Poses Menu"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text(" + Press B"); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle Depth of Field"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text(" + Press A"); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle SSAO"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text(" + Press X"); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle Alternate Near Clip"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Hold RB"); ImGui.TableSetColumnIndex(1); ImGui.Text(""); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text(" + Press D-Pad Right"); ImGui.TableSetColumnIndex(1); ImGui.Text("Reset Roll"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text(" + Press D-Pad Up"); ImGui.TableSetColumnIndex(1); ImGui.Text("Reset Zoom"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text(" + Press D-Pad Left"); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle Freeze Game"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text(" + Press D-Pad Down"); ImGui.TableSetColumnIndex(1); ImGui.Text("Teleport Player to Camera Position"); ImGui.EndTable(); } ImGui.Separator(); } ImGui.PopID(); #if MOUSE_AND_KEYBOARD_LAYER ImGui.PushID("Mouse/Keyboard"); if (ImGui.CollapsingHeader("Mouse & Keyboard")) { ImGui.PushItemWidth(width * 0.2f); if (ImGui.Checkbox("Enable Mouse", ref mouseEnabled)) { Config.Settings.Binds binds = config.Binds; binds.EnableMouse = mouseEnabled; config.Binds = binds; ConfigManager.SaveConfig(this); } if (ImGui.DragFloat("Mouse Sensitivity", ref mouseSensitivity, 0.001f, 0.0f, 0.0f, "%.4f")) { Config.Settings.Binds binds = config.Binds; binds.MouseSensitivity = mouseSensitivity; config.Binds = binds; ConfigManager.SaveConfig(this); } if (ImGui.Checkbox("Enable Keyboard", ref keyboardEnabled)) { Config.Settings.Binds binds = config.Binds; binds.EnableKeyboard = keyboardEnabled; config.Binds = binds; ConfigManager.SaveConfig(this); } if (ImGui.DragInt("Keyboard Look Sensitivity", ref keyboardLookValue, 20, 0, Int16.MaxValue)) { Config.Settings.Binds binds = config.Binds; binds.KeyboardLookSensitivity = keyboardLookValue; config.Binds = binds; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Value that gets sent as a simulated joystick movement. Range: [0, 32767]."); ImGui.EndTooltip(); } ImGui.PopItemWidth(); if (ImGui.BeginTable("Keyboard Binds", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) { ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Num 0"); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle Free Camera"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Arrow Up/Down/Left/Right"); ImGui.TableSetColumnIndex(1); ImGui.Text("Move Camera"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Num 8/2/4/6"); ImGui.TableSetColumnIndex(1); ImGui.Text("Look"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Num 7/1"); ImGui.TableSetColumnIndex(1); ImGui.Text("Translate Up/Down"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Num 9/3"); ImGui.TableSetColumnIndex(1); ImGui.Text("Roll Camera"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Num *"); ImGui.TableSetColumnIndex(1); ImGui.Text("Reset Roll"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Num -/+"); ImGui.TableSetColumnIndex(1); ImGui.Text("Zoom"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Num ."); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle UI"); ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Num /"); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle Depth of Field"); ImGui.EndTable(); } ImGui.Separator(); } ImGui.PopID(); #endif ImGui.PushID("Viewport"); if (ImGui.CollapsingHeader("Viewport") && vCameraViewportIndex >= 0) { drawViewportInfo(vCameraViewportIndex, width, config, false); ImGui.Separator(); } ImGui.PopID(); ImGui.PushID("Player"); if (ImGui.CollapsingHeader("Player") && player != null) { ImGui.Checkbox("Hide Weapon", ref hideWeapon); nint controlsAddr = MemoryUtil.Read(player.Instance + 0x12608); nint zoneStateAddr = MemoryUtil.Read(0x1451C42B8); ZoneState zoneState = ZoneState.Unknown; if (controlsAddr != 0x0 && zoneStateAddr != 0x0) { ref byte passiveFlag = ref MemoryUtil.GetRef(player.Instance + 0x7626); ref byte passiveFlag2 = ref MemoryUtil.GetRef(MemoryUtil.Read(player.Instance + 0x7D20) + 0x9B8); bool passive = passiveFlag == 0x1 && passiveFlag2 == 0x1; if (ImGui.Checkbox("Passive", ref passive)) { passiveFlag = byteFlag(passive); passiveFlag2 = byteFlag(passive); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Passive: Calm camera and your hunter looks neutral/smiles.\nCombat: Intense camera and your hunter looks angry.\nIf you have Passive set and Combat Controls on, or vice versa, expect glitchy behavior."); ImGui.EndTooltip(); } bool combatControls = MemoryUtil.Read(controlsAddr + 0xB18) == 0x80; zoneState = combatControls ? ZoneState.Combat : ZoneState.Hub; #if QUARANTINED_FEATURES if (ImGui.Checkbox("Combat Controls", ref combatControls)) { passiveFlag = byteFlag(!combatControls); passiveFlag2 = byteFlag(!combatControls); setPlayerController1.Invoke(player.Instance); setPlayerController5.Invoke(controlsAddr); } int zoneStateInt = (int)forceZoneState; Vector2 pos = ImGui.GetCursorPos(); pos.Y += 6; ImGui.SetCursorPos(pos); ImGui.Text($"Force Zone State (Current: {((MemoryUtil.GetRef(zoneStateAddr + 0xD2EA) == 0x1) ? "Hub" : "Combat")})"); if (ImGui.BeginItemTooltip()) { ImGui.Text("This will apply when moving to a different area."); ImGui.EndTooltip(); } ImGui.SameLine(); pos = ImGui.GetCursorPos(); pos.Y -= 6; ImGui.SetCursorPos(pos); ImGui.RadioButton("Off", ref zoneStateInt, 0); ImGui.SameLine(); pos = ImGui.GetCursorPos(); pos.Y -= 6; ImGui.SetCursorPos(pos); ImGui.RadioButton("Hub", ref zoneStateInt, 1); ImGui.SameLine(); pos = ImGui.GetCursorPos(); pos.Y -= 6; ImGui.SetCursorPos(pos); ImGui.RadioButton("Combat", ref zoneStateInt, 2); forceZoneState = (ZoneState)zoneStateInt; if (ImGui.Button("Run Change Zone State")) { zoneStateManualInvoke = true; setZoneState.Invoke(player.Instance, 0x000106C0); // or 0x00010780. } if (ImGui.BeginItemTooltip()) { ImGui.Text("You can use this to apply the value of Force Zone State.\nIf you're in a map and Force Zone State is set to Off or Combat, this will send you back to camp."); ImGui.EndTooltip(); } if (ImGui.Checkbox("Force Passive in Combat Zones", ref forcePassiveInCombatZone)) { if (forcePassiveInCombatZone) { zoneStateForcePassive1.Enable(); zoneStateForcePassive2.Enable(); } else { zoneStateForcePassive1.Disable(); zoneStateForcePassive2.Disable(); } } if (ImGui.Checkbox("Force Combat in Passive Zones", ref forceCombatInPassiveZone)) { if (forceCombatInPassiveZone) { zoneStateForceCombat1.Enable(); zoneStateForceCombat2.Enable(); } else { zoneStateForceCombat1.Disable(); zoneStateForceCombat2.Disable(); } } #endif } if (zoneState != ZoneState.Combat) { ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } if (ImGui.Checkbox("Force Crawl", ref enableCrawl)) { if (enableCrawl) { MemoryUtil.GetRef(psuedoObject2 + 0x70) = player.Position.X + player.Forward.X; MemoryUtil.GetRef(psuedoObject2 + 0x74) = player.Position.Y + player.Forward.Y; MemoryUtil.GetRef(psuedoObject2 + 0x78) = player.Position.Z + player.Forward.Z; Quaternion playerRotation = new Quaternion(player.Forward.X, player.Forward.Y, player.Forward.Z, 0.0f); Quaternion objectRotation = getReverse(playerRotation); MemoryUtil.GetRef(psuedoObject2 + 0x40) = objectRotation.X; MemoryUtil.GetRef(psuedoObject2 + 0x44) = objectRotation.Y; MemoryUtil.GetRef(psuedoObject2 + 0x48) = objectRotation.Z; MemoryUtil.GetRef(psuedoObject2 + 0x4C) = objectRotation.W; MemoryUtil.GetRef(psuedoObject2 + 0x50) = 0.0f; MemoryUtil.GetRef(psuedoObject2 + 0x54) = 1.0f; MemoryUtil.GetRef(psuedoObject2 + 0x58) = 0.0f; MemoryUtil.GetRef(psuedoObject2 + 0x5C) = 0.0f; MemoryUtil.GetRef(psuedoObject2 + 0x60) = playerRotation.X; MemoryUtil.GetRef(psuedoObject2 + 0x64) = playerRotation.Y; MemoryUtil.GetRef(psuedoObject2 + 0x68) = playerRotation.Z; MemoryUtil.GetRef(psuedoObject2 + 0x6C) = playerRotation.W; } } if (zoneState != ZoneState.Combat) { ImGui.PopItemFlag(); ImGui.PopStyleVar(); if (ImGui.BeginItemTooltip()) { ImGui.Text("You have to be out in a map to use this."); ImGui.EndTooltip(); } } else { if (ImGui.BeginItemTooltip()) { ImGui.Text("Simulate crawling under an object in the direction your character was facing when enabled."); ImGui.EndTooltip(); } } if (zoneState != ZoneState.Hub) { ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } if (ImGui.Button("Sit in Hot Springs")) { // Run sit in hot springs action (top of function): // MonsterHunterWorld.exe+17601F0 - mov [rsp+08],rbx MemoryUtil.WriteBytes(player.ActionController.Instance + 0xC0, [0x65, 0x00, 0x00, 0x00]); MemoryUtil.WriteBytes(player.ActionController.Instance + 0xBC, [0x01, 0x00, 0x00, 0x00]); } if (zoneState != ZoneState.Hub) { ImGui.PopItemFlag(); ImGui.PopStyleVar(); if (ImGui.BeginItemTooltip()) { ImGui.Text("You have to be in a hub area to use this."); ImGui.EndTooltip(); } } if (ImGui.Checkbox("Allow Hot Springs Anywhere", ref allowHotSpringsAnywhere)) { if (allowHotSpringsAnywhere) { jmpOverHotSpringsEval.Enable(); } else { jmpOverHotSpringsEval.Disable(); } } if (ImGui.BeginItemTooltip()) { ImGui.Text("Disable check for being about halfway submerged in water to stay sitting."); ImGui.EndTooltip(); } if (ImGui.Checkbox("Disable Hot Springs Steam", ref disableHotSpringsSteam)) { if (disableHotSpringsSteam) { jmpOverHotSpringsSteam.Enable(); } else { jmpOverHotSpringsSteam.Disable(); } } if (ImGui.BeginItemTooltip()) { ImGui.Text("It will take a couple of seconds to fade away."); ImGui.EndTooltip(); } ImGui.PushItemWidth(width * 0.35f); ref float playerOpacity = ref MemoryUtil.GetRef(player.Instance + 0x78E0); if (ImGui.DragFloat("Opacity", ref playerOpacity, 0.01f, 0.0f, Single.MaxValue)) { playerOpacityOverride = playerOpacity; } ImGui.PopItemWidth(); if (ImGui.CollapsingHeader("Wetness")) { nint wetnessAddr = player.Instance + 0x13BD0; ImGui.PushItemWidth(width * 0.3f); float headWetness = MemoryUtil.Read(wetnessAddr); if (ImGui.DragFloat("Head", ref headWetness, 0.005f)) { MemoryUtil.WriteBytes(wetnessAddr, BitConverter.GetBytes(headWetness)); } float bodyWetness = MemoryUtil.Read(wetnessAddr + 0x28); if (ImGui.DragFloat("Body", ref bodyWetness, 0.005f)) { MemoryUtil.WriteBytes(wetnessAddr + 0x28, BitConverter.GetBytes(bodyWetness)); } float waistWetness = MemoryUtil.Read(wetnessAddr + 0x50); if (ImGui.DragFloat("Waist", ref waistWetness, 0.005f)) { MemoryUtil.WriteBytes(wetnessAddr + 0x50, BitConverter.GetBytes(waistWetness)); } float legsWetness = MemoryUtil.Read(wetnessAddr + 0x78); if (ImGui.DragFloat("Legs", ref legsWetness, 0.005f)) { MemoryUtil.WriteBytes(wetnessAddr + 0x78, BitConverter.GetBytes(legsWetness)); } if (ImGui.DragFloat("Whole Body", ref wholeBodyWetness, 0.005f)) { if (applyCharacterWetness) { MemoryUtil.WriteBytes(wetnessAddr, BitConverter.GetBytes(wholeBodyWetness)); MemoryUtil.WriteBytes(wetnessAddr + 0x28, BitConverter.GetBytes(wholeBodyWetness)); MemoryUtil.WriteBytes(wetnessAddr + 0x50, BitConverter.GetBytes(wholeBodyWetness)); MemoryUtil.WriteBytes(wetnessAddr + 0x78, BitConverter.GetBytes(wholeBodyWetness)); } } ImGui.PopItemWidth(); if (ImGui.Checkbox("Override Player Wetness", ref applyCharacterWetness)) { if (applyCharacterWetness) { noopCharacterWetnessUpdate.Enable(); } else { noopCharacterWetnessUpdate.Disable(); } MemoryUtil.WriteBytes(wetnessAddr, BitConverter.GetBytes(wholeBodyWetness)); MemoryUtil.WriteBytes(wetnessAddr + 0x28, BitConverter.GetBytes(wholeBodyWetness)); MemoryUtil.WriteBytes(wetnessAddr + 0x50, BitConverter.GetBytes(wholeBodyWetness)); MemoryUtil.WriteBytes(wetnessAddr + 0x78, BitConverter.GetBytes(wholeBodyWetness)); } } ImGui.DragFloat3("Position", ref player.Position, 0.5f); Vector3 forward; forward.X = player.Forward.X; forward.Y = player.Forward.Y; forward.Z = player.Forward.Z; ImGui.DragFloat3("Forward", ref forward, 0.0f); Vector4 rotation; rotation.X = player.Rotation.X; rotation.Y = player.Rotation.Y; rotation.Z = player.Rotation.Z; rotation.W = player.Rotation.W; if (ImGui.SliderFloat4("Rotation", ref rotation, -1.0f, 1.0f)) { player.Rotation.X = rotation.X; player.Rotation.Y = rotation.Y; player.Rotation.Z = rotation.Z; player.Rotation.W = rotation.W; } if (ImGui.Button("Reset")) { player.Rotation.X = 0.0f; player.Rotation.Z = 0.0f; } if (ImGui.Checkbox("Disable Collision", ref disableCollision)) { if (disableCollision) { disableCollisionEnable(); } else { if (disableExtraGravity) { disableExtraGravity = false; disableExtraGravityDisable(); } if (disableGravity) { disableGravity = false; disableGravityDisable(); } if (disableExtraCollision) { disableExtraCollision = false; disableExtraCollisionDisable(); } disableCollisionDisable(); } } if (!disableCollision) { ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } if (ImGui.Checkbox("Disable Another Y Collision", ref disableExtraCollision)) { if (disableExtraCollision) { disableExtraCollisionEnable(); } else { if (disableExtraGravity) { disableExtraGravity = false; disableExtraGravityDisable(); } if (disableGravity) { disableGravity = false; disableGravityDisable(); } disableExtraCollisionDisable(); } } if (ImGui.BeginItemTooltip()) { ImGui.Text("This will make your legs goofy, but is needed to get on top of some things."); ImGui.EndTooltip(); } if (!disableCollision) { ImGui.PopItemFlag(); ImGui.PopStyleVar(); } if (!disableExtraCollision) { ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } if (ImGui.Checkbox("Disable Y Gravity", ref disableGravity)) { if (disableGravity) { disableGravityEnable(); } else { if (disableExtraGravity) { disableExtraGravity = false; disableExtraGravityDisable(); } disableGravityDisable(); } } if (ImGui.BeginItemTooltip()) { ImGui.Text("Avoid falling when going too high (Y axis)."); ImGui.EndTooltip(); } if (!disableExtraCollision) { ImGui.PopItemFlag(); ImGui.PopStyleVar(); } if (!disableGravity) { ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } if (ImGui.Checkbox("Disable More Gravity", ref disableExtraGravity)) { if (disableExtraGravity) { disableExtraGravityEnable(); } else { disableExtraGravityDisable(); } } if (ImGui.BeginItemTooltip()) { ImGui.Text("This can stop you from falling when going out of bounds and/or rotating."); ImGui.EndTooltip(); } if (!disableGravity) { ImGui.PopItemFlag(); ImGui.PopStyleVar(); } ImGui.Separator(); } ImGui.PopID(); ImGui.PushID("World"); if (ImGui.CollapsingHeader("World")) { nint timeAddr = MemoryUtil.Read(sMain.Instance + 0xAF878); if (timeAddr != 0x0) { float gameTime = MemoryUtil.Read(timeAddr + 0x38); if (ImGui.SliderFloat("Time of Day", ref gameTime, 0.0f, 24.0f)) { MemoryUtil.WriteBytes(timeAddr + 0x38, BitConverter.GetBytes(gameTime)); } } ImGui.PushItemWidth(width * 0.125f); ref float gameSpeed = ref MemoryUtil.GetRef(sMain.Instance + 0xA4); if (ImGui.DragFloat("Game Speed", ref gameSpeed, 0.005f, 0.0f, Single.MaxValue)) { if (gameSpeed == 1.0f) { decoupleDtFromGameTime = false; } } ImGui.SameLine(); if (ImGui.Button("Toggle Freeze Game")) { toggleFreezeGame(); } ImGui.SameLine(); if (ImGui.Button("Advance Frame")) { advanceFrame++; } ImGui.PopItemWidth(); ImGui.Checkbox("Decouple Camera Speed from Game Speed", ref decoupleDtFromGameTime); if (ImGui.BeginItemTooltip()) { ImGui.Text("Enable this to move in free camera at a normal speed when game speed is not 1.0."); ImGui.EndTooltip(); } if (ImGui.Checkbox("Override View Mode", ref overrideViewMode)) { config.OverrideViewMode = overrideViewMode; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Replace in-game View Mode with the free camera from this mod."); ImGui.EndTooltip(); } if (ImGui.Checkbox("Underwater Camera", ref enableUnderwaterCamera)) { if (enableUnderwaterCamera) { underwaterCameraEnable(); } else { underwaterCameraDisable(); } } if (ImGui.BeginItemTooltip()) { ImGui.Text("Enable the screen filter from diving but whenever your camera goes underwater.\nWARNING: This is experimental, unfinished and known to crash in at least The Rotten Vale.\nIf you want to see the effect you can try it in the Seliana Gathering Hub, the Ancient Forest or your Private Suite."); ImGui.EndTooltip(); } ImGui.Separator(); } ImGui.PopID(); ImGui.PushID("Graphics"); if (ImGui.CollapsingHeader("Graphical Tweaks")) { if (ImGui.Checkbox("3x Shadow Resolution (Requires Reload)", ref tripleShadowRes)) { if (tripleShadowRes) { tripleShadowResEnable(); } else { tripleShadowResDisable(); } Config.GraphicalTweaks graphics = config.Graphics; graphics.TripleShadowResolution = tripleShadowRes; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("In-Game Settings:\n - High: 1.0 -> 3.0\n - Mid: 0.7 -> 2.1\n - Low: 0.5 -> 1.5\nReload shadows by toggling Shadow Quality in Options -> Display -> Advanced Graphics Settings."); ImGui.EndTooltip(); } ImGui.PushItemWidth(width * 0.145f); if (ImGui.Checkbox("##Apply Larger Shadow Range", ref applyShadowBias)) { Config.GraphicalTweaks graphics = config.Graphics; graphics.ApplyShadowRange = applyShadowBias; config.Graphics = graphics; ConfigManager.SaveConfig(this); } ImGui.SameLine(); if (ImGui.InputFloat("Shadow Range", ref shadowBiasOffset, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue)) { Config.GraphicalTweaks graphics = config.Graphics; graphics.ShadowRangeOffset = shadowBiasOffset; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("This will inversely reduce the detail of shadows closer to the camera (like the player shadow), so it's a trade-off.\nValue is an offset. Recommended: 0.5."); ImGui.EndTooltip(); } ImGui.SameLine(); if (ImGui.Checkbox("##Apply Radius", ref applyShadowRadius)) { Config.GraphicalTweaks graphics = config.Graphics; graphics.ApplyShadowRadius = applyShadowRadius; config.Graphics = graphics; ConfigManager.SaveConfig(this); } ImGui.SameLine(); if (ImGui.InputFloat("Shadow Radius", ref shadowRadiusOffset, 0.0f, 0.0f, "%.5f", ImGuiInputTextFlags.EnterReturnsTrue)) { Config.GraphicalTweaks graphics = config.Graphics; graphics.ShadowRadiusOffset = shadowRadiusOffset; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Size of a shadows border (to be softened if HQ Mode is enabled).\nValue is an offset. Recommended: -0.0001 (if Shadow Range = 0.5)."); ImGui.EndTooltip(); } ImGui.PopItemWidth(); /* if (ImGui.Checkbox("Higher Shadow Detail in Hoarfrost Reach/Seliana Gathering Hub", ref lowShadowDetailOverride)) { Config.GraphicalTweaks graphics = config.Graphics; graphics.HigherShadowDetailInHoarfrost = lowShadowDetailOverride; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Disable reduced detail/range shadows in Hoarfrost Reach and Seliana Gathering Hub.\nAlso doubles the Shadow Range offset in those areas."); ImGui.EndTooltip(); } */ if (ImGui.Checkbox("Enable \"HQ Mode\"", ref enableHQMode)) { ssaoAdjustments = enableHQMode; setSSAOAdjustements(ssaoAdjustments, ssaoB); ssrAdjustments = enableHQMode; setSSRAdjustements(ssrAdjustments); setHQMode(enableHQMode); Config.GraphicalTweaks graphics = config.Graphics; graphics.EnableHQMode = enableHQMode; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Enable the game's built-in \"HQ Mode\" and associated tweaks to not tank performance.\nBy default, HQ Mode jacks up various rendering parameters and enables HQ Shadows.\nSome of the values are put too high to work for general gameplay.\nThis tweak adjusts the following parameters:\n SSAO Max Sample Num HQ: 64 -> 16\n SSLR Accurate Threshold HQ: 0.5 -> 0.2\nAs well as SSAO Dispersion: 10.0 -> 1.75 to mitigate a grid artifact in the SSAO rendering."); ImGui.EndTooltip(); } if (ImGui.Checkbox("Volume Rendering Full Resolution Blur Pass (Requires Area Change)", ref disableVolumeDownsample)) { if (disableVolumeDownsample) { volumeSars1.Enable(); volumeSars2.Enable(); volumeSars3.Enable(); volumeSars4.Enable(); volumeSars5.Enable(); volumeSars6.Enable(); volumeSars7.Enable(); volumeSars8.Enable(); volumeSars9.Enable(); } else { volumeSars1.Disable(); volumeSars2.Disable(); volumeSars3.Disable(); volumeSars4.Disable(); volumeSars5.Disable(); volumeSars6.Disable(); volumeSars7.Disable(); volumeSars8.Disable(); volumeSars9.Disable(); } Config.GraphicalTweaks graphics = config.Graphics; graphics.FullResolutionVolumeBlur = disableVolumeDownsample; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("This can get rid of excessive aliasing when an object is in front of a volumetric effect.\nYou have to move to a different area one time for this to apply. It will remain applied after that."); ImGui.EndTooltip(); } if (ImGui.Checkbox("Higher Than \"Highest\" Volume Rendering Quality", ref higherVolumeQuality)) { if (higherVolumeQuality) { value2ForVolumeQuality.Enable(); } else { value2ForVolumeQuality.Disable(); } Config.GraphicalTweaks graphics = config.Graphics; graphics.HigherThanHighestVolumeRendering = higherVolumeQuality; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("*Extremely Resource Intensive* Only noticeable effect is likely in areas that had visible breakup with Volume Rendering Quality: Highest.\nThis takes mostly the same path as Highest, so expect the same visual artifacts."); ImGui.EndTooltip(); } if (ImGui.Checkbox("Disable Player/Palico/NPC LOD Limit in Gameplay", ref disableLODLimits)) { if (disableLODLimits) { disableLODLimitsEnable(); } else { disableLODLimitsDisable(); } Config.GraphicalTweaks graphics = config.Graphics; graphics.DisableLODLimits = disableLODLimits; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("This will make the default (gameplay) LOD limits equivalent to View Mode. Disabling the limit on:\n - Player Models & Shadows\n - Palico Models & Shadows\n - NPC Models & Shadows\n - Simple NPC Models & Shadows\nAlso equivalent to the settings applied in your room with the addition of disabled Simple NPC limits."); ImGui.EndTooltip(); } ImGui.PushItemWidth(width * 0.1f); ImGui.InputFloat("##Foliage LOD Bias", ref foliageLODBias, 0.0f, 0.0f, "%.2f"); if (ImGui.BeginItemTooltip()) { ImGui.Text("In-Game Settings:\n - High: 3.0\n - Mid: 1.0\n - Low: 0.9\n - Variable: -1.0\nHigher value = Farther distance before plants switch to a lower LOD."); ImGui.EndTooltip(); } ImGui.SameLine(); ImGui.InputFloat("##Foliage LOD Factor", ref foliageLODFactor, 0.0f, 0.0f, "%.2f"); if (ImGui.BeginItemTooltip()) { ImGui.Text("Controls the distance at which the game decides to no longer render some plants.\nCan be effectively overridden by a high first value.\nDefault: 1.0, Best Quality: 0.0."); ImGui.EndTooltip(); } ImGui.SameLine(); ImGui.Text("Foliage LOD Bias"); ImGui.InputFloat("##Terrain/Object LOD Bias", ref terrainLODBias, 0.0f, 0.0f, "%.2f"); if (ImGui.BeginItemTooltip()) { ImGui.Text("In-Game Settings:\n - High: 3.0\n - Mid: 1.0\n - Low: 0.9\n - Variable: -1.0\nHigher value = Farther distance before objects switch to a lower LOD."); ImGui.EndTooltip(); } ImGui.SameLine(); ImGui.InputFloat("##Terrain/Object LOD Factor", ref terrainLODFactor, 0.0f, 0.0f, "%.2f"); if (ImGui.BeginItemTooltip()) { ImGui.Text("Controls the distance at which the game decides to no longer render some objects.\nCan be effectively overridden by a high first value.\nDefault: 1.0, Best Quality: 0.0."); ImGui.EndTooltip(); } ImGui.SameLine(); ImGui.Text("Terrain/Object LOD Bias"); ImGui.InputFloat("Snow LOD Bias", ref snowField4GlobalLODParam, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags.EnterReturnsTrue); ImGui.PopItemWidth(); bool lodsSet = areLODFactorsSet(); bool disableLODButton = lodsSet && areLODFactorsDefault(); if (disableLODButton) { ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); lodsSet = false; } if (ImGui.Checkbox("Apply LOD Biases", ref lodsSet)) { setLODFactors(lodsSet); applyLODFactors = lodsSet && !areLODFactorsDefault(); Config.GraphicalTweaks graphics = config.Graphics; if (lodsSet) { graphics.FoliageLODBias = foliageLODBias; graphics.TerrainLODBias = terrainLODBias; graphics.FoliageLODFactor = foliageLODFactor; graphics.TerrainLODFactor = terrainLODFactor; graphics.SnowLODBias = snowField4GlobalLODParam; } graphics.ApplyLODFactors = applyLODFactors; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (disableLODButton) { ImGui.PopItemFlag(); ImGui.PopStyleVar(); } if (ImGui.Checkbox("Larger Foliage Sway Range", ref largerFoliageSwayRange)) { if (largerFoliageSwayRange) { addressHigherValueForFoliageSway.Enable(); } else { addressHigherValueForFoliageSway.Disable(); } Config.GraphicalTweaks graphics = config.Graphics; graphics.LargerFoliageSwayRange = largerFoliageSwayRange; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Increase the distance at which Foliage Sway is still applied to lower priority plants."); ImGui.EndTooltip(); } if (ImGui.Checkbox("Disable Reduced Rate Animations", ref disableReducedRateAnimations)) { if (disableReducedRateAnimations) { zeroFrameSkip.Enable(); } else { zeroFrameSkip.Disable(); } Config.GraphicalTweaks graphics = config.Graphics; graphics.DisableReducedRateAnimations = disableReducedRateAnimations; config.Graphics = graphics; ConfigManager.SaveConfig(this); } if (ImGui.BeginItemTooltip()) { ImGui.Text("Ignore the frame skip set on an animal's animation when they get farther from the camera."); ImGui.EndTooltip(); } if (ImGui.CollapsingHeader("Depth of Field Parameters")) { ImGui.Checkbox("Enabled", ref dofParams.enabled); ImGui.Checkbox("New Version", ref dofParams.newVersion); ImGui.DragFloat("FNumber", ref dofParams.fNumber, 0.001f, 0.0f, 0.0f, "%.5f"); ImGui.DragFloat("Sensor Size", ref dofParams.sensorSize, 0.001f, 0.0f, 0.0f, "%.5f"); ImGui.DragFloat("Focus Distance", ref dofParams.focusDistance, 0.2f); ImGui.DragFloat("Near Coef", ref dofParams.nearCoef, 0.001f, 0.0f, 0.0f, "%.5f"); ImGui.DragFloat("Far Coef", ref dofParams.farCoef, 0.001f, 0.0f, 0.0f, "%.5f"); ImGui.Checkbox("Near Enabled", ref dofParams.nearEnable); ImGui.Checkbox("Far Enabled", ref dofParams.farEnable); ImGui.Checkbox("Debug Draw", ref dofParams.debugDraw); if (!dofParams.newVersion) { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } ImGui.Text("New Version Parameters:"); ImGui.DragFloat("Radius", ref dofParams.radius, 0.001f, 0.0f, 0.0f, "%.6f"); ImGui.DragFloat("Depth Scale Foreground", ref dofParams.depthScaleForeground, 0.0001f, 0.0f, 0.0f, "%.6f"); ImGui.DragFloat("Aspect", ref dofParams.aspect, 0.001f, 0.0f, 0.0f, "%.6f"); if (!dofParams.newVersion) { ImGui.PopStyleVar(); } if (ImGui.Button("Reset Per-frame Parameters")) { fillOutDofParams = true; } } if (ImGui.CollapsingHeader("Vignetting Parameters")) { ImGui.Checkbox("Apply Adjustments", ref applyVignettingParams); ImGui.Checkbox("Enabled", ref dofParams.vignettingEnabled); ImGui.Checkbox("Ellipse", ref dofParams.vignettingEllipse); ImGui.DragFloat("Ellipticity", ref dofParams.vignettingEllipticity, 0.05f); ImGui.DragFloat("Offset", ref dofParams.vignettingOffset, 0.05f); ImGui.DragFloat("Power", ref dofParams.vignettingPow, 0.05f); ImGui.InputInt("Color", ref dofParams.vignettingColor, 0, 0, ImGuiInputTextFlags.CharsHexadecimal); if (ImGui.Button("Reset Per-frame Parameters")) { fillOutVignettingParams = true; } } if (ImGui.CollapsingHeader("Shadow Distance Parameters")) { ImGui.PushItemWidth(width * 0.2f); ImGui.Text($"sUmbra: {sUmbra.Instance:x}"); nint obj = MemoryUtil.Read(sUmbra.Instance + 0x00149740); ImGui.Text($"Object Address: {obj:x}"); ImGui.Checkbox("Apply Adjustments", ref applyShadowAdjust); ImGui.InputFloat("Shadow Backforward Distance", ref shadowBackforwardDistance); if (ImGui.BeginItemTooltip()) { ImGui.Text("Try increasing this if it looks like objects are being culled out of the shadow map at certain angles.\nThese values probably neeed to be entirely retuned per-area after increasing shadow range."); ImGui.EndTooltip(); } ImGui.Text($"Original: {lastShadowBackforwardDistance}"); ImGui.InputFloat("Shadow Distance", ref shadowDistance); ImGui.Text($"Original: {lastShadowDistance}"); ImGui.InputFloat("Shadow Distribution", ref shadowDistribution); ImGui.Text($"Original: {lastShadowDistribution}"); /* ImGui.InputFloat("Broad Area Shadow Range", ref broadAreaShadowRange); ImGui.Text($"Original: {lastBroadAreaShadowRange}"); ImGui.InputFloat("Shadow FOV", ref shadowFov); ImGui.Text($"Original: {lastShadowFov}"); */ ImGui.PopItemWidth(); } if (ImGui.CollapsingHeader("Lighting Parameters")) { ImGui.Text($"Address: {lightingObject:x}"); if (lightingObject != 0x0) { ImGui.PushItemWidth(width * 0.2f); drawRenderParameter("Tone Map Type", lightingObject, 0x16C, false, 1.0f); drawRenderParameter("Compute Luminance", lightingObject, 0x170); //drawRenderParameter("Luminance Version", lightingObject, 0x168); drawRenderParameter("Shoulder Strength", lightingObject, 0x174); drawRenderParameter("Linear Strength", lightingObject, 0x178); drawRenderParameter("Linear Angle", lightingObject, 0x17C); drawRenderParameter("Toe Strength", lightingObject, 0x180); drawRenderParameter("Toe Num", lightingObject, 0x184); drawRenderParameter("Toe Denum", lightingObject, 0x188); drawRenderParameter("White Point", lightingObject, 0x18C); //drawRenderParameter("LUT Blend", lightingObject, 0x1C8); //drawRenderParameter("Vfx LUT Blend", lightingObject, 0x1D0); drawRenderParameter("Enable Color Grading", lightingObject, 0x1D8); drawRenderParameter("Input Color Linear to PQ", lightingObject, 0x1A1); drawRenderParameter("Output Color PQ to Linear", lightingObject, 0x1A0); drawRenderParameter("Dispersion", lightingObject, 0x19C); drawRenderParameter("Edge Sharpness", lightingObject, 0x198); drawRenderParameter("Downsample Volume", lightingObject, 0x210); ImGui.PopItemWidth(); } } if (ImGui.CollapsingHeader("FXAA Parameters")) { ImGui.Text($"Address: {fxaaObject:x}"); if (fxaaObject != 0x0) { ImGui.PushItemWidth(width * 0.2f); drawRenderParameter("FXAA Subpix", fxaaObject, 0x178, true); drawRenderParameter("FXAA Edge Threshold", fxaaObject, 0x17C, true); drawRenderParameter("FXAA Edge Threshold Min", fxaaObject, 0x180, true); ImGui.PopItemWidth(); } } if (ImGui.CollapsingHeader("Misc Parameters")) { nint baseAddr = MemoryUtil.Read(0x1451C4368); ImGui.Text($"Address: {baseAddr:x}"); ImGui.PushItemWidth(width * 0.2f); drawRenderParameter("HQ Mode", baseAddr, 0xE9A3); drawRenderParameter("Primary Shadow Sample Num", baseAddr, 0xE5C4); drawRenderParameter("Primary Shadow Sample Num HQ", baseAddr, 0xE5CC); drawRenderParameter("Primary Shadow HQ", baseAddr, 0xE5C0); if (ImGui.BeginItemTooltip()) { ImGui.Text("This seems to refer to softening the edges of shadows."); ImGui.EndTooltip(); } drawRenderParameter("Primary Shadow HQ HQ", baseAddr, 0xE5C2); drawRenderParameter("LOD Length Bias HQ", baseAddr, 0x1FC); drawRenderParameter("LOD Pixel Size Bias HQ", baseAddr, 0x1FC); inputSSAOParameters(null, baseAddr); drawRenderParameter("SSLR Loop Count", baseAddr, 0xE628); drawRenderParameter("SSLR Loop Count Factor For CBR", baseAddr, 0xE62C); drawRenderParameter("SSLR Eliminate Depth", baseAddr, 0xE630); drawRenderParameter("SSLR Accurate Threshold", baseAddr, 0xE644); drawRenderParameter("SSLR Accurate Threshold HQ", baseAddr, 0xE64C); drawRenderParameter("SSLR Dither Radius", baseAddr, 0xE634); drawRenderParameter("SSLR Importance Bias", baseAddr, 0xE638); drawRenderParameter("SSLR Mip Scale", baseAddr, 0xE63C); drawRenderParameter("SSLR Mip Bias", baseAddr, 0xE640); drawRenderParameter("SSLR Dither Resolve", baseAddr, 0xB43F); drawRenderParameter("SSLR Edge Atten Rate", baseAddr, 0xB428); drawRenderParameter("SSLR Mip 0 Count Threshold", baseAddr, 0xB438); drawRenderParameter("SSLR Depth Eliminate Rate", baseAddr, 0xB42C); drawRenderParameter("SSLR Use Mipmap", baseAddr, 0xE650); drawRenderParameter("SSLR GBuffer Jitter", baseAddr, 0xB440); drawRenderParameter("Contact Shadows Enabled", baseAddr, 0xB4EC); drawRenderParameter("Force Disable Contact Shadows", baseAddr, 0xB4ED); drawRenderParameter("Facial Contact Shadows Enabled", baseAddr, 0xB4EE); drawRenderParameter("Contact Shadows Enable Noise", baseAddr, 0xB500); drawRenderParameter("Facial Contact Shadows Enable Noise", baseAddr, 0xB501); drawRenderParameter("Contact Shadow Intensity", baseAddr, 0xB4F0); drawRenderParameter("Contact Shadow Length", baseAddr, 0xB4F4); drawRenderParameter("Contact Shadow Accept Maximum Length", baseAddr, 0xB4F8); drawRenderParameter("Contact Shadow Accept Minimum Length", baseAddr, 0xB4FC); /* drawRenderParameter("Capsule AO Enabled", baseAddr, 0xB502); drawRenderParameter("Force Disable Capsule AO", baseAddr, 0xB503); drawRenderParameter("Checkerboard Alpha Unroll Near", baseAddr, 0xE964); drawRenderParameter("Checkerboard Alpha Unroll Far", baseAddr, 0xE968); drawRenderParameter("Checkerboard History Blend Rate", baseAddr, 0xE96C); drawRenderParameter("Checkerboard Sanitize Color", baseAddr, 0xE972); drawRenderParameter("Checkerboard Blend Dither", baseAddr, 0xE973); drawRenderParameter("Checkerboard BBox Strength", baseAddr, 0xE974); drawRenderParameter("Checkerboard Dither Passthru Weight", baseAddr, 0xE978); drawRenderParameter("Checkerboard Dither Filtered Weight", baseAddr, 0xE97C); drawRenderParameter("Checkerboard Continous History Reset", baseAddr, 0xE971); */ ImGui.PopItemWidth(); } ImGui.Separator(); } ImGui.PopID(); ImGui.PushID("Debug"); if (ImGui.CollapsingHeader("DEBUG")) { if (vCamera != null || pCamera != null) { ImGui.Text("Camera:"); if (vCamera != null) { ImGui.Text($"Visible Camera: {vCamera.Instance:x}"); ImGui.Text($"freeCameraFallback: {freeCameraFallback}"); //ImGui.Text($"viewModeObject: {psuedoViewModeObject:x}"); } if (pCamera != null) { ImGui.Text($"Player Camera: {pCamera.Instance:x}"); ImGui.Text($"Applying Offset: {applyPerspective}"); ImGui.Text($"previousCameraAnimState: {previousCameraAnimState}"); ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); ImGui.DragFloat3("Offset", ref cameraOffset); ImGui.PopItemFlag(); } ImGui.Separator(); } ImGui.PushID("Viewports"); ImGui.Text("Viewports:"); for (int i = 0; i < 8; i++) { ImGui.PushID($"Viewport{i}"); if (ImGui.CollapsingHeader($"Viewport #{i} ({((i == vCameraViewportIndex) ? "visible" : "inactive")})")) { drawViewportInfo(i, width, config, true); } ImGui.PopID(); } ImGui.PopID(); ImGui.Separator(); if (player != null) { ImGui.PushID("Player"); ImGui.Text("Player:"); ImGui.Text($"Address: {player.Instance:x}"); drawAnimationInfo(player); bool move = player.Move; if (ImGui.Checkbox("Move", ref move)) { player.Move = move; } ImGui.SameLine(); bool fix = player.Fix; if (ImGui.Checkbox("Fix", ref fix)) { player.Fix = fix; } ImGui.PopID(); ImGui.Separator(); ImGui.PushID("Palico"); ImGui.Text("Palico/Otomo"); ImGui.Text($"Address: {sOtomo.Instance:x}"); ImGui.PopID(); ImGui.Separator(); } Monster[] monsters = Monster.GetAllMonsters(); if (monsters.Length != 0 && ImGui.CollapsingHeader("Monsters")) { for (int i = monsters.Length - 1; i >= 0; i--) { Monster monster = monsters[i]; ImGui.PushID(monster.Instance); ImGui.Text($"{monster.Name}:"); ImGui.Text($" Address: {monster.Instance:x}"); ImGui.DragFloat3("Position", ref monster.Position, 0.5f); drawAnimationInfo(monster); ImGui.PopID(); ImGui.Separator(); } } ImGui.Text("Graphics:"); // Locations taken from MHW-DTI-Dumps/wip_dump_15_20_00.h. ImGui.InputFloat("Simulation Fps", ref MemoryUtil.GetRef(sMain.Instance + 0x58)); if (ImGui.BeginItemTooltip()) { ImGui.Text("This does not apply to jiggle physics."); ImGui.EndTooltip(); } ImGui.InputFloat("Max Fps", ref MemoryUtil.GetRef(sMain.Instance + 0x5C)); ImGui.InputFloat("Fps", ref MemoryUtil.GetRef(sMain.Instance + 0x68)); ImGui.Text($"Delta Time: {MemoryUtil.Read(sMain.Instance + 0x94)}"); ImGui.Text($"prevFoliageLODBias: {prevFoliageLODBias}"); ImGui.Text($"prevTerrainLODBias: {prevTerrainLODBias}"); ImGui.Text($"shadowCascadeValue: {lastShadowCascadeValue}"); ImGui.Text($"shadowBias: {lastShadowBias}"); ImGui.Text($"shadowRadius: {lastShadowRadius}"); ImGui.Separator(); #if MOUSE_AND_KEYBOARD_LAYER ImGui.PushID("Mouse/Keyboard"); ImGui.Text("Mouse:"); ImGui.Text($"Address: {sMhMouse.Instance:x}"); ImGui.Text("Keyboard:"); ImGui.Text($"Address: {sMhKeyboard.Instance:x}"); ImGui.PopID(); #endif ImGui.PushID("Pad"); ImGui.Text("Pad:"); ImGui.Text($"Address: {controllerAddr():x}"); int Rx = MemoryUtil.Read(controllerAddr() + 0x1B0); int Ry = MemoryUtil.Read(controllerAddr() + 0x1B4); int Lx = MemoryUtil.Read(controllerAddr() + 0x1B8); int Ly = MemoryUtil.Read(controllerAddr() + 0x1BC); byte PadRz = MemoryUtil.Read(controllerAddr() + 0x1C0); byte PadLz = MemoryUtil.Read(controllerAddr() + 0x1C1); ImGui.Text("Left Stick:"); ImGui.Text($" X: {Lx} ({PadLx})"); ImGui.Text($" Y: {Ly} ({PadLy})"); ImGui.Text($" LT: {PadLz}"); ImGui.Text("Right Stick:"); ImGui.Text($" X: {Rx} ({PadRx})"); ImGui.Text($" Y: {Ry} ({PadRy})"); ImGui.Text($" RT: {PadRz}"); ImGui.PushItemWidth(width * 0.125f); ImGui.DragFloat("+Right", ref plusRight, 0.01f); ImGui.SameLine(); ImGui.DragFloat("+Forward", ref plusForward, 0.01f); ImGui.SameLine(); if (ImGui.Button("Reset")) { plusRight = 0.0f; plusForward = 0.0f; } ImGui.SameLine(); if (ImGui.Button("Flip")) { if (plusRight != 0.0f) { plusRight = -plusRight; } if (plusForward != 0.0f) { plusForward = -plusForward; } } ImGui.PopItemWidth(); ImGui.PopID(); ImGui.Separator(); ImGui.PushID("Orbit"); ImGui.Text("Orbital Camera:"); ImGui.PushItemWidth(width * 0.15f); ImGui.DragFloat("Distance", ref orbitDistance, 1.0f); ImGui.SameLine(); ImGui.DragFloat("Target Y", ref orbitY, 1.0f); ImGui.DragFloat("Movement Rotation", ref orbitMovementRotation, 1.0f); ImGui.PopItemWidth(); ImGui.PopID(); ImGui.Separator(); } ImGui.PopID(); ImGui.PushID("Credits"); if (ImGui.CollapsingHeader("Credits")) { ImGui.TextWrapped("Fexty/SharpPluginLoader Authors: Framework for this mod and reference for various memory locations."); ImGui.TextWrapped("Otis_Inf: Initial LOD and object fading adjustment locations. Time of day and game speed."); ImGui.TextWrapped("Andoryuuta: MHW-ClassPropDump/MHW-DTI-Dumps."); ImGui.TextWrapped("MonsterHunterWorldModding/wiki Authors."); } ImGui.PopID(); } } }