combat/CombatGeometry.cs
// CombatGeometry.cs
using System;
using Sandbox;

public enum HitZone
{
    Head = 0,
    Torso = 1,
    Legs = 2
}

public enum HitDirection
{
    Front = 0,
    Back = 1,
    Left = 2,
    Right = 3
}

public static class CombatGeometry
{
    /// <summary>
    /// Détermine la zone anatomique touchée en fonction du nom d'os ModelDoc.
    /// </summary>
    public static HitZone ResolveHitZone( string boneName )
    {
        if ( string.IsNullOrWhiteSpace( boneName ) )
            return HitZone.Torso;

        // Tête
        if ( boneName.Contains( "spine_005", StringComparison.OrdinalIgnoreCase ) || 
             boneName.Contains( "head", StringComparison.OrdinalIgnoreCase ) )
        {
            return HitZone.Head;
        }

        // Bas du corps
        if ( boneName.Contains( "thigh", StringComparison.OrdinalIgnoreCase ) ||
             boneName.Contains( "shin", StringComparison.OrdinalIgnoreCase ) ||
             boneName.Contains( "foot", StringComparison.OrdinalIgnoreCase ) )
        {
            return HitZone.Legs;
        }

        // Tronc / Épaules / Bras
        return HitZone.Torso;
    }

    /// <summary>
    /// Calcule la direction cardinale de l'attaque relative à l'orientation de la victime.
    /// Projeté sur le plan horizontal pour ignorer les dénivelés.
    /// </summary>
    public static HitDirection CalculateHitDirection( Vector3 victimPos, Rotation victimRot, Vector3 attackerPos )
    {
        var toAttacker = (attackerPos - victimPos).WithZ( 0 ).Normal;

        // Projections scalaires sur les axes locaux
        var forwardDot = Vector3.Dot( victimRot.Forward, toAttacker );
        var rightDot = Vector3.Dot( victimRot.Right, toAttacker );

        // Cône frontal / dorsal à 90° (cos(45°) ≈ 0.707)
        if ( forwardDot >= 0.707f )
            return HitDirection.Front;

        if ( forwardDot <= -0.707f )
            return HitDirection.Back;

        return rightDot > 0f ? HitDirection.Right : HitDirection.Left;
    }
}