diff options
| author | 2025-10-07 22:52:31 -0400 | |
|---|---|---|
| committer | 2025-10-07 22:52:31 -0400 | |
| commit | 353023e77af45f1f1a719d76b6a03f6343d99737 (patch) | |
| tree | c94fe9341efab1445921350148d294f129817bea | |
| parent | e46ee00f56cf6c1f67e3a663f6820ddc045a1b4b (diff) | |
| download | NewCamera-353023e77af45f1f1a719d76b6a03f6343d99737.tar.gz NewCamera-353023e77af45f1f1a719d76b6a03f6343d99737.tar.bz2 NewCamera-353023e77af45f1f1a719d76b6a03f6343d99737.zip | |
Big update, lots of fixes
Signed-off-by: Andrew Opalach <andrew@akon.city>
| -rwxr-xr-x | Config.cs | 69 | ||||
| -rwxr-xr-x | Plugin.cs | 1267 |
2 files changed, 831 insertions, 505 deletions
@@ -5,21 +5,14 @@ namespace MHWNewCamera {
internal class Config : IConfig
{
- public struct Binds
- {
- public Binds()
- {
- }
- }
-
public struct Settings
{
public const float DEFAULT_SPEED = 3.00f;
public const float DEFAULT_ZOOM_SPEED = 1.0f;
public const float DEFAULT_SPEED_MODIFIER = 0.25f;
public const float DEFAULT_SENSITIVITY = 1.95f;
+ public const double DEFAULT_PITCH_LIMIT = -1.0;
public const int DEFAULT_DEADZONE = 4750;
- public const double DEFAULT_PITCH_LIMIT = 88.25;
public Settings()
{
@@ -27,33 +20,85 @@ namespace MHWNewCamera CameraZoomSpeed = DEFAULT_ZOOM_SPEED;
CameraSpeedModifier = DEFAULT_SPEED_MODIFIER;
CameraSensitivity = DEFAULT_SENSITIVITY;
- StickDeadzone = DEFAULT_DEADZONE;
CameraPitchLimit = DEFAULT_PITCH_LIMIT;
+ StickDeadzone = DEFAULT_DEADZONE;
}
public float CameraSpeed { get; set; }
public float CameraZoomSpeed { get; set; }
public float CameraSpeedModifier { get; set; }
public float CameraSensitivity { get; set; }
- public int StickDeadzone { get; set; }
public double CameraPitchLimit { get; set; }
+ public int StickDeadzone { get; set; }
}
public struct Preset
{
public double FOV { get; set; }
public float Forward { get; set; }
- public float Left { get; set; }
+ public float Right { get; set; }
public float Up { get; set; }
public double Roll { get; set; }
}
+ public struct SavedPosition
+ {
+ public float PosX { get; set; }
+ public float PosY { get; set; }
+ public float PosZ { get; set; }
+ public float TargetX { get; set; }
+ public float TargetY { get; set; }
+ public float TargetZ { get; set; }
+ public double Roll { get; set; }
+ }
+
public String Name => "MHWNewCamera";
- public String Version => "1.1";
+ public String Version => "1.2";
+
+ private static Dictionary<string, Button> buttonMap = new Dictionary<string, Button>
+ {
+ { "r1", Button.R1 }, { "rb", Button.R1 },
+ { "r2", Button.R2 }, { "rt", Button.R2 },
+ { "r3", Button.R3 }, { "rstick", Button.R3 },
+ { "l1", Button.L1 }, { "lb", Button.L1 },
+ { "l2", Button.L2 }, { "lt", Button.L2 },
+ { "l3", Button.L3 }, { "lstick", Button.L3 },
+ { "a", Button.Cross }, { "cross", Button.Cross },
+ { "b", Button.Circle }, { "circle", Button.Circle },
+ { "x", Button.Square }, { "square", Button.Square },
+ { "y", Button.Triangle }, { "triangle", Button.Triangle },
+ { "start", Button.Options }, { "options", Button.Options },
+ { "select", Button.Share }, { "share", Button.Share },
+ { "up", Button.Up },
+ { "down", Button.Down },
+ { "left", Button.Left },
+ { "right", Button.Right }
+ };
+
+ public static Button[]? ParseCombo(String comboString)
+ {
+ string[] buttonStrings = comboString.Split(",");
+ if (buttonStrings.Length == 2)
+ {
+ string b1 = buttonStrings[0].ToLower();
+ string b2 = buttonStrings[1].ToLower();
+ if (buttonMap.ContainsKey(b1) && buttonMap.ContainsKey(b2))
+ {
+ return [ buttonMap[b1], buttonMap[b2] ];
+ }
+ }
+ return null;
+ }
+
+ public bool DisableMod { get; set; } = false;
+
+ public bool EnableCombo { get; set; } = true;
+ public String FreeCameraCombo { get; set; } = "RStick,LT";
public Settings CameraSettings { get; set; } = new Settings();
public bool PerspectiveCameraEnabled { get; set; } = false;
public Dictionary<String, Preset> Presets { get; set; } = new Dictionary<String, Preset>();
public String Selected { get; set; } = "";
+ public Dictionary<String, SavedPosition> Positions { get; set; } = new Dictionary<String, SavedPosition>();
}
}
@@ -1,4 +1,4 @@ -#define ADDR_ASSERTS
+//#define ADDR_ASSERTS
using ImGuiNET;
using System.Numerics;
@@ -15,24 +15,48 @@ using System.Diagnostics; #endif
// @TODO:
-// - UI button to disable fragile workarounds.
-// - Manully set freecam viewport index.
-// - Save direct camera offsets as preset.
+// - Trigger blue camera on minimap.
// - Ability to disable more inputs in freecam.
-/*
-PadDown = 0x198, PadOld = 0x19C, PadTrg = 0x1A0, PadRel = 0x1A4, PadChg = 0x1A8
-uint PadDown = MemoryUtil.Read<uint>(sMhSteamController.Instance + 0x198);
-MemoryUtil.WriteBytes(sMhSteamController.Instance + 0x198, BitConverter.GetBytes(PadRel));
-*/
-// Known Issues:
-// - Leaving dialoge when vp.Camera.Up is slightly off will not apply camera offsets when it should.
-// - Test Case: Go up to the handler with the camera left of the player. Talk to her and click Post a New Quest.
-// Then after the open book animation, leave the dialoge and the camera should jump.
-// - Getting up from cart doesn't apply offsets when it should.
-// - Greatly increasing FOV to mitigate culling when camera is rolled causes issues.
-// - HUD overlays misplaced.
-// - Other various hard to explain graphical errors.
-// - Offsetting the camera too much can easily break culling if the camera is behind the ground/wall/ceiling.
+// - Update default binds.
+// - Bind to change preset.
+// - Bind to reverse freecam input (left AND right stick no effect on camera).
+// - Display equiped armor in the debug UI.
+// - Manully set freecam viewport index.
+// - Override in-game viewmode.
+// - +right and +forward to move character.
+// - Keyframes?
+// - Special case freecam for cutscenes and canteen animations.
+
+// Test cases:
+// Offset Perspective:
+// - For all cases roll should an extra consideration.
+// Constant FOV:
+// - In quest book/board GUI (uses player camera).
+// previousCameraAnimState = 5 (Don't apply offset):
+// - Zoom into quest board or The Handler's book.
+// - Open map animation.
+// - Entering/Leaving tent.
+// previousCameraAnimState = 4 (We choose to apply offset):
+// - Quest depart/return.
+// - Traveling on the lift in Astera.
+// previousCameraAnimState = 2 (Apply offset):
+// - Point camera towards quest board.
+// 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.
+// Free Camera:
+// - Toggle rapidly and there should be no visual jump.
+// - Story cutscenes.
+// - Canteen cutscene/animation.
+// - Inside tent.
+// - Equipment select inside tent.
namespace MHWNewCamera
{
@@ -43,53 +67,69 @@ namespace MHWNewCamera private const double DEFAULT_FOV = 60.0;
- private bool modDisabled = false;
- private bool modToggleDisabled = false;
+ private bool disableMod = false;
private float cameraSpeed;
private float cameraZoomSpeed;
private float cameraSpeedModifier;
private float cameraSensitivity;
- private int stickDeadzone;
private double cameraPitchLimit;
+ private int stickDeadzone;
+
+ private bool enableCombo = false;
+ private Button[]? freeCameraCombo = null;
private double cameraFov = DEFAULT_FOV;
private float cameraForward = 0.0f;
- private float cameraLeft = 0.0f;
+ private float cameraRight = 0.0f;
private float cameraXOffset = 0.0f;
private float cameraYOffset = 0.0f;
private float cameraZOffset = 0.0f;
- private double cameraPitch = 0.0;
private double cameraYaw = 0.0;
+ private double cameraPitch = 0.0;
private double cameraRoll = 0.0;
-
- private double? preZoomFov = null;
- private double? preZoomRoll = null;
+ private int cameraWrapState = 0;
private bool freeCamera = false;
- private bool toggleFreeCamera = false;
+ private bool enableFreeCamera = false;
+ private Camera? vCamera = null;
+ private bool cameraSetFromAlt = false;
+ private Vector3 cameraPosition;
+ private Vector3 cameraTarget;
+ private double? preDetachFov = null;
+ private double? preDetachRoll = null;
private bool unlockMovementHeld = false;
private bool unlockMovementToggled = false;
private bool offsetPerspective = false;
- private bool toggleOffsetPerspective = false;
- private Camera? targetPlayerCamera = null;
+ private bool enableOffsetPerspective = false;
+ private bool applyPerspective = false;
private Player? lastPlayer = null;
+ private Camera? pCamera = null;
private float previousFov = -1.0f;
private int previousCameraAnimState = 0;
- private bool changeAfterMapOpened = true;
- private bool changeAfterGetUp = true;
- private bool changeAfterInsideTent = true;
- private float? resetFovInView = null;
+ private bool ignoreAnimState = false;
+
+ private bool debugButton = false;
+ private float plusRight = 0.0f;
+ private float plusForward = 0.0f;
+
+ private delegate void SetCameraDelegate(nint unknownPtr);
+ private Hook<SetCameraDelegate>? setCameraHook;
+
+ private delegate void SetCameraTentDelegate(nint unknownPtr);
+ private Hook<SetCameraTentDelegate>? setCameraTentHook;
private delegate void CalculateCameraDelegate(nint unknownPtr);
private Hook<CalculateCameraDelegate>? calculateCameraHook;
- private delegate void CalculateViewDelegate(nint unknownPtr);
- private Hook<CalculateViewDelegate>? calculateViewHook;
+ private delegate void CameraUpDelegate(nint unknownPtr);
+ private Hook<CameraUpDelegate>? cameraUpHook;
- private delegate float CalculateMovementDelegate(int stickValue);
- private Hook<CalculateMovementDelegate>? calculateMovementHook;
+ private delegate float CheckMovementDelegate(int stickValue);
+ private Hook<CheckMovementDelegate>? checkMovementHook;
+
+ private Patch disableCameraAnimation;
private bool disableCollision = false;
private bool disableExtraCollision = false;
@@ -102,13 +142,6 @@ namespace MHWNewCamera private Patch disableExtraYCollision;
private Patch disableGravityYUpdate;
private Patch disableGravityXZUpdate;
- /*
- private Patch disableRotationGravity;
- private Patch disableRotationGravity2;
- private Patch disableRotationGravity3;
- private Patch disableRotationGravity4;
- private Patch disableRotationGravity5;
- */
private Patch disableGravityEval;
private void disableCollisionEnable()
@@ -150,52 +183,52 @@ namespace MHWNewCamera private void disableExtraGravityEnable()
{
disableGravityEval.Enable();
- /*
- disableRotationGravity.Enable();
- disableRotationGravity2.Enable();
- disableRotationGravity3.Enable();
- disableRotationGravity4.Enable();
- disableRotationGravity5.Enable();
- disableGravityXZUpdate.Enable();
- */
}
private void disableExtraGravityDisable()
{
disableGravityEval.Disable();
- /*
- disableRotationGravity.Disable();
- disableRotationGravity2.Disable();
- disableRotationGravity3.Disable();
- disableRotationGravity4.Disable();
- disableRotationGravity5.Disable();
- disableGravityXZUpdate.Disable();
- */
}
- private string typedPresetName = "";
-
private static readonly MtObject sMhSteamController = SingletonManager.GetSingleton("sMhSteamController")!;
+ private nint controllerAddr() => sMhSteamController.Instance;
+
+ private static readonly MtObject sOtomo = SingletonManager.GetSingleton("sOtomo")!;
+
+ // Gui strings.
+ private string typedCombo = "";
+ private string typedPresetName = "";
+ private string typedPositionName = "";
+ private string selectedPositionName = "";
public void OnLoad()
{
Config config = ConfigManager.GetConfig<Config>(this);
+ disableMod = config.DisableMod;
+ enableCombo = config.EnableCombo;
+ freeCameraCombo = Config.ParseCombo(config.FreeCameraCombo);
+ typedCombo = config.FreeCameraCombo.Replace(",", "+");
+
Config.Settings settings = config.CameraSettings;
cameraSpeed = settings.CameraSpeed;
cameraZoomSpeed = settings.CameraZoomSpeed;
cameraSpeedModifier = settings.CameraSpeedModifier;
cameraSensitivity = settings.CameraSensitivity;
- stickDeadzone = settings.StickDeadzone;
cameraPitchLimit = settings.CameraPitchLimit;
+ if (cameraPitchLimit != -1.0f)
+ {
+ cameraPitchLimit = Math.Clamp(cameraPitchLimit, 0.0f, 89.95f);
+ }
+ stickDeadzone = settings.StickDeadzone;
- toggleOffsetPerspective = config.PerspectiveCameraEnabled;
+ enableOffsetPerspective = config.PerspectiveCameraEnabled;
if (config.Selected != "")
{
Config.Preset preset = config.Presets[config.Selected];
cameraFov = preset.FOV;
cameraForward = preset.Forward;
- cameraLeft = preset.Left;
+ cameraRight = preset.Right;
cameraYOffset = preset.Up;
cameraRoll = preset.Roll;
}
@@ -203,30 +236,55 @@ namespace MHWNewCamera ConfigManager.SaveConfig<Config>(this);
// Asserts based on version 15.23.00.
+ // @TODO: Handle addr not found.
+
+ // A place to check state before CalculateCameraHook.
+ nint addr = PatternScanner.FindFirst(Pattern.FromString("48 8B C4 48 89 58 08 48 89 70 10 48 89 78 18 4C 89 60 20 55 41 56 41 57 48 8D A8 28 FE FF FF 48 81 EC C0 02 00 00 0F 29 70 D8 48 8B F1"));
+#if ADDR_ASSERTS
+ Trace.Assert(addr == 0x141fa16d0); // nint
+#endif
+ setCameraHook = Hook.Create<SetCameraDelegate>(addr, SetCameraHook);
+
+ // 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<SetCameraTentDelegate>(addr, SetCameraTentHook);
// Hook where we can adjust the camera position.
- nint 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"));
+ 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);
+ Trace.Assert(addr == 0x141fa5380); // nint
#endif
calculateCameraHook = Hook.Create<CalculateCameraDelegate>(addr, CalculateCameraHook);
- // Hook where we can directly modify the view matrix.
- 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"));
+ // Hook where we can set Camera.Up before it's used.
+ addr = PatternScanner.FindFirst(Pattern.FromString("40 53 48 81 EC 80 00 00 00 8B 81 B0 17 00 00 48 8B D9 85 C0 ?? ??"));
#if ADDR_ASSERTS
- Trace.Assert(addr == 0x14228eb60);
+ Trace.Assert(addr == 0x141fa11a0); // nint
#endif
- calculateViewHook = Hook.Create<CalculateViewDelegate>(addr, CalculateViewHook);
+ cameraUpHook = Hook.Create<CameraUpDelegate>(addr, CameraUpHook);
- // Hook where we can adjust the analog stick value the game uses.
+ // Hook where we can change the analog stick value the game uses for character movement.
addr = PatternScanner.FindFirst(Pattern.FromString("66 0F 6E C1 0F 5B C0 85 C9 78 11"));
#if ADDR_ASSERTS
- Trace.Assert(addr == 0x142107cb0);
+ Trace.Assert(addr == 0x142107cb0); // int
#endif
- calculateMovementHook = Hook.Create<CalculateMovementDelegate>(addr, CalculateMovementHook);
+ checkMovementHook = Hook.Create<CheckMovementDelegate>(addr, CheckMovementHook);
unchecked
{
+ addr = PatternScanner.FindFirst(Pattern.FromString("40 53 48 81 EC B0 00 00 00 48 8B D9 48 8B D1 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 48 8B 03 48 8D 54 24 30"));
+#if ADDR_ASSERTS
+ Trace.Assert(addr == 0x1423b1420); // nint
+#endif
+ disableCameraAnimation = new Patch(addr + 0x50, [
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
+ ]);
+
// 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
@@ -267,277 +325,429 @@ namespace MHWNewCamera 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
]);
- /*
- // <PLAYER>+0xac0
-
- // 141325C19 - F3 0F11 83 80000000 - movss [rbx+00000080],xmm0
- // 141325C36 - F3 0F11 83 84000000 - movss [rbx+00000084],xmm0
- // 141325C54 - F3 0F11 83 88000000 - movss [rbx+00000088],xmm0
- addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 59 DB F3 0F 59 D2 F3 0F 11 83 80 00 00 00 F3 0F 58 E3 F3 0F 10 83 84 00 00 00 F3 41 0F 5C C4 F3 0F 58 E2 F3 0F 11 83 84 00 00 00 F3 0F 10 83 88 00 00 00 F3 41 0F 5C C5 44 0F 28 AC 24 C0 01 00 00 F3 0F 11 83 88 00 00 00"));
-#if ADDR_ASSERTS
- Trace.Assert(addr + 0x8 == 0x141325c19);
-#endif
- disableRotationGravity = new Patch(addr + 0x8, [0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90]);
- disableRotationGravity2 = new Patch(addr + 0x25, [0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90]);
- disableRotationGravity3 = new Patch(addr + 0x43, [0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90]);
-
- // 1425D94E4 - F3 0F11 86 C0000000 - movss [rsi+000000C0],xmm0
- // 1425D94F4 - F3 0F11 86 C8000000 - movss [rsi+000000C8],xmm0
- addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 11 86 C0 00 00 00 F3 0F 10 85 48 02 00 00 F3 0F 11 86 C8 00 00 00 F3 0F 10 85 50 02 00 00 F3 0F 11 8E C4 00 00 00 F3 0F 10 8D 54 02 00 00 89 BE CC 00 00 00 F3 0F 11 86 D0 00 00 00 F3 0F 10 85 58 02 00 00 F3 0F 11 86 D8 00 00 00 F3 0F 10 85 68 02 00 00"));
-#if ADDR_ASSERTS
- Trace.Assert(addr == 0x1425D94E4);
-#endif
- disableRotationGravity4 = new Patch(addr, [0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90]);
- disableRotationGravity5 = new Patch(addr + 0x10, [0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90]);
- */
-
- // Stop falling from moving player.
- // 141BFFEFC - F3 0F11 7E 04 - movss [rsi+04],xmm7
- //
- // Instance (of many?) of Y position evaluation for falling?
- // 141325E2A - 44 0F2F 9B 80010000 - comiss xmm11,[rbx+00000180]
-
// 141BFFF75 - E8 965872FF - call MonsterHunterWorld.exe+1325810
addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 11 97 54 15 00 00 F3 0F 11 8F 58 15 00 00 F3 0F 10 47 68 F3 0F 5E D8 44 89 B7 6C 15 00 00 F3 0F 5E D0 F3 0F 5E C8 F3 0F 11 9F 60 15 00 00 F3 0F 11 97 64 15 00 00 F3 0F 11 8F 68 15 00 00"));
#if ADDR_ASSERTS
- Trace.Assert(addr + 0x40 == 0x141BFFF75);
+ Trace.Assert(addr + 0x40 == 0x141bfff75);
#endif
disableGravityEval = new Patch(addr + 0x40, [0x90, 0x90, 0x90, 0x90, 0x90]);
}
}
- // These "assume" functions are really scuffed and almost certainly could have
- // more proper checks, I just haven't gotten around to it.
+ 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);
+ }
- // Quest board menu.
- private static bool assumeInQuestBoard(float fov)
+ private void setCameraRoll(Camera camera)
{
- return fov == 20.000038f || fov == 20.017189f || fov == 20.00004f;
+ // Don't test our luck with precision weirdness if we know we can be exact.
+ if (cameraRoll == 0.0)
+ {
+ camera.Up.X = 0.0f;
+ camera.Up.Y = 1.0f;
+ camera.Up.Z = 0.0f;
+ }
+ else if (cameraRoll == 180.0)
+ {
+ camera.Up.X = 0.0f;
+ camera.Up.Y = -1.0f;
+ camera.Up.Z = 0.0f;
+ }
+ else
+ {
+ // yaw + 90.0 = point right.
+ camera.Up.X = (float)(Math.Sin(Double.DegreesToRadians(cameraRoll)) * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Cos(Double.DegreesToRadians(cameraYaw + 90.0)));
+ camera.Up.Y = (float)(Math.Cos(Double.DegreesToRadians(cameraRoll)));
+ camera.Up.Z = (float)(Math.Sin(Double.DegreesToRadians(cameraRoll)) * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Sin(Double.DegreesToRadians(cameraYaw + 90.0)));
+ }
+ }
+
+ private void setPerspective(Camera camera)
+ {
+ Quaternion forward = getForward(camera.Position, camera.Target);
+ Quaternion right = forward * Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(Single.DegreesToRadians(180.0f)));
+ forward = Quaternion.Normalize(forward);
+ right = Quaternion.Normalize(right);
+ Vector3 pos = camera.Position;
+ pos.X += forward.X * cameraForward;
+ pos.Y += forward.Y * cameraForward;
+ pos.Z += forward.Z * cameraForward;
+ pos.X += right.X * cameraRight;
+ pos.Z += right.Z * cameraRight;
+ pos.X += cameraXOffset;
+ if (debugButton) pos.Y += cameraYOffset;
+ pos.Z += cameraZOffset;
+ camera.Position = pos;
+ if (debugButton && cameraFov != DEFAULT_FOV)
+ {
+ camera.FieldOfView = (float)((cameraFov * previousFov) / DEFAULT_FOV);
+ }
}
- private bool assumeOnRails(Viewport vp, Camera camera)
+ private void setTentBasePos(Vector3 pos, Vector3 target)
{
- // 1. Seasonal gathering hub cutscene.
- // 2. Zoom into quest board or the handler's book.
- // 3. Leaving tent.
- // 4. Getting up from carting.
- // 5. Leaving dialoge with NPC.
- // Checking Up.Y != 1.0f is an attempt to include only #2.
- return vp.Camera != null && vp.Camera.Instance != camera.Instance && vp.Camera.FarClip == 4000000 &&
- vp.Camera.Fix && vp.Camera.Up.Y != 1.0f;
+ // @TODO: This can be picked out of the code.
+ nint baseAddr = MemoryUtil.Read<nint>(0x145011f58); // Default:
+ MemoryUtil.WriteBytes(baseAddr + 0x3e20, BitConverter.GetBytes(pos.X)); // 0.0
+ MemoryUtil.WriteBytes(baseAddr + 0x3e24, BitConverter.GetBytes(pos.Y)); // -19850.0
+ MemoryUtil.WriteBytes(baseAddr + 0x3e28, BitConverter.GetBytes(pos.Z)); // 270.0
+ MemoryUtil.WriteBytes(baseAddr + 0x3e30, BitConverter.GetBytes(target.X)); // 0.0
+ MemoryUtil.WriteBytes(baseAddr + 0x3e34, BitConverter.GetBytes(target.Y)); // -19830.0
+ MemoryUtil.WriteBytes(baseAddr + 0x3e38, BitConverter.GetBytes(target.Z)); // 0.0
}
- private bool assumeInOpenMap(float fov)
+ private void disableFreeCamera()
{
- if (fov == 50.942066f)
+ freeCamera = false;
+ if (preDetachFov != null)
+ {
+ cameraFov = (double)preDetachFov;
+ preDetachFov = null;
+ }
+ if (preDetachRoll != null)
{
- if (!changeAfterMapOpened)
+ cameraRoll = (double)preDetachRoll;
+ preDetachRoll = null;
+ }
+ cameraWrapState = 0;
+ setTentBasePos(new Vector3(0.0f, -19850.0f, 270.0f), new Vector3(0.0f, -19830.0f, 0.0f));
+ cameraSetFromAlt = false;
+ }
+
+ private void updateFreecam(Camera camera)
+ {
+ float deltaTime = camera.DeltaTime;
+
+ if (Input.IsDown(Button.L2) && Input.IsDown(Button.R2)) // Left stick zoom.
+ {
+ int PadLy = MemoryUtil.Read<int>(controllerAddr() + 0x1bc);
+ if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0;
+ double adjustedZoomSpeed = cameraZoomSpeed * deltaTime * cameraFov;
+ double Ly = PadLy / (Int16.MaxValue / adjustedZoomSpeed);
+ cameraFov = Math.Clamp(cameraFov - Ly, 1.0, 179.0);
+ }
+ else if (!(unlockMovementHeld || unlockMovementToggled)) // Move camera.
+ {
+ int PadLy = MemoryUtil.Read<int>(controllerAddr() + 0x1bc);
+ if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0;
+ int PadLx = MemoryUtil.Read<int>(controllerAddr() + 0x1b8);
+ if (Math.Abs(PadLx) < stickDeadzone) PadLx = 0;
+ double adjustedSpeed = cameraSpeed * deltaTime;
+ double Lx = PadLx / (Int16.MaxValue / adjustedSpeed);
+ double Ly = PadLy / (Int16.MaxValue / adjustedSpeed);
+
+ Quaternion forward = getForward(cameraPosition, cameraTarget);
+
+ if (Input.IsDown(Button.L2))
{
- return true;
+ forward.Y = 0.0f;
+ Lx *= cameraSpeedModifier;
+ Ly *= cameraSpeedModifier;
+ double buttonOffset = adjustedSpeed / 2.0;
+ buttonOffset *= cameraSpeedModifier;
+ if (Input.IsDown(Button.Up))
+ {
+ cameraPosition.Y += (float)buttonOffset;
+ }
+ if (Input.IsDown(Button.Down))
+ {
+ cameraPosition.Y -= (float)buttonOffset;
+ }
+ if (Input.IsDown(Button.Left))
+ {
+ cameraRoll -= buttonOffset;
+ }
+ if (Input.IsDown(Button.Right))
+ {
+ cameraRoll += buttonOffset;
+ }
}
- // Assume the camera's FOV could end up at 50.942066 during normal gameplay.
- // Try to mitigate that by tracking the triggers for opening the map
- // (press and quickly release select or press A at departure location).
- if (Input.IsReleased(Button.Share) || Input.IsPressed(Button.Cross))
+
+ Quaternion right = forward;
+ right.Y = 0.0f;
+ right = right * Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(Single.DegreesToRadians(180.0f)));
+ forward = Quaternion.Normalize(forward);
+ right = Quaternion.Normalize(right);
+ cameraPosition.X += (float)(right.X * Lx);
+ cameraPosition.Z += (float)(right.Z * Lx);
+ cameraPosition.X += (float)(forward.X * Ly);
+ cameraPosition.Y += (float)(forward.Y * Ly);
+ cameraPosition.Z += (float)(forward.Z * Ly);
+
+ if (plusForward != 0.0f)
{
- changeAfterMapOpened = false;
- return true;
+ cameraPosition.X += (float)(forward.X * plusForward * deltaTime);
+ cameraPosition.Y += (float)(forward.Y * plusForward * deltaTime);
+ cameraPosition.Z += (float)(forward.Z * plusForward * deltaTime);
}
}
- if (!changeAfterMapOpened) changeAfterMapOpened = true;
+ // Camera look.
+ int PadRx = MemoryUtil.Read<int>(controllerAddr() + 0x1b0);
+ if (Math.Abs(PadRx) < stickDeadzone) PadRx = 0;
+ int PadRy = MemoryUtil.Read<int>(controllerAddr() + 0x1b4);
+ if (Math.Abs(PadRy) < stickDeadzone) PadRy = 0;
+ double adjustedSensitivity = cameraSensitivity * deltaTime * cameraFov;
+ double Rx = PadRx / (Int16.MaxValue / adjustedSensitivity);
+ double Ry = PadRy / (Int16.MaxValue / adjustedSensitivity);
+ cameraYaw += Rx;
+ if (cameraYaw >= 180.0)
+ {
+ cameraYaw -= 360.0;
+ }
+ else if (cameraYaw < -180.0)
+ {
+ cameraYaw += 360.0;
+ }
+ if (cameraPitchLimit >= 0.0)
+ {
+ cameraPitch = Math.Clamp(cameraPitch + Ry, -cameraPitchLimit, cameraPitchLimit);
+ }
+ else
+ {
+ cameraPitch += Ry;
+ if (cameraPitch >= 90.0 && cameraWrapState == 0)
+ {
+ cameraRoll += 180.0;
+ cameraWrapState = 1;
+ }
+ else if (cameraPitch < -90.0 && cameraWrapState == 0)
+ {
+ cameraPitch += 360.0;
+ cameraRoll += 180.0;
+ cameraWrapState = 1;
+ }
+ else if (cameraPitch < 90.0 && cameraWrapState == 1)
+ {
+ cameraRoll -= 180.0;
+ cameraWrapState = 0;
+ }
+ else if (cameraPitch >= 270.0 && cameraWrapState == 1)
+ {
+ cameraPitch -= 360.0;
+ cameraRoll -= 180.0;
+ cameraWrapState = 0;
+ }
+ }
+ if (cameraRoll >= 360.0)
+ {
+ cameraRoll -= 360.0;
+ }
+ else if (cameraRoll < 0.0)
+ {
+ cameraRoll += 360.0;
+ }
- return false;
+ if (plusRight != 0.0)
+ {
+ cameraYaw += plusRight * deltaTime;
+ }
+
+ // 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.
+ double dist = 700.0 - cameraForward;
+ cameraTarget.X = cameraPosition.X + (float)(dist * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Cos(Double.DegreesToRadians(cameraYaw)));
+ cameraTarget.Y = cameraPosition.Y + (float)(dist * Math.Sin(Double.DegreesToRadians(cameraPitch)));
+ cameraTarget.Z = cameraPosition.Z + (float)(dist * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Sin(Double.DegreesToRadians(cameraYaw)));
+
+ camera.Position = cameraPosition;
+ camera.Target = cameraTarget;
+ camera.FieldOfView = (float)cameraFov;
}
- private bool assumeInCanteen(float fov, float previousFov)
+ private Camera? getVisibleCamera()
{
- if (fov == 50.0f)
+ for (int i = 0; i < 8; i++)
{
- if (!changeAfterGetUp)
- {
- return true;
- }
- // Assume that FOV will be greater than or equal to 51.0 before sitting at the canteen.
- // Also, assume that if FOV is equal to 50.0 in a different situation, previousFov
- // will be less than 51.0 because it would have been lowering last frame.
- // This is easily the most fragile check here.
- if (previousFov >= 51.0f)
+ Viewport vp = CameraSystem.GetViewport(i);
+ // A viewport can be visible with a null camera.
+ if (vp.Visible && vp.Camera != null)
{
- if (Input.IsPressed(Button.Cross) || (Input.IsDown(Button.Triangle) || Input.IsReleased(Button.Triangle)))
+ if (freeCamera && vp.Camera != vCamera)
{
- changeAfterGetUp = false;
- return true;
+ // This will still be broken in most cases, just less broken.
+ cameraPosition = vp.Camera.Position;
+ cameraTarget = vp.Camera.Target;
}
+ return vp.Camera;
}
}
-
- if (!changeAfterGetUp) changeAfterGetUp = true;
-
- return false;
+ return null;
}
- private bool assumeInEnterTent(Camera camera, int animState)
+ private void SetCameraHook(nint unknownPtr)
{
- if (camera.Up.Y != 1.0f && animState == 5)
+ if (!disableMod)
{
- if (!changeAfterInsideTent)
+ vCamera = getVisibleCamera();
+ if (pCamera == null && lastPlayer != null)
{
- return true;
+ // This assume the visible camera when, or right after, MainPlayer is set is the player camera.
+ pCamera = vCamera;
}
- // This is possible to trip if you spam A while loading into a level before
- // seeing the wingdrake animation.
- if (previousCameraAnimState != 5)
+ if (pCamera != null)
{
- if (Input.IsPressed(Button.Cross))
+ previousCameraAnimState = MemoryUtil.Read<int>(pCamera.Instance + 0x240);
+ if (previousCameraAnimState == 5)
{
- changeAfterInsideTent = false;
- return true;
+ // 1:314 = Wingdrake landing on area enter.
+ // 1:319 = Scared wingdrake landing next to monster.
+ Player player = Player.MainPlayer!;
+ ActionInfo currentActionInfo = player.ActionController.CurrentAction;
+ if (currentActionInfo.ActionSet == 1 && (currentActionInfo.ActionId == 314 || currentActionInfo.ActionId == 319))
+ {
+ // Temporarily disable evaluation of cameraAnimState != 5.
+ ignoreAnimState = true;
+ }
+ }
+ else if (ignoreAnimState)
+ {
+ // Once cameraAnimState is no longer 5, resume default logic.
+ ignoreAnimState = false;
}
}
+ else
+ {
+ previousCameraAnimState = 0;
+ }
}
-
- if (!changeAfterInsideTent) changeAfterInsideTent = true;
-
- return false;
+ setCameraHook!.Original(unknownPtr);
}
- private void maybeSetFovForCulling(Viewport vp, Camera camera)
+ private void SetCameraTentHook(nint unknownPtr)
{
- /* I don't think this would be correct. As of now I'm pretty sure roll is only
- * considered after this point, in CalculateViewHook.
- if (cameraRoll == 90.0 || cameraRoll == 270.0)
- {
- camera.AspectRatio = vp.Region.Height / (float)vp.Region.Width;
- }
- */
- if (cameraRoll != 0.0 && camera.FieldOfView < 130.0f)
+ if (!disableMod && freeCamera)
{
- // The closer the FOV is to 180, the more odd behavior occurs.
- // 130 seems like a OK default for when the camera is rolled.
- // This will break HUD overlays like "!" on top of NPCs and the tent exit cutscene.
- resetFovInView = camera.FieldOfView;
- camera.FieldOfView = 130.0f;
+ setTentBasePos(cameraPosition, cameraTarget);
}
- /*
- else if (camera.FieldOfView < 60.0f)
+ setCameraTentHook!.Original(unknownPtr);
+ if (!disableMod && freeCamera && vCamera != null)
{
- resetFovInView = camera.FieldOfView;
- camera.FieldOfView = 60.0f;
+ updateFreecam(vCamera);
+ setCameraRoll(vCamera);
+ cameraSetFromAlt = true;
}
- */
- }
-
- private void setPerspective(Camera camera, Vector3 pos, Quaternion forward)
- {
- Quaternion left = forward * Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(Single.DegreesToRadians(180.0f)));
- pos.X += forward.X * cameraForward;
- pos.Y += forward.Y * cameraForward;
- pos.Z += forward.Z * cameraForward;
- pos.X -= left.X * cameraLeft;
- pos.Z -= left.Z * cameraLeft;
- pos.X += cameraXOffset;
- pos.Y += cameraYOffset;
- pos.Z += cameraZOffset;
- camera.Position = pos;
}
- private static Quaternion getForward(Vector3 pos, Vector3 target)
+ private static bool assumeInQuestBoard(float fov)
{
- return new Quaternion(target.X - pos.X, target.Y - pos.Y, target.Z - pos.Z, 0.0f);
+ return fov == 20.000038f || fov == 20.017189f || fov == 20.00004f;
}
- // If freeCamera (camera.Move = false), this hook won't run.
+ // If camera.Move = false, this hook won't run.
private void CalculateCameraHook(nint unknownPtr)
{
- if (modDisabled)
+ if (disableMod)
{
calculateCameraHook!.Original(unknownPtr);
return;
}
- Viewport vp = CameraSystem.MainViewport;
- Camera? camera = offsetPerspective ? targetPlayerCamera : vp.Camera;
- if (camera == null) return;
-
- bool applyPerspective = offsetPerspective;
- if (offsetPerspective)
+ if (enableOffsetPerspective && !offsetPerspective)
{
- int cameraAnimState = MemoryUtil.Read<int>(camera.Instance + 0x240);
- applyPerspective = camera.Fix && camera.Move;
- applyPerspective &= !assumeOnRails(vp, camera);
- applyPerspective &= !assumeInQuestBoard(camera.FieldOfView);
- applyPerspective &= !assumeInOpenMap(camera.FieldOfView);
- applyPerspective &= !assumeInCanteen(camera.FieldOfView, previousFov);
- applyPerspective &= !assumeInEnterTent(camera, cameraAnimState);
- previousCameraAnimState = cameraAnimState;
+ offsetPerspective = true;
+ }
+ else if (!enableOffsetPerspective && offsetPerspective)
+ {
+ offsetPerspective = false;
}
- previousFov = camera.FieldOfView;
-
- calculateCameraHook!.Original(unknownPtr);
+ if (pCamera != null)
+ {
+ // previousFov is the pre-offset FOV value.
+ previousFov = pCamera.FieldOfView;
+ }
+ applyPerspective = offsetPerspective && !freeCamera && pCamera != null;
if (applyPerspective)
{
- Quaternion forward = Quaternion.Normalize(getForward(camera.Position, camera.Target));
- setPerspective(camera, camera.Position, forward);
- camera.FieldOfView = (float)((cameraFov * previousFov) / 60.0);
+ applyPerspective &= (previousCameraAnimState != 5 || ignoreAnimState);
+ applyPerspective &= !assumeInQuestBoard(previousFov);
}
- if (toggleFreeCamera && !freeCamera)
+ if (applyPerspective && !debugButton)
{
- freeCamera = true;
- camera.Move = false;
- preZoomFov = cameraFov;
- preZoomRoll = cameraRoll;
- if (applyPerspective)
+ // Applying Y offset here keeps crosshair UI centered, but affects the angle of the camera.
+ pCamera!.Position.Y += cameraYOffset;
+ if (cameraFov != DEFAULT_FOV)
{
- cameraFov = camera.FieldOfView;
+ pCamera!.FieldOfView = (float)((cameraFov * previousFov) / DEFAULT_FOV);
}
- // Camera position might have changed.
- Quaternion forward = Quaternion.Normalize(getForward(camera.Position, camera.Target));
- cameraPitch = Double.RadiansToDegrees(Math.Asin(forward.Y));
- cameraYaw = Double.RadiansToDegrees(Math.Atan2(forward.Z, forward.X));
}
- if (applyPerspective) maybeSetFovForCulling(vp, camera);
- }
+ calculateCameraHook!.Original(unknownPtr);
- private void CalculateViewHook(nint unknownPtr)
- {
- if (modDisabled)
+ // Setting the perspective at this point (after 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 too much later, it may not
+ // be considered by lower-level functions like culling.
+ if (applyPerspective)
{
- calculateViewHook!.Original(unknownPtr);
- return;
+ setPerspective(pCamera!);
}
- Viewport vp = CameraSystem.MainViewport;
- bool notFreecam = offsetPerspective && !freeCamera;
- Camera? camera = notFreecam ? targetPlayerCamera : vp.Camera;
-
- bool updateView = freeCamera || offsetPerspective;
- if (resetFovInView != null && updateView && camera != null)
+ if (vCamera != null)
{
- camera.FieldOfView = (float)resetFovInView;
- resetFovInView = 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 = Double.RadiansToDegrees(Math.Atan2(forward.Z, forward.X));
+ cameraPitch = Double.RadiansToDegrees(Math.Asin(forward.Y));
+ if (enableFreeCamera)
+ {
+ freeCamera = true;
+ cameraPosition = vCamera.Position;
+ cameraTarget = vCamera.Target;
+ preDetachFov = cameraFov;
+ preDetachRoll = cameraRoll;
+ // 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 freecam. This is also why
+ // we don't enable freecam until after applying a offset on this update.
+ cameraFov = vCamera.FieldOfView;
+ }
+ }
+ // No else if because we wan't to updateFreecam() if freeCamera was enabled above.
+ if (freeCamera)
+ {
+ if (!cameraSetFromAlt)
+ {
+ updateFreecam(vCamera);
+ }
+ cameraSetFromAlt = false;
+ if (!enableFreeCamera)
+ {
+ disableFreeCamera();
+ }
+ }
}
+ }
- calculateViewHook!.Original(unknownPtr);
-
- if (updateView && cameraRoll != 0.0)
+ private void CameraUpHook(nint unknownPtr)
+ {
+ cameraUpHook!.Original(unknownPtr);
+ if (disableMod) return;
+ // This is still runs before culling. Checking Camera.Fix for tent idle, at least.
+ if ((applyPerspective || freeCamera) && vCamera != null && vCamera.Fix)
+ {
+ setCameraRoll(vCamera);
+ }
+ if (applyPerspective)
{
- Matrix4x4 rollRotation = Matrix4x4.CreateRotationZ((float)Double.DegreesToRadians(cameraRoll));
- vp.ViewMatrix *= rollRotation;
+ setCameraRoll(pCamera!);
}
}
- private float CalculateMovementHook(int stickValue)
+ private float CheckMovementHook(int stickValue)
{
- if (!modDisabled && freeCamera && !(unlockMovementHeld || unlockMovementToggled))
+ if (!disableMod && freeCamera && !(unlockMovementHeld || unlockMovementToggled))
{
stickValue = 0;
}
- return calculateMovementHook!.Original(stickValue);
+ return checkMovementHook!.Original(stickValue);
}
private void disableAllHooks()
@@ -569,24 +779,22 @@ namespace MHWNewCamera Config config = ConfigManager.GetConfig<Config>(this);
float width = ImGui.GetWindowWidth();
- if (ImGui.Checkbox("Disable Mod", ref modDisabled))
+ if (ImGui.Checkbox("Disable Mod", ref disableMod))
{
- if (modDisabled)
+ if (disableMod)
{
disableAllHooks();
if (freeCamera)
{
- freeCamera = false;
- if (preZoomRoll != null)
- {
- cameraRoll = (double)preZoomRoll;
- preZoomRoll = null;
- }
+ disableFreeCamera();
}
for (int i = 0; i < 8; i++)
{
Viewport vp = CameraSystem.GetViewport(i);
- if (vp.Camera != null) vp.Camera.Move = true;
+ if (vp.Camera != null)
+ {
+ vp.Camera.Move = true;
+ }
}
Player? player = Player.MainPlayer;
if (player != null)
@@ -595,59 +803,71 @@ namespace MHWNewCamera player.Rotation.Z = 0.0f;
}
}
+ config.DisableMod = disableMod;
+ ConfigManager.SaveConfig<Config>(this);
}
if (ImGui.BeginItemTooltip())
{
ImGui.Text("Try to disable as much of the mod as possible.");
ImGui.EndTooltip();
}
- if (modDisabled) return;
- ImGui.Checkbox("Disable Toggle Bind", ref modToggleDisabled);
- if (ImGui.BeginItemTooltip())
- {
- ImGui.Text("Disable button combination (Hold RStick + Press LT) for toggling free camera.");
- ImGui.EndTooltip();
- }
+ if (disableMod) return;
- ImGui.Checkbox("Enable Free Camera", ref toggleFreeCamera);
- if (toggleFreeCamera)
+ 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 toggleOffsetPerspective))
+ if (ImGui.Checkbox("Enable Perspective Camera", ref enableOffsetPerspective))
{
- // Take the opposite because it's yet to be toggled.
- config.PerspectiveCameraEnabled = !offsetPerspective;
+ config.PerspectiveCameraEnabled = enableOffsetPerspective;
ConfigManager.SaveConfig<Config>(this);
}
- if (toggleFreeCamera)
+ if (enableFreeCamera)
{
ImGui.PopItemFlag();
ImGui.PopStyleVar();
}
+ ImGui.Separator();
+
ImGui.PushID("Perspective");
float singleFov = (float)cameraFov;
if (ImGui.DragFloat("Field of View", ref singleFov, 0.4f, 1.0f, 179.0f))
{
cameraFov = singleFov;
}
- ImGui.DragFloat("Forward", ref cameraForward, 0.4f);
- ImGui.DragFloat("Left", ref cameraLeft, 0.4f);
- ImGui.DragFloat("Up", ref cameraYOffset, 0.4f);
+ ImGui.DragFloat("Forward", ref cameraForward, 0.25f);
+ ImGui.DragFloat("Right", ref cameraRight, 0.25f);
+ ImGui.DragFloat("Up", ref cameraYOffset, 0.025f);
+ float roll = (float)cameraRoll;
+ if (ImGui.DragFloat("Roll", ref roll, 0.25f))
+ {
+ cameraRoll = roll;
+ if (preDetachRoll != null)
+ {
+ preDetachRoll = roll;
+ }
+ }
if (ImGui.Button("Default"))
{
cameraFov = DEFAULT_FOV;
cameraForward = 0.0f;
- cameraLeft = 0.0f;
+ cameraRight = 0.0f;
cameraXOffset = 0.0f;
cameraYOffset = 0.0f;
cameraZOffset = 0.0f;
+ cameraRoll = 0.0f;
config.Selected = "";
ConfigManager.SaveConfig<Config>(this);
}
ImGui.SameLine();
+ ImGui.PushItemWidth(width * 0.15f);
+ ImGui.InputText("##Preset Name", ref typedPresetName, 99);
+ ImGui.SameLine();
if (ImGui.Button("Save"))
{
string name = typedPresetName;
@@ -656,7 +876,7 @@ namespace MHWNewCamera Config.Preset preset = new Config.Preset();
preset.FOV = cameraFov;
preset.Forward = cameraForward;
- preset.Left = cameraLeft;
+ preset.Right = cameraRight;
preset.Up = cameraYOffset;
preset.Roll = cameraRoll;
if (config.Presets.ContainsKey(name))
@@ -672,19 +892,6 @@ namespace MHWNewCamera }
}
ImGui.SameLine();
- if (ImGui.Button("Delete"))
- {
- if (config.Selected != "")
- {
- config.Presets.Remove(config.Selected);
- config.Selected = "";
- ConfigManager.SaveConfig<Config>(this);
- }
- }
- ImGui.SameLine();
- ImGui.PushItemWidth(width * 0.2f);
- ImGui.InputText("##Preset Name", ref typedPresetName, 99);
- ImGui.SameLine();
if (ImGui.BeginCombo("##Preset", config.Selected))
{
Dictionary<string, Config.Preset>.KeyCollection presetKeys = config.Presets.Keys;
@@ -699,7 +906,7 @@ namespace MHWNewCamera Config.Preset preset = config.Presets[config.Selected];
cameraFov = preset.FOV;
cameraForward = preset.Forward;
- cameraLeft = preset.Left;
+ cameraRight = preset.Right;
cameraYOffset = preset.Up;
cameraRoll = preset.Roll;
}
@@ -708,6 +915,16 @@ namespace MHWNewCamera ImGui.EndCombo();
}
ImGui.PopItemWidth();
+ ImGui.SameLine();
+ if (ImGui.Button("Delete"))
+ {
+ if (config.Selected != "")
+ {
+ config.Presets.Remove(config.Selected);
+ config.Selected = "";
+ ConfigManager.SaveConfig<Config>(this);
+ }
+ }
ImGui.PopID();
ImGui.PushID("Settings");
@@ -735,6 +952,20 @@ namespace MHWNewCamera ImGui.Text("Camera look sensitivity in freecam.");
ImGui.EndTooltip();
}
+ float pitchLimit = (float)cameraPitchLimit;
+ if (ImGui.InputFloat("Pitch Limit", ref pitchLimit, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue))
+ {
+ cameraPitchLimit = pitchLimit;
+ if (cameraPitchLimit != -1.0f)
+ {
+ cameraPitchLimit = Math.Clamp(cameraPitchLimit, 0.0f, 89.95f);
+ }
+ }
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("-1.0 = Wrap around (go upside down).");
+ ImGui.EndTooltip();
+ }
ImGui.InputInt("Stick Deadzone", ref stickDeadzone, 10);
if (ImGui.Button("Default"))
{
@@ -742,8 +973,8 @@ namespace MHWNewCamera cameraZoomSpeed = Config.Settings.DEFAULT_ZOOM_SPEED;
cameraSpeedModifier = Config.Settings.DEFAULT_SPEED_MODIFIER;
cameraSensitivity = Config.Settings.DEFAULT_SENSITIVITY;
- stickDeadzone = Config.Settings.DEFAULT_DEADZONE;
cameraPitchLimit = Config.Settings.DEFAULT_PITCH_LIMIT;
+ stickDeadzone = Config.Settings.DEFAULT_DEADZONE;
}
ImGui.SameLine();
if (ImGui.Button("Reset"))
@@ -753,8 +984,8 @@ namespace MHWNewCamera cameraZoomSpeed = settings.CameraZoomSpeed;
cameraSpeedModifier = settings.CameraSpeedModifier;
cameraSensitivity = settings.CameraSensitivity;
- stickDeadzone = settings.StickDeadzone;
cameraPitchLimit = settings.CameraPitchLimit;
+ stickDeadzone = settings.StickDeadzone;
}
ImGui.SameLine();
if (ImGui.Button("Save"))
@@ -764,29 +995,84 @@ namespace MHWNewCamera settings.CameraZoomSpeed = cameraZoomSpeed;
settings.CameraSpeedModifier = cameraSpeedModifier;
settings.CameraSensitivity = cameraSensitivity;
- settings.StickDeadzone = stickDeadzone;
settings.CameraPitchLimit = cameraPitchLimit;
+ settings.StickDeadzone = stickDeadzone;
config.CameraSettings = settings;
ConfigManager.SaveConfig<Config>(this);
}
ImGui.PopID();
+ ImGui.PushID("Binds");
+ if (ImGui.CollapsingHeader("Binds"))
+ {
+ if (ImGui.Checkbox("Toggle Free Camera", ref enableCombo))
+ {
+ config.EnableCombo = enableCombo;
+ ConfigManager.SaveConfig<Config>(this);
+ }
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("Hold the first button and press the second.");
+ 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.FreeCameraCombo = comboString;
+ ConfigManager.SaveConfig<Config>(this);
+ }
+ }
+ }
+ ImGui.PopID();
+
ImGui.PushID("Debug");
- if (ImGui.CollapsingHeader("DEBUG"))
+ if (ImGui.CollapsingHeader("DEBUG/Extras"))
{
+ ImGui.Checkbox("Debug Button", ref debugButton);
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("Currently toggles how early camera Y position and FOV are set (off = earlier).\nIf you want to see why: go out, set a big \"Up\" offset, aim in your slinger and click this button on and off.");
+ ImGui.EndTooltip();
+ }
+
ImGui.PushID("Camera");
- if (targetPlayerCamera != null)
+ if (pCamera != null)
{
- ImGui.Text($"Target Camera: {targetPlayerCamera.Instance:x}");
+ ImGui.Text($"Player Camera: {pCamera.Instance:x}");
+ ImGui.Text($"Applying Offset: {applyPerspective}");
+ ImGui.Text($"previousCameraAnimState: {previousCameraAnimState}");
}
+
+ ImGui.Separator();
+
ImGui.Text("Camera/Viewport:");
- Viewport vp;
for (int i = 0; i < 8; i++)
{
- if (ImGui.CollapsingHeader($"Camera #{i}"))
+ ImGui.PushID($"Viewport{i}");
+ Viewport vp = CameraSystem.GetViewport(i);
+ if (ImGui.CollapsingHeader($"Viewport #{i} ({(vp.Visible ? "visible" : "inactive")})"))
{
- ImGui.PushID($"Camera{i}");
- vp = CameraSystem.GetViewport(i);
ImGui.Text($"Pointer: {vp.Instance:x}");
ImGui.Text($"Visible: {vp.Visible}");
ImGui.Text($"Region: {vp.Region.X} {vp.Region.Y} {vp.Region.Width} {vp.Region.Height}");
@@ -798,11 +1084,14 @@ namespace MHWNewCamera var camera = vp.Camera;
ImGui.Text($"Camera Pointer: {camera.Instance:x}");
ImGui.DragFloat("FOV", ref camera.FieldOfView, 0.45f);
- ImGui.Text($"Internal FOV: {previousFov}");
- if (ImGui.BeginItemTooltip())
+ if (camera == pCamera)
{
- ImGui.Text("What the FOV would be if not set by us.");
- ImGui.EndTooltip();
+ ImGui.Text($"Internal FOV: {previousFov}");
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("What the FOV would be if not set by us.");
+ ImGui.EndTooltip();
+ }
}
ImGui.InputFloat("Aspect Ratio", ref camera.AspectRatio);
ImGui.InputFloat("Far Clip", ref camera.FarClip);
@@ -810,51 +1099,113 @@ namespace MHWNewCamera ImGui.DragFloat3("Position", ref camera.Position, 0.45f);
ImGui.DragFloat3("Target", ref camera.Target, 0.45f);
ImGui.DragFloat3("Up", ref camera.Up, 0.45f);
- ImGui.Text("Offset:");
- float offsetForward = 0.0f;
- if (ImGui.DragFloat("Forward", ref offsetForward, 0.45f))
+ ImGui.PushItemWidth(width * 0.15f);
+ ImGui.InputText("##Position Name", ref typedPositionName, 99);
+ ImGui.SameLine();
+ if (ImGui.Button("Save"))
{
- 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;
+ string name = typedPositionName;
+ if (name != "")
+ {
+ Config.SavedPosition pos = new Config.SavedPosition();
+ 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<Config>(this);
+ }
}
- float offsetLeft = 0.0f;
- if (ImGui.DragFloat("Left", ref offsetLeft, 0.45f))
+ ImGui.SameLine();
+ if (ImGui.BeginCombo("##Positions", ""))
{
- Quaternion forward = getForward(camera.Position, camera.Target);
- forward = Quaternion.Normalize(forward);
- Quaternion left = forward * Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(Single.DegreesToRadians(180.0f)));
- camera.Position.X += left.X * offsetLeft;
- camera.Position.Z += left.Z * offsetLeft;
+ Dictionary<string, Config.SavedPosition>.KeyCollection positionKeys = config.Positions.Keys;
+ for (int j = 0; j < positionKeys.Count; j++)
+ {
+ string positionKey = positionKeys.ElementAt(j);
+ if (ImGui.Selectable(positionKey))
+ {
+ Config.SavedPosition pos = config.Positions[positionKey];
+ selectedPositionName = positionKey;
+ 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 = Double.RadiansToDegrees(Math.Atan2(forward.Z, forward.X));
+ cameraPitch = Double.RadiansToDegrees(Math.Asin(forward.Y));
+ camera.Position = cameraPosition;
+ camera.Target = cameraTarget;
+ cameraRoll = pos.Roll;
+ }
+ }
+ ImGui.EndCombo();
}
- if (i == 0)
+ ImGui.PopItemWidth();
+ ImGui.SameLine();
+ if (ImGui.Button("Delete"))
{
- ImGui.Text("Rotation:");
- double pitch = cameraPitch;
- if (ImGui.InputDouble("Pitch", ref pitch, 0.25))
+ if (selectedPositionName != "")
{
- cameraPitch = pitch;
+ config.Positions.Remove(selectedPositionName);
+ selectedPositionName = "";
+ ConfigManager.SaveConfig<Config>(this);
}
- double yaw = cameraYaw;
- if (ImGui.InputDouble("Yaw", ref yaw, 0.25))
+ }
+ if (camera == vCamera)
+ {
+ float yaw = (float)cameraYaw;
+ if (ImGui.DragFloat("Yaw", ref yaw, 0.25f))
{
cameraYaw = yaw;
}
- float roll = (float)cameraRoll;
- if (ImGui.DragFloat("Roll", ref roll, 0.25f))
+ float pitch = (float)cameraPitch;
+ if (ImGui.DragFloat("Pitch", ref pitch, 0.25f))
{
- cameraRoll = roll;
- if (preZoomRoll != null)
- {
- preZoomRoll = roll;
- }
+ cameraPitch = pitch;
+ }
+ float offsetRoll = (float)cameraRoll;
+ if (ImGui.DragFloat("Roll", ref offsetRoll, 0.25f))
+ {
+ cameraRoll = offsetRoll;
+ }
+ if (camera == pCamera && !freeCamera)
+ {
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
+ }
+ ImGui.Text("Offset:");
+ float offsetForward = 0.0f;
+ if (ImGui.DragFloat("Forward", ref offsetForward, 0.45f))
+ {
+ 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;
+ cameraPosition = camera.Position;
}
- float pitchLimit = (float)cameraPitchLimit;
- if (ImGui.InputFloat("Pitch Limit", ref pitchLimit, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue))
+ float offsetRight = 0.0f;
+ if (ImGui.DragFloat("Right", ref offsetRight, 0.45f))
{
- cameraPitchLimit = pitchLimit;
+ Quaternion forward = getForward(camera.Position, camera.Target);
+ Quaternion right = forward * Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(Single.DegreesToRadians(180.0f)));
+ forward = Quaternion.Normalize(forward);
+ right = Quaternion.Normalize(right);
+ camera.Position.X += right.X * offsetRight;
+ camera.Position.Z += right.Z * offsetRight;
+ cameraPosition = camera.Position;
+ }
+ if (camera == pCamera && !freeCamera)
+ {
+ ImGui.PopStyleVar();
}
}
bool move = camera.Move;
@@ -869,8 +1220,8 @@ namespace MHWNewCamera camera.Fix = fix;
}
}
- ImGui.PopID();
}
+ ImGui.PopID();
}
ImGui.PopID();
@@ -882,6 +1233,11 @@ namespace MHWNewCamera ImGui.Text("Player:");
ImGui.Text($"Pointer: {player.Instance:x}");
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);
if (ImGui.Checkbox("Disable Collision", ref disableCollision))
{
if (disableCollision)
@@ -1018,11 +1374,6 @@ namespace MHWNewCamera player.Rotation.X = 0.0f;
player.Rotation.Z = 0.0f;
}
- Vector3 forward;
- forward.X = player.Forward.X;
- forward.Y = player.Forward.Y;
- forward.Z = player.Forward.Z;
- ImGui.DragFloat3("Forward", ref forward, 0.0f);
ActionInfo currentActionInfo = player.ActionController.CurrentAction;
SharpPluginLoader.Core.Actions.Action? currentAction = null;
if (currentActionInfo.ActionSet >= 0 && currentActionInfo.ActionSet <= 3)
@@ -1036,7 +1387,7 @@ namespace MHWNewCamera AnimationLayerComponent? animationLayer = player.AnimationLayer;
AnimationId currentAnimation = player.CurrentAnimation;
ImGui.Text("Action/Animation:");
- ImGui.Text($" Current: {currentAction}, {currentAnimation}");
+ ImGui.Text($" Current: {currentAction} {currentActionInfo}, {currentAnimation}");
if (animationLayer != null)
{
ImGui.Text($" Speed: {animationLayer.Speed:0.000}");
@@ -1064,21 +1415,38 @@ namespace MHWNewCamera }
ImGui.Text($"In Menu: {playerInMenu}");
*/
- ImGui.Text($"Move: {player.Move}, Fix: {player.Fix}");
+ 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($"Pointer: {sOtomo.Instance:x}");
+ ImGui.PopID();
+
+ ImGui.Separator();
+
ImGui.PushID("Pad");
ImGui.Text("Pad:");
- ImGui.Text($"Pointer: {sMhSteamController.Instance:x}");
- int PadRx = MemoryUtil.Read<int>(sMhSteamController.Instance + 0x1b0);
- int PadRy = MemoryUtil.Read<int>(sMhSteamController.Instance + 0x1b4);
- int PadLx = MemoryUtil.Read<int>(sMhSteamController.Instance + 0x1b8);
- int PadLy = MemoryUtil.Read<int>(sMhSteamController.Instance + 0x1bc);
- byte PadRz = MemoryUtil.Read<byte>(sMhSteamController.Instance + 0x1c0);
- byte PadLz = MemoryUtil.Read<byte>(sMhSteamController.Instance + 0x1c1);
+ ImGui.Text($"Pointer: {controllerAddr():x}");
+ int PadRx = MemoryUtil.Read<int>(controllerAddr() + 0x1b0);
+ int PadRy = MemoryUtil.Read<int>(controllerAddr() + 0x1b4);
+ int PadLx = MemoryUtil.Read<int>(controllerAddr() + 0x1b8);
+ int PadLy = MemoryUtil.Read<int>(controllerAddr() + 0x1bc);
+ byte PadRz = MemoryUtil.Read<byte>(controllerAddr() + 0x1c0);
+ byte PadLz = MemoryUtil.Read<byte>(controllerAddr() + 0x1c1);
ImGui.Text("Left Stick:");
ImGui.Text($" X: {PadLx}");
ImGui.Text($" Y: {PadLy}");
@@ -1087,164 +1455,77 @@ namespace MHWNewCamera ImGui.Text($" X: {PadRx}");
ImGui.Text($" Y: {PadRy}");
ImGui.Text($" R2: {PadRz}");
+ ImGui.DragFloat("+right", ref plusRight, 0.05f);
+ ImGui.DragFloat("+forward", ref plusForward, 0.05f);
ImGui.PopID();
}
ImGui.PopID();
}
- public void OnUpdate(float deltaTime)
+ private void checkUnlockMovement()
{
- if (modDisabled) return;
-
- Viewport vp = CameraSystem.MainViewport;
- Camera? camera = vp.Camera;
- if (camera == null) return;
-
- Player? player = Player.MainPlayer;
- if (player != null)
+ if (!unlockMovementHeld && Input.IsPressed(Button.R2))
{
- if (offsetPerspective && player != lastPlayer)
- {
- // Update target camera on player change.
- targetPlayerCamera = camera;
- previousFov = -1.0f;
- }
- lastPlayer = player;
- if (toggleOffsetPerspective && !offsetPerspective)
- {
- offsetPerspective = true;
- targetPlayerCamera = camera;
- previousFov = -1.0f;
- }
- else if (!toggleOffsetPerspective && offsetPerspective)
- {
- offsetPerspective = false;
- targetPlayerCamera = null;
- }
+ unlockMovementHeld = true;
}
-
- if (!modToggleDisabled && (!Input.IsPressed(Button.R3) && Input.IsDown(Button.R3)) && Input.IsPressed(Button.L2))
+ else if (unlockMovementHeld && Input.IsReleased(Button.R2))
{
- toggleFreeCamera = !toggleFreeCamera;
+ unlockMovementHeld = false;
}
-
- if (freeCamera)
+ if (unlockMovementHeld && Input.IsPressed(Button.L1))
{
- if (!unlockMovementHeld && Input.IsPressed(Button.R2))
- {
- unlockMovementHeld = true;
- }
- else if (unlockMovementHeld && Input.IsReleased(Button.R2))
- {
- unlockMovementHeld = false;
- }
-
- if (unlockMovementHeld && Input.IsPressed(Button.L1))
- {
- unlockMovementToggled = !unlockMovementToggled;
- }
-
- if (Input.IsDown(Button.R2))
+ unlockMovementToggled = !unlockMovementToggled;
+ }
+ if (Input.IsDown(Button.R2))
+ {
+ if (Input.IsDown(Button.L2))
{
- if (Input.IsDown(Button.L2))
+ if (unlockMovementHeld)
{
- if (unlockMovementHeld)
- {
- unlockMovementHeld = false;
- }
- if (unlockMovementToggled)
- {
- unlockMovementToggled = false;
- }
+ unlockMovementHeld = false;
}
- else if (Input.IsReleased(Button.L2))
+ if (unlockMovementToggled)
{
- unlockMovementHeld = true;
+ unlockMovementToggled = false;
}
}
-
- if (Input.IsDown(Button.L2) && Input.IsDown(Button.R2))
- {
- int PadLy = MemoryUtil.Read<int>(sMhSteamController.Instance + 0x1bc);
- if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0;
- double adjustedZoomSpeed = cameraZoomSpeed * (deltaTime * cameraFov);
- double Ly = PadLy / (Int16.MaxValue / adjustedZoomSpeed);
- cameraFov = Math.Clamp(cameraFov - Ly, 1.0, 179.0);
- }
- else if (!(unlockMovementHeld || unlockMovementToggled))
+ else if (Input.IsReleased(Button.L2))
{
- int PadLy = MemoryUtil.Read<int>(sMhSteamController.Instance + 0x1bc);
- if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0;
- int PadLx = MemoryUtil.Read<int>(sMhSteamController.Instance + 0x1b8);
- if (Math.Abs(PadLx) < stickDeadzone) PadLx = 0;
- double adjustedSpeed = cameraSpeed * (deltaTime * 100.0);
- double Lx = PadLx / (Int16.MaxValue / adjustedSpeed);
- double Ly = PadLy / (Int16.MaxValue / adjustedSpeed);
- Quaternion forward = getForward(camera.Position, camera.Target);
- double buttonOffset = adjustedSpeed / 2.0;
- if (Input.IsDown(Button.L2))
- {
- buttonOffset *= cameraSpeedModifier;
- Lx *= cameraSpeedModifier;
- Ly *= cameraSpeedModifier;
- forward.Y = 0.0f;
- }
- if (Input.IsDown(Button.Down))
- {
- camera.Position.Y -= (float)buttonOffset;
- }
- if (Input.IsDown(Button.Up))
- {
- camera.Position.Y += (float)buttonOffset;
- }
- if (Input.IsDown(Button.Left))
- {
- cameraRoll -= buttonOffset;
- }
- if (Input.IsDown(Button.Right))
- {
- cameraRoll += buttonOffset;
- }
- forward = Quaternion.Normalize(forward);
- Quaternion left = forward * Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(Single.DegreesToRadians(180.0f)));
- camera.Position.X += (float)(left.X * Lx);
- camera.Position.Z += (float)(left.Z * Lx);
- camera.Position.X += (float)(forward.X * Ly);
- camera.Position.Y += (float)(forward.Y * Ly);
- camera.Position.Z += (float)(forward.Z * Ly);
+ unlockMovementHeld = true;
}
- int PadRx = MemoryUtil.Read<int>(sMhSteamController.Instance + 0x1b0);
- if (Math.Abs(PadRx) < stickDeadzone) PadRx = 0;
- int PadRy = MemoryUtil.Read<int>(sMhSteamController.Instance + 0x1b4);
- if (Math.Abs(PadRy) < stickDeadzone) PadRy = 0;
- double adjustedSensitivity = cameraSensitivity * (deltaTime * cameraFov);
- double Rx = PadRx / (Int16.MaxValue / adjustedSensitivity);
- double Ry = PadRy / (Int16.MaxValue / adjustedSensitivity);
- cameraYaw += Rx;
- cameraPitch = Math.Clamp(cameraPitch + Ry, -cameraPitchLimit, cameraPitchLimit);
- // This is the same value the game uses for the player camera. Oddly the in-game view mode
- // uses 1.0 like I did here before, which is really bad for precision.
- double dist = 700.0 - cameraForward;
- camera.Target.X = camera.Position.X + (float)(dist * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Cos(Double.DegreesToRadians(cameraYaw)));
- camera.Target.Y = camera.Position.Y + (float)(dist * Math.Sin(Double.DegreesToRadians(cameraPitch)));
- camera.Target.Z = camera.Position.Z + (float)(dist * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Sin(Double.DegreesToRadians(cameraYaw)));
- camera.FieldOfView = (float)cameraFov;
- if (!toggleFreeCamera)
+ }
+ }
+
+ private void checkPlayerChange()
+ {
+ Player? player = Player.MainPlayer;
+ if (player != lastPlayer)
+ {
+ pCamera = null;
+ lastPlayer = player;
+ }
+ }
+
+ public void OnUpdate(float deltaTime)
+ {
+ if (disableMod) return;
+
+ // Consider that pCamera could become an invalid pointer.
+ checkPlayerChange();
+
+ if (enableCombo && freeCameraCombo != null)
+ {
+ Button b1 = freeCameraCombo[0];
+ Button b2 = freeCameraCombo[1];
+ if ((!Input.IsPressed(b1) && Input.IsDown(b1)) && Input.IsPressed(b2))
{
- freeCamera = false;
- camera.Move = true;
- if (preZoomFov != null)
- {
- cameraFov = (double)preZoomFov;
- preZoomFov = null;
- }
- if (preZoomRoll != null)
- {
- cameraRoll = (double)preZoomRoll;
- preZoomRoll = null;
- }
+ enableFreeCamera = !enableFreeCamera;
}
- maybeSetFovForCulling(vp, camera);
+ }
+
+ if (freeCamera)
+ {
+ checkUnlockMovement();
}
}
}
|