diff --git a/src/AcDream.Core/Selection/WorldPicker.cs b/src/AcDream.Core/Selection/WorldPicker.cs index 1c49b70..6074373 100644 --- a/src/AcDream.Core/Selection/WorldPicker.cs +++ b/src/AcDream.Core/Selection/WorldPicker.cs @@ -57,7 +57,7 @@ public static class WorldPicker /// /// Ray-sphere intersection against each candidate's - /// using a fixed 5m sphere radius. Returns the + /// using a fixed 0.7 m sphere radius. Returns the /// of the closest hit within , or null on miss. /// /// @@ -68,10 +68,22 @@ public static class WorldPicker /// of world meters. /// /// + /// /// Entities with ServerGuid == 0 (atlas-tier scenery, dat-hydrated /// statics) are skipped — they have no server-side identity and can't be /// the target of a Use packet. The player's own guid is skipped via /// . + /// + /// + /// Radius history (Issue #59). Started at 5 m as a forgiving default; + /// in practice this over-picked massively — any cursor anywhere near an + /// NPC selected the NPC instead of a nearby item, and "click empty + /// ground to deselect" was nearly impossible. Tightened to 0.7 m on + /// 2026-05-15 to roughly match the actual hitbox radius of humanoids + + /// most items. A future refinement is per-itemType radius (smaller for + /// tapers, bigger for shop chests) or priority sorting (items beat + /// NPCs at equal hit-distance). + /// /// public static uint? Pick( Vector3 origin, Vector3 direction, @@ -79,7 +91,7 @@ public static class WorldPicker uint skipServerGuid, float maxDistance = 50f) { - const float Radius = 5f; + const float Radius = 0.7f; const float Radius2 = Radius * Radius; if (direction.LengthSquared() < 1e-10f) return null;