CoverSurface.cs
using Sandbox;

namespace PaintballBaddies;

/// <summary>Explicit opt-in for geometry usable by the cover controller.</summary>
public sealed class CoverSurface : Component
{
    [Property] public float ModelHeight { get; set; }
    [Property] public bool Curved { get; set; }
    // For chest-high machinery where the marker cannot safely fire over the top.
    [Property] public bool StandingOnly { get; set; }
    // Optional semantic volume over solid workshop geometry. This identifies
    // the original map's crates without duplicating their renderers/collision.
    [Property] public Vector3 WorkshopSize {get;set;}
    public bool Matches(SceneTraceResult hit)=>hit.Hit && (Find(hit.GameObject)==this ||
        (WorkshopSize.x>0 && Contains(hit.HitPosition)));
    private static CoverSurface Find(GameObject go)
    {
        while(go.IsValid()){var cover=go.Components.Get<CoverSurface>();if(cover.IsValid())return cover;go=go.Parent;}
        return null;
    }
    private bool Contains(Vector3 position)
    {
        var p=WorldRotation.Inverse*(position-WorldPosition);
        return System.MathF.Abs(p.x)<=WorkshopSize.x*.5f+3 && System.MathF.Abs(p.y)<=WorkshopSize.y*.5f+3
            && p.z>=-3 && p.z<=WorkshopSize.z+3;
    }
    public static CoverSurface Resolve(Scene scene,SceneTraceResult hit)
    {
        if(!hit.Hit)return null;
        var direct=Find(hit.GameObject);
        if(direct.IsValid() || (hit.GameObject?.Components.Get<MapCollider>() is null && hit.GameObject?.Tags.Has("workshop_geometry")!=true))return direct;
        return direct ?? scene.GetAllComponents<CoverSurface>().FirstOrDefault(s=>s.WorkshopSize.x>0 && s.Enabled && s.GameObject.Active && s.Contains(hit.HitPosition));
    }
    public float Top
    {
        get
        {
            var box = Components.Get<BoxCollider>();
            return WorldPosition.z + (box is not null ? box.Center.z + box.Scale.z * .5f : ModelHeight) * WorldScale.z;
        }
    }
}