using ImGuiNET; using System.Numerics; using SharpPluginLoader.Core; using SharpPluginLoader.Core.Entities; using SharpPluginLoader.Core.IO; using SharpPluginLoader.Core.View; using SharpPluginLoader.Core.Memory; using SharpPluginLoader.Core.MtTypes; using SharpPluginLoader.Core.Actions; using SharpPluginLoader.Core.Configuration; namespace MHWNewCamera { public unsafe class Plugin : IPlugin { public string Name => "MHW New Camera"; public string Author => "pizza"; private const float DEFAULT_FOV = 60.0f; private bool keyboardEnabled; private Config.Binds keyboardBinds; private float cameraSpeed; private float cameraKeySpeed; private float cameraSpeedModifier; private float cameraSensitivity; private int stickDeadzone; private float cameraPitchLimit; private float cameraFov = DEFAULT_FOV; private float cameraForward = 0.0f; private float cameraLeft = 0.0f; private float cameraXOffset = 0.0f; private float cameraYOffset = 0.0f; private float cameraZOffset = 0.0f; private float cameraPitch = 0.0f; private float cameraYaw = 0.0f; private float cameraRoll = 0.0f; private bool freeCamera = false; private bool toggleFreeCamera = false; private bool unlockMovementHeld = false; private bool unlockMovementToggled = false; private bool offsetPerspective = false; private bool toggleOffsetPerspective = false; private Camera? targetCamera = null; private Player? lastPlayer = null; private float previousFov = -1.0f; private bool decreasingFov = false; private bool changeAfterOpenMap = true; private bool changeAfterGetUp = true; private bool resetFovInView = false; private delegate void CalculateCameraDelegate(nint unknownPtr); private Hook? calculateCameraHook; private delegate void CalculateViewDelegate(nint unknownPtr); private Hook? calculateViewHook; private delegate float CalculateMovementDelegate(int stickValue); private Hook? calculateMovementHook; private bool disableCollision = false; private bool disableExtraCollision = false; private Patch disableXCollision; private Patch disableYCollision; private Patch disableSecondaryYCollision; private Patch disableZCollision; private Patch disableExtraYCollision; private string typedPresetName = ""; private static readonly MtObject sMhSteamController = SingletonManager.GetSingleton("sMhSteamController")!; public void OnLoad() { Config config = ConfigManager.GetConfig(this); keyboardEnabled = config.KeyboardEnabled; keyboardBinds = config.KeyboardBinds; Config.Settings settings = config.CameraSettings; cameraSpeed = settings.CameraSpeed; cameraKeySpeed = settings.CameraKeySpeed; cameraSpeedModifier = settings.CameraSpeedModifier; cameraSensitivity = settings.CameraSensitivity; stickDeadzone = settings.StickDeadzone; cameraPitchLimit = settings.CameraPitchLimit; toggleOffsetPerspective = config.PerspectiveCameraEnabled; if (config.Selected != "") { Config.Preset preset = config.Presets[config.Selected]; cameraFov = preset.FOV; cameraForward = preset.Forward; cameraLeft = preset.Left; cameraYOffset = preset.Up; cameraRoll = preset.Roll; } ConfigManager.SaveConfig(this); // Hook where we can adjust the camera position. calculateCameraHook = Hook.Create(0x141fa5380, CalculateCameraHook); //calculateCameraHook = Hook.Create(0x142290620, CalculateCameraHook); // Hook where we can directly modify the view matrix. calculateViewHook = Hook.Create(0x14228eb60, CalculateViewHook); //calculateViewHook2 = Hook.Create(0x14228fb80, CalculateViewHook2); // Hook where we can adjust the analog stick value the game uses. calculateMovementHook = Hook.Create(0x142107cb0, CalculateMovementHook); unchecked { // Noop collision checks. disableXCollision = new Patch((nint)0x141c001b5, [0x90, 0x90, 0x90, 0x90]); disableYCollision = new Patch((nint)0x141c001c3, [0x90, 0x90, 0x90, 0x90, 0x90]); disableSecondaryYCollision = new Patch((nint)0x141c000d2, [0x90, 0x90, 0x90, 0x90, 0x90]); disableZCollision = new Patch((nint)0x141c001d2, [0x90, 0x90, 0x90, 0x90, 0x90]); disableExtraYCollision = new Patch((nint)0x141bfff90, [0x90, 0x90, 0x90, 0x90, 0x90]); } } private static bool assumeInQuestBoard(float fov) { return fov == 20.000038f || fov == 20.017189f || fov == 20.00004f; } private bool assumeInAnimation(Viewport vp, Camera camera) { return vp.Camera != null && vp.Camera.Instance != camera.Instance && vp.Camera.FarClip == 4000000 && vp.Camera.Fix; } private bool assumeInOpenMapAnimation(float fov) { // 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, press A at departure location). // This is a really rough hack but better than nothing for now. if (fov == 50.942066f) { if (!changeAfterOpenMap) return true; if (Input.IsReleased(Button.Share) || Input.IsPressed(Button.Cross) || Input.IsReleased(Key.M)) { changeAfterOpenMap = false; return true; } } if (!changeAfterOpenMap) { changeAfterOpenMap = true; } return false; } private bool assumeInCanteen(float fov, float previousFov) { // Same idea as assumeInOpenMapAnimation(). if (fov == 50.0f) { if (!changeAfterGetUp) return true; // fov = 50.0 is too common, assume the FOV will always be greater than 51.0 // before sitting at the canteen. Also assuming that if FOV is 50.0 otherwise // that previousFov will be something closer to 50.0. if (previousFov >= 51.0f) { if (Input.IsPressed(Button.Cross) || (Input.IsDown(Button.Triangle) || Input.IsReleased(Button.Triangle))) { changeAfterGetUp = false; return true; } } } if (!changeAfterGetUp) { changeAfterGetUp = true; } return false; } 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; camera.FieldOfView = cameraFov; } private void adjustForCameraRoll(Viewport vp, Camera camera) { camera.AspectRatio = vp.Region.Height / (float)vp.Region.Width; // Increase FOV for culling then set it back in CalculateViewHook. camera.FieldOfView *= 2.0f; resetFovInView = true; } 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 void CalculateCameraHook(nint unknownPtr) { calculateCameraHook!.Original(unknownPtr); Viewport vp = CameraSystem.MainViewport; Camera? camera = vp.Camera; if (offsetPerspective && !freeCamera) { camera = targetCamera; if (camera == null) return; decreasingFov = previousFov >= 0.0f && previousFov > camera.FieldOfView; bool applyPerspective = camera.Fix && camera.Move; applyPerspective &= !assumeInQuestBoard(camera.FieldOfView); applyPerspective &= !(assumeInAnimation(vp, camera) && decreasingFov); applyPerspective &= !assumeInOpenMapAnimation(camera.FieldOfView); applyPerspective &= !assumeInCanteen(camera.FieldOfView, previousFov); previousFov = camera.FieldOfView; if (applyPerspective) { Quaternion forward = Quaternion.Normalize(getForward(camera.Position, camera.Target)); setPerspective(camera, camera.Position, forward); if (cameraRoll != 0.0f) adjustForCameraRoll(vp, camera); } } else if (camera != null) { // Track this just for the debug display. previousFov = camera.FieldOfView; } if (camera != null && toggleFreeCamera && !freeCamera) { freeCamera = true; camera.Move = false; // Camera position could have changed. Quaternion forward = Quaternion.Normalize(getForward(camera.Position, camera.Target)); cameraPitch = Single.RadiansToDegrees((float)Math.Asin(forward.Y)); cameraYaw = Single.RadiansToDegrees((float)Math.Atan2(forward.Z, forward.X)); } } private void CalculateViewHook(nint unknownPtr) { Viewport vp = CameraSystem.MainViewport; bool updateView = freeCamera || offsetPerspective; if (resetFovInView) { if (updateView) { Camera? camera; if ((camera = freeCamera ? vp.Camera : targetCamera) != null) { camera.FieldOfView = cameraFov; } } resetFovInView = false; } calculateViewHook!.Original(unknownPtr); if (updateView) { vp.ViewMatrix *= Matrix4x4.CreateRotationZ(Single.DegreesToRadians(cameraRoll)); } } private float CalculateMovementHook(int stickValue) { if (freeCamera && !(unlockMovementHeld || unlockMovementToggled)) { stickValue = 0; } return calculateMovementHook!.Original(stickValue); } private static void drawVector(Vector3 v, String name) { ImGui.Text($" {name}:"); ImGui.Text($" X: {v.X:0.00}"); ImGui.Text($" Y: {v.Y:0.00}"); ImGui.Text($" Z: {v.Z:0.00}"); } /* private static void drawQuaternion(MtQuaternion q, String name) { ImGui.Text($" {name}:"); ImGui.Text($" X: {q.X:0.00}"); ImGui.Text($" Y: {q.Y:0.00}"); ImGui.Text($" Z: {q.Z:0.00}"); ImGui.Text($" W: {q.W:0.00}"); } */ private static void inputVector(ref Vector3 v, String name, String key) { ImGui.PushID(name + key); ImGui.Text($" {name}:"); float x = v.X; float y = v.Y; float z = v.Z; if (ImGui.InputFloat($"X", ref x, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue)) { v.X = x; } if (ImGui.InputFloat($"Y", ref y, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue)) { v.Y = y; } if (ImGui.InputFloat($"Z", ref z, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue)) { v.Z = z; } ImGui.PopID(); } private static void inputQuaternion(ref MtQuaternion q, String name, String key) { ImGui.PushID(name + key); ImGui.Text($" {name}:"); ImGui.SliderFloat($"X", ref q.X, -1.0f, 1.0f); ImGui.SliderFloat($"Y", ref q.Y, -1.0f, 1.0f); ImGui.SliderFloat($"Z", ref q.Z, -1.0f, 1.0f); ImGui.SliderFloat($"W", ref q.W, -1.0f, 1.0f); ImGui.PopID(); } public void OnImGuiRender() { Config config = ConfigManager.GetConfig(this); ImGui.Checkbox("Enable Free Camera", ref toggleFreeCamera); if (toggleFreeCamera) { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } if (ImGui.Checkbox("Enable Perspective Camera", ref toggleOffsetPerspective)) { // Take the oposite because it's yet to be toggled. config.PerspectiveCameraEnabled = !offsetPerspective; ConfigManager.SaveConfig(this); } if (toggleFreeCamera) { ImGui.PopStyleVar(); } ImGui.PushID("Perspective"); ImGui.SliderFloat("Field of View", ref cameraFov, 1.0f, 180.0f); ImGui.SliderFloat("Forward", ref cameraForward, -360.0f, 360.0f); ImGui.SliderFloat("Left", ref cameraLeft, -360.0f, 360.0f); ImGui.SliderFloat("Up", ref cameraYOffset, -360.0f, 360.0f); if (ImGui.Button("Default")) { cameraFov = DEFAULT_FOV; cameraForward = 0.0f; cameraLeft = 0.0f; cameraXOffset = 0.0f; cameraYOffset = 0.0f; cameraZOffset = 0.0f; config.Selected = ""; ConfigManager.SaveConfig(this); } ImGui.SameLine(); if (ImGui.Button("Save")) { String name = typedPresetName; if (name != "") { Config.Preset preset = new Config.Preset(); preset.FOV = cameraFov; preset.Forward = cameraForward; preset.Left = cameraLeft; preset.Up = cameraYOffset; preset.Roll = cameraRoll; if (config.Presets.ContainsKey(name)) { config.Presets[name] = preset; } else { config.Presets.Add(name, preset); } config.Selected = name; ConfigManager.SaveConfig(this); } } ImGui.SameLine(); ImGui.PushItemWidth(170); ImGui.InputText("##Preset Name", ref typedPresetName, 99); ImGui.SameLine(); if (ImGui.BeginCombo("##Preset", config.Selected)) { Dictionary.KeyCollection presetKeys = config.Presets.Keys; for (int i = 0; i < presetKeys.Count; i++) { string key = presetKeys.ElementAt(i); bool isSelected = key == config.Selected; if (ImGui.Selectable(key, isSelected)) { config.Selected = key; ConfigManager.SaveConfig(this); Config.Preset preset = config.Presets[config.Selected]; cameraFov = preset.FOV; cameraForward = preset.Forward; cameraLeft = preset.Left; cameraYOffset = preset.Up; cameraRoll = preset.Roll; } if (isSelected) { ImGui.SetItemDefaultFocus(); } } ImGui.EndCombo(); } ImGui.PopItemWidth(); ImGui.PopID(); ImGui.PushID("Settings"); ImGui.SliderFloat("Camera Speed", ref cameraSpeed, 0.1f, 10.0f); if (ImGui.BeginItemTooltip()) { ImGui.Text("Movement speed in freecam."); ImGui.EndTooltip(); } ImGui.SliderFloat("Button Speed", ref cameraKeySpeed, 0.01f, 3.0f); if (ImGui.BeginItemTooltip()) { ImGui.Text("Rate of camera adjustment buttons/keybinds."); ImGui.EndTooltip(); } ImGui.SliderFloat("Speed Modifier", ref cameraSpeedModifier, 0.1f, 10.0f); if (ImGui.BeginItemTooltip()) { ImGui.Text("Value to multiply speed by when L2 is held."); ImGui.EndTooltip(); } ImGui.SliderFloat("Camera Sensitivity", ref cameraSensitivity, 0.005f, 1.00f); if (ImGui.BeginItemTooltip()) { ImGui.Text("Camera look sensitivity in freecam."); ImGui.EndTooltip(); } ImGui.InputInt("Stick Deadzone", ref stickDeadzone, 10); if (ImGui.Button("Default")) { cameraSpeed = Config.Settings.DEFAULT_SPEED; cameraKeySpeed = Config.Settings.DEFAULT_KEY_SPEED; cameraSpeedModifier = Config.Settings.DEFAULT_SPEED_MODIFIER; cameraSensitivity = Config.Settings.DEFAULT_SENSITIVITY; stickDeadzone = Config.Settings.DEFAULT_DEADZONE; cameraPitchLimit = Config.Settings.DEFAULT_PITCH_LIMIT; } ImGui.SameLine(); if (ImGui.Button("Reset")) { Config.Settings settings = config.CameraSettings; cameraSpeed = settings.CameraSpeed; cameraKeySpeed = settings.CameraKeySpeed; cameraSpeedModifier = settings.CameraSpeedModifier; cameraSensitivity = settings.CameraSensitivity; stickDeadzone = settings.StickDeadzone; cameraPitchLimit = settings.CameraPitchLimit; } ImGui.SameLine(); if (ImGui.Button("Save")) { Config.Settings settings = config.CameraSettings; settings.CameraSpeed = cameraSpeed; settings.CameraKeySpeed = cameraKeySpeed; settings.CameraSpeedModifier = cameraSpeedModifier; settings.CameraSensitivity = cameraSensitivity; settings.StickDeadzone = stickDeadzone; settings.CameraPitchLimit = cameraPitchLimit; config.CameraSettings = settings; ConfigManager.SaveConfig(this); } ImGui.PopID(); if (ImGui.CollapsingHeader("DEBUG")) { ImGui.Text($"Camera/Viewport:"); Viewport vp; for (int i = 0; i < 1; 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}"); if (vp.Camera != null) { ImGui.InputFloat("X Offset", ref cameraXOffset); ImGui.InputFloat("Y Offset", ref cameraYOffset); ImGui.InputFloat("Z Offset", ref cameraZOffset); ImGui.Text($" Camera Pointer: {vp.Camera.Instance:x}"); ImGui.InputFloat("FOV", ref vp.Camera.FieldOfView); 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 vp.Camera.AspectRatio); ImGui.InputFloat("Far Clip", ref vp.Camera.FarClip); ImGui.InputFloat("Near Clip", ref vp.Camera.NearClip); inputVector(ref vp.Camera.Position, "Position", "cam"); inputVector(ref vp.Camera.Target, "Target", "cam"); drawVector(vp.Camera.Up, "Up"); ImGui.Text(" Rotation:"); float pitch = cameraPitch; if (ImGui.InputFloat("Pitch", ref pitch, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue)) { cameraPitch = pitch; } float yaw = cameraYaw; if (ImGui.InputFloat("Yaw", ref yaw, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue)) { cameraYaw = yaw; } float roll = cameraRoll; if (ImGui.InputFloat("Roll", ref roll, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue)) { cameraRoll = roll; } float pitchLimit = cameraPitchLimit; if (ImGui.InputFloat("Pitch Limit", ref pitchLimit, 0.0f, 0.0f, null, ImGuiInputTextFlags.EnterReturnsTrue)) { cameraPitchLimit = pitchLimit; } ImGui.Text($" Move: {vp.Camera.Move}"); ImGui.Text($" Fix: {vp.Camera.Fix}"); } } ImGui.Separator(); ImGui.PushID("Pad"); ImGui.Text($"Pad:"); ImGui.Text($" Pointer: {sMhSteamController.Instance:x}"); int PadRx = MemoryUtil.Read(sMhSteamController.Instance + 0x1b0); int PadRy = MemoryUtil.Read(sMhSteamController.Instance + 0x1b4); int PadLx = MemoryUtil.Read(sMhSteamController.Instance + 0x1b8); int PadLy = MemoryUtil.Read(sMhSteamController.Instance + 0x1bc); byte PadRz = MemoryUtil.Read(sMhSteamController.Instance + 0x1c0); byte PadLz = MemoryUtil.Read(sMhSteamController.Instance + 0x1c1); ImGui.Text(" Left Stick:"); ImGui.Text($" X: {PadLx}"); ImGui.Text($" Y: {PadLy}"); ImGui.Text($" L2: {PadLz}"); ImGui.Text(" Right Stick:"); ImGui.Text($" X: {PadRx}"); ImGui.Text($" Y: {PadRy}"); ImGui.Text($" R2: {PadRz}"); ImGui.PopID(); ImGui.Separator(); ImGui.Text($"Player:"); Player? player = Player.MainPlayer; if (player != null) { ImGui.PushID("Player"); ImGui.Text($" Pointer: {player.Instance:x}"); inputVector(ref player.Position, "Position", "player"); if (ImGui.Checkbox("Disable Collision", ref disableCollision)) { if (disableCollision) { disableXCollision.Enable(); disableYCollision.Enable(); disableSecondaryYCollision.Enable(); disableZCollision.Enable(); } else { disableXCollision.Disable(); disableYCollision.Disable(); disableSecondaryYCollision.Disable(); disableZCollision.Disable(); } } if (ImGui.Checkbox("Disable Extra Y Collision", ref disableExtraCollision)) { if (disableExtraCollision) { disableExtraYCollision.Enable(); } else { disableExtraYCollision.Disable(); } } if (ImGui.BeginItemTooltip()) { ImGui.Text("This will make your legs goofy, but it's needed to get on top of some things."); ImGui.EndTooltip(); } inputQuaternion(ref player.Rotation, "Rotation", "player"); if (ImGui.Button("Reset")) { player.Rotation.X = 0.0f; player.Rotation.Z = 0.0f; } drawVector(player.Forward, "Forward"); ActionController actionController = player.ActionController; ImGui.Text($" Action: {actionController.CurrentAction} Animation: {player.CurrentAnimation} Frame: {player.AnimationLayer!.CurrentFrame:0.000}"); // https://github.com/HunterPie/HunterPie/blob/fa73f81ed0cdc921a6cf63f96c0fcff3688d88c2/HunterPie.Integrations/Datasources/MonsterHunterWorld/Entity/Game/MHWGame.cs#L74 bool playerInMenu = false; nint offset = MemoryUtil.Read(0x1451c4640); if (offset != 0) { offset += 0x13FD0; offset = MemoryUtil.Read(offset); if (offset != 0) { offset += 0xB734; playerInMenu = MemoryUtil.Read(offset) == 1; } } ImGui.Text($" In Menu: {playerInMenu}"); ImGui.Text($" Move: {player.Move}"); ImGui.Text($" Fix: {player.Fix}"); ImGui.PopID(); } } } public void OnUpdate(float deltaTime) { float adjustedKeySpeed = cameraKeySpeed * deltaTime * 1000.0f; float adjustedSpeed = cameraSpeed * deltaTime * 1000.0f; float adjustedSensitivity = cameraSensitivity * deltaTime * 1000.0f; if (keyboardEnabled) { if (Input.IsPressed(keyboardBinds.ToggleFreeCamera)) { toggleFreeCamera = !toggleFreeCamera; } if (Input.IsPressed(keyboardBinds.TogglePerspectiveCamera)) { toggleOffsetPerspective = !toggleOffsetPerspective; } /* if (Input.IsDown(keyboardBinds.IncreaseSpeed)) { cameraSpeed += 0.5f * deltaTime; } if (Input.IsDown(keyboardBinds.DecreaseSpeed)) { cameraSpeed -= 0.5f * deltaTime; if (cameraSpeed < 0.1f) cameraSpeed = 0.1f; } if (Input.IsDown(keyboardBinds.IncreaseFOV)) { cameraFov += adjustedKeySpeed / 2.0f; } if (Input.IsDown(keyboardBinds.DecreaseFOV)) { cameraFov -= adjustedKeySpeed / 2.0f; } if (Input.IsDown(keyboardBinds.Forward)) { cameraForward += adjustedKeySpeed; } if (Input.IsDown(keyboardBinds.Backward)) { cameraForward -= adjustedKeySpeed; } if (Input.IsDown(keyboardBinds.Left)) { cameraLeft += adjustedKeySpeed; } if (Input.IsDown(keyboardBinds.Right)) { cameraLeft -= adjustedKeySpeed; } if (Input.IsDown(keyboardBinds.Up)) { cameraYOffset += adjustedKeySpeed; } if (Input.IsDown(keyboardBinds.Down)) { cameraYOffset -= adjustedKeySpeed; } */ } Viewport vp = CameraSystem.MainViewport; Camera? camera = vp.Camera; if (camera == null) return; Player? player = Player.MainPlayer; if (player != null) { if (offsetPerspective && player != lastPlayer) { // Update target camera on player change. targetCamera = camera; previousFov = -1.0f; } lastPlayer = player; if (toggleOffsetPerspective && !offsetPerspective) { offsetPerspective = true; targetCamera = camera; previousFov = -1.0f; } else if (!toggleOffsetPerspective && offsetPerspective) { offsetPerspective = false; targetCamera = null; } } if (Input.IsDown(Button.L2) && Input.IsPressed(Button.L1)) { toggleFreeCamera = !toggleFreeCamera; } if (!toggleFreeCamera && freeCamera) { freeCamera = false; camera.Move = true; } if (freeCamera) { if (player != null) { if (!unlockMovementHeld && Input.IsPressed(Button.L1)) { unlockMovementToggled = !unlockMovementToggled; } if (!unlockMovementToggled) { if (Input.IsPressed(Button.R2)) { unlockMovementHeld = true; } if (Input.IsReleased(Button.R2)) { unlockMovementHeld = false; } } } if (!(unlockMovementHeld || unlockMovementToggled)) { int PadLx = MemoryUtil.Read(sMhSteamController.Instance + 0x1b8); if (Math.Abs(PadLx) < stickDeadzone) PadLx = 0; int PadLy = MemoryUtil.Read(sMhSteamController.Instance + 0x1bc); if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0; float Lx = PadLx / (Int16.MaxValue / adjustedSpeed); float Ly = PadLy / (Int16.MaxValue / adjustedSpeed); Quaternion forward = getForward(camera.Position, camera.Target); if (Input.IsDown(Button.L2)) { if (Input.IsDown(Button.Down)) { camera.Position.Y -= adjustedKeySpeed * cameraSpeedModifier; } if (Input.IsDown(Button.Up)) { camera.Position.Y += adjustedKeySpeed * cameraSpeedModifier; } Lx *= cameraSpeedModifier; Ly *= cameraSpeedModifier; forward.Y = 0.0f; } forward = Quaternion.Normalize(forward); Quaternion left = forward * Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(Single.DegreesToRadians(180.0f))); camera.Position.X += left.X * Lx; camera.Position.Z += left.Z * Lx; camera.Position.X += forward.X * Ly; camera.Position.Y += forward.Y * Ly; camera.Position.Z += forward.Z * Ly; } int PadRx = MemoryUtil.Read(sMhSteamController.Instance + 0x1b0); if (Math.Abs(PadRx) < stickDeadzone) PadRx = 0; int PadRy = MemoryUtil.Read(sMhSteamController.Instance + 0x1b4); if (Math.Abs(PadRy) < stickDeadzone) PadRy = 0; float Rx = PadRx / (Int16.MaxValue / adjustedSensitivity); float Ry = PadRy / (Int16.MaxValue / adjustedSensitivity); cameraYaw += Rx; cameraPitch += Ry; float cap = cameraPitchLimit; if (cameraPitch > cap) cameraPitch = cap; else if (cameraPitch < -cap) cameraPitch = -cap; camera.Target.X = camera.Position.X + ((float)Math.Cos(Single.DegreesToRadians(cameraPitch)) * (float)Math.Cos(Single.DegreesToRadians(cameraYaw))); camera.Target.Y = camera.Position.Y + (float)Math.Sin(Single.DegreesToRadians(cameraPitch)); camera.Target.Z = camera.Position.Z + ((float)Math.Cos(Single.DegreesToRadians(cameraPitch)) * (float)Math.Sin(Single.DegreesToRadians(cameraYaw))); camera.FieldOfView = cameraFov; if (cameraRoll != 0.0f) adjustForCameraRoll(vp, camera); } } } }