Asset Dump
This commit is contained in:
@@ -125,9 +125,11 @@ namespace ProjectM.Simulation
|
||||
else
|
||||
rawAim = math.normalize(rawAim);
|
||||
|
||||
// Client fires along raw aim; only the server applies the auto-target assist cone.
|
||||
// Client fires along raw aim. Only the server applies the auto-target assist cone, and only for
|
||||
// GAMEPAD shots (precise mouse aim is left exact per the active input scheme).
|
||||
float2 dir = rawAim;
|
||||
if (isServer && eff.ValueRO.AutoTargetRange > 0f)
|
||||
if (isServer && eff.ValueRO.AutoTargetRange > 0f
|
||||
&& applied.InternalInput.Scheme == InputSchemeId.Gamepad)
|
||||
{
|
||||
dir = AutoTarget.Resolve(
|
||||
xform.ValueRO.Position,
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace ProjectM.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// Pure, deterministic, Burst-safe helpers for turning a screen-cursor camera ray into a planar (XZ)
|
||||
/// aim direction (and the ground point it targets) for the top-down player. Isolated from the managed
|
||||
/// <c>Camera</c> so the projection is unit-testable without a render context (mirrors
|
||||
/// <see cref="AutoTarget"/> / <c>CharacterControlMath</c> / <c>BaseGridMath</c>). Used client-side by the
|
||||
/// input gather (facing direction) and the aim-reticle presentation (the world ground point), but kept
|
||||
/// here in Simulation alongside the other pure combat/movement math.
|
||||
/// </summary>
|
||||
public static class AimMath
|
||||
{
|
||||
/// <summary>
|
||||
/// Intersects a camera ray with the horizontal plane at <paramref name="planeY"/>. Returns false (and
|
||||
/// <paramref name="hit"/> = default) when the ray is parallel to / points away from the plane (cursor
|
||||
/// above the horizon); otherwise <paramref name="hit"/> is the world-space intersection point.
|
||||
/// </summary>
|
||||
/// <param name="rayOrigin">Camera ray origin (world space).</param>
|
||||
/// <param name="rayDir">Camera ray direction (need not be normalized).</param>
|
||||
/// <param name="planeY">World Y of the aim plane (the player's movement plane).</param>
|
||||
/// <param name="hit">The world-space ground intersection point, when this returns true.</param>
|
||||
public static bool TryGroundHit(float3 rayOrigin, float3 rayDir, float planeY, out float3 hit)
|
||||
{
|
||||
hit = default;
|
||||
// Solve rayOrigin.y + t * rayDir.y == planeY. A near-zero rayDir.y means the ray runs parallel.
|
||||
float denom = rayDir.y;
|
||||
if (math.abs(denom) < 1e-6f)
|
||||
return false;
|
||||
float t = (planeY - rayOrigin.y) / denom;
|
||||
if (t < 0f)
|
||||
return false; // intersection behind the ray origin (cursor above the horizon line)
|
||||
hit = rayOrigin + rayDir * t;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalized planar aim direction (world XZ mapped to <c>float2(x, y)</c>) from
|
||||
/// <paramref name="playerPos"/> toward the cursor's ground-projection point. Returns
|
||||
/// <paramref name="fallback"/> when the ray misses the plane, OR the hit lies within
|
||||
/// <paramref name="deadZoneRadius"/> of the player (too close to define a stable heading), so the
|
||||
/// caller holds its previous aim instead of snapping or spinning when the cursor is over the character.
|
||||
/// </summary>
|
||||
/// <param name="rayOrigin">Camera ray origin (world space).</param>
|
||||
/// <param name="rayDir">Camera ray direction (need not be normalized).</param>
|
||||
/// <param name="playerPos">Player world position; only XZ is used for the heading.</param>
|
||||
/// <param name="planeY">World Y of the aim plane.</param>
|
||||
/// <param name="fallback">Direction returned when there is no valid hit (e.g. the previous aim).</param>
|
||||
/// <param name="deadZoneRadius">
|
||||
/// World radius around the player inside which facing is held (no update). 0 keeps only the tiny
|
||||
/// epsilon guard against an exactly-coincident hit (the original behaviour).
|
||||
/// </param>
|
||||
public static float2 PlanarAimFromRay(float3 rayOrigin, float3 rayDir, float3 playerPos, float planeY,
|
||||
float2 fallback, float deadZoneRadius = 0f)
|
||||
{
|
||||
if (!TryGroundHit(rayOrigin, rayDir, planeY, out var hit))
|
||||
return fallback;
|
||||
|
||||
float2 planar = new float2(hit.x - playerPos.x, hit.z - playerPos.z);
|
||||
float dz = math.max(1e-3f, deadZoneRadius); // never below the original coincident-hit epsilon
|
||||
if (math.lengthsq(planar) < dz * dz)
|
||||
return fallback;
|
||||
|
||||
return math.normalize(planar);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a71e5a6ceef479e49983a86a038abc47
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace ProjectM.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// Active input-scheme ids for the local player, streamed in <see cref="PlayerInput.Scheme"/> so the
|
||||
/// server can apply aim-assist only to gamepad shots while leaving precise mouse aim exact.
|
||||
/// <para>
|
||||
/// A plain <c>byte</c> (not an <c>enum</c>) deliberately: this value is compared inside the
|
||||
/// Burst-compiled <c>AbilityFireSystem</c>, and cross-assembly <c>enum</c> use inside Burst code has
|
||||
/// tripped the Burst type-hash internal compiler error in this project before (see CLAUDE.md /
|
||||
/// ProjectileClassificationSystem). Integer consts are Burst-safe and replicate as a single byte.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public static class InputSchemeId
|
||||
{
|
||||
/// <summary>Mouse + keyboard: aim is the cursor direction; shots are precise (no auto-target assist).</summary>
|
||||
public const byte KeyboardMouse = 0;
|
||||
|
||||
/// <summary>Gamepad: aim is the right-stick direction; the server applies the auto-target assist cone.</summary>
|
||||
public const byte Gamepad = 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d2fa5ecb20cf454f9c4d70958df73e4
|
||||
@@ -22,12 +22,17 @@ namespace ProjectM.Simulation
|
||||
/// <summary>Primary ability fire. InputEvent survives the frame→tick→rollback boundary so a press fires exactly once.</summary>
|
||||
[GhostField] public InputEvent Fire;
|
||||
|
||||
/// <summary>Active input scheme this tick (<see cref="InputSchemeId"/>: 0 = mouse/keyboard, 1 = gamepad).
|
||||
/// The server reads it so the auto-target assist applies only to gamepad shots; precise mouse aim is left
|
||||
/// exact. A byte (not an enum): it is compared inside the Burst-compiled <c>AbilityFireSystem</c>.</summary>
|
||||
[GhostField] public byte Scheme;
|
||||
|
||||
public FixedString512Bytes ToFixedString()
|
||||
{
|
||||
var s = new FixedString512Bytes();
|
||||
s.Append(Move.x); s.Append(','); s.Append(Move.y); s.Append(';');
|
||||
s.Append(Aim.x); s.Append(','); s.Append(Aim.y); s.Append(';');
|
||||
s.Append(Fire.Count);
|
||||
s.Append(Fire.Count); s.Append(';'); s.Append(Scheme);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user