From b4b75cc22d5799a4110e78543e338d850c877384 Mon Sep 17 00:00:00 2001 From: Matuno Date: Sat, 2 May 2026 02:48:04 +0200 Subject: [PATCH] feat: migrate to API 15 and implement ViewMatrix targeting - Updated to Dalamud API 15 and .NET 10. - Resolved service warnings in Plugin.cs by properly initializing IFramework and IPluginLog. - Refactored targeting to use engine-native ViewMatrix projection. The previous targeting logic relied on the mini-map cone rotation (AreaMapNumberArray), which was offset from the actual scene camera and required fragile 'magic number' corrections (+135 deg). The new system projects targets directly into camera-space using the game's internal ViewMatrix. This provides 100% accurate horizontal targeting by checking the target's position relative to the camera's local axes, eliminating all world-space rotation offsets and coordinate mapping issues. --- BetterTargetingSystem/Plugin.cs | 4 ++-- BetterTargetingSystem/Utils.cs | 38 +++++++++++++++++---------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/BetterTargetingSystem/Plugin.cs b/BetterTargetingSystem/Plugin.cs index eebbee6..14f635e 100644 --- a/BetterTargetingSystem/Plugin.cs +++ b/BetterTargetingSystem/Plugin.cs @@ -37,8 +37,8 @@ public sealed unsafe class Plugin : IDalamudPlugin [PluginService] public static IDalamudPluginInterface PluginInterface { get; private set; } = null!; [PluginService] public static ICommandManager CommandManager { get; private set; } = null!; - [PluginService] public static IFramework Framework { get; set; } - [PluginService] public static IPluginLog PluginLog { get; set; } + [PluginService] public static IFramework Framework { get; set; } = null!; + [PluginService] public static IPluginLog PluginLog { get; set; } = null!; public Configuration Configuration { get; init; } [PluginService] public static IClientState Client { get; set; } = null!; diff --git a/BetterTargetingSystem/Utils.cs b/BetterTargetingSystem/Utils.cs index d1888d6..6b8f742 100644 --- a/BetterTargetingSystem/Utils.cs +++ b/BetterTargetingSystem/Utils.cs @@ -37,32 +37,34 @@ internal static float DistanceBetweenObjects(Vector3 sourcePos, Vector3 targetPo return distance; } + + internal unsafe static float GetCameraRotation() { - // Gives the camera rotation in deg between -180 and 180 - var cameraRotation = AreaMapNumberArray.Instance()->ConeRotation; + var cameraManager = CameraManager.Instance(); + if (cameraManager == null || cameraManager->CurrentCamera == null) + return 0; - // Transform the [-180,180] rotation to rad with same 0 as a GameObject rotation - // There might be an easier way to do that, but geometry and I aren't friends - var sign = Math.Sign(cameraRotation) == -1 ? -1 : 1; - var rotation = (float)((Math.Abs(cameraRotation * (Math.PI / 180)) - Math.PI) * sign); - - // DO NOT ASK WHY. +135 - return rotation; + // Extract horizontal rotation from ViewMatrix + var matrix = cameraManager->CurrentCamera->ViewMatrix; + return (float)Math.Atan2(matrix.M31, matrix.M33); } - internal static bool IsInFrontOfCamera(DalamudGameObject obj, float maxAngle) + internal unsafe static bool IsInFrontOfCamera(DalamudGameObject obj, float maxAngle) { - // This is still relying on camera orientation but the cone is from the player's position - if (Plugin.ObjectTable.LocalPlayer == null) + var cameraManager = CameraManager.Instance(); + if (cameraManager == null || cameraManager->CurrentCamera == null || Plugin.ObjectTable.LocalPlayer == null) return false; - var rotation = GetCameraRotation(); - var faceVec = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)); - - var dir = obj.Position - Plugin.ObjectTable.LocalPlayer.Position; - var dirVec = new Vector2(dir.Z, dir.X); - var angle = Math.Acos(Vector2.Dot(dirVec, faceVec) / dirVec.Length() / faceVec.Length()); + var matrix = cameraManager->CurrentCamera->ViewMatrix; + var p = obj.Position; + + // Transform world position to camera-space position (Projection) + float camX = matrix.M11 * p.X + matrix.M21 * p.Y + matrix.M31 * p.Z + matrix.M41; + float camZ = matrix.M13 * p.X + matrix.M23 * p.Y + matrix.M33 * p.Z + matrix.M43; + + // Horizontal angle in camera-space: atan2(X, -Z) + var angle = Math.Abs(Math.Atan2(camX, -camZ)); return angle <= Math.PI * maxAngle / 360; }