A component that defines an out-of-bounds box trigger for a golf game. When a golf ball enters it the host treats it like a ball leaving the hole bounds and posts an OnBallOutOfBounds event; when a non-ball body enters it posts OnBodyOutOfBounds. It also draws a translucent red box gizmo in the editor using the BoxCollider scale.
using Sandbox;
/// <summary>
/// A placeable out-of-bounds zone: a box trigger (the Box Collider on the same object, Is Trigger
/// on) that a golf ball must not enter. When one does, the host treats it exactly as a ball that
/// left the Hole's bounds: back to where it was last shot from, the out-of-bounds penalty, the
/// announcement and the sound. A player who walks in is stood back next to their ball, or by the
/// tee if their ball hasn't been shot: no damage, no shot cost. Works on any hole and next to the
/// Hole's own bounds, which keep doing their job. Pickups and everything else pass through it
/// untouched. Drawn in the editor as a translucent red box, so it is easy to see and to resize
/// from the Box Collider's Scale.
/// </summary>
[Title( "Golf Out Of Bounds" ), Category( "Golf" ), Icon( "block" )]
public sealed class GolfOutOfBounds : Component, Component.ITriggerListener
{
void Component.ITriggerListener.OnTriggerEnter( Collider other )
{
// Physics runs everywhere, but only the host decides what counts.
if ( !Networking.IsHost ) return;
if ( !other.IsValid() || !other.GameObject.IsValid() ) return;
var ball = other.GameObject.GetComponentInParent<IGolfCourseBall>();
if ( ball is not null )
{
if ( !ball.IsHoled ) IGolfCourseEvents.Post( x => x.OnBallOutOfBounds( this, ball ) );
return;
}
// Anything else (a player's body, for one): the game resolves it.
IGolfCourseEvents.Post( x => x.OnBodyOutOfBounds( this, other.GameObject ) );
}
protected override void DrawGizmos()
{
var box = GetComponent<BoxCollider>( true );
var bounds = box is not null
? BBox.FromPositionAndSize( box.Center, box.Scale )
: BBox.FromPositionAndSize( new Vector3( 0f, 0f, 100f ), new Vector3( 200f, 200f, 200f ) );
var alpha = Gizmo.IsSelected ? 0.35f : (Gizmo.IsHovered ? 0.25f : 0.12f);
Gizmo.Draw.Color = Color.Red.WithAlpha( alpha );
Gizmo.Draw.SolidBox( bounds );
Gizmo.Draw.LineThickness = Gizmo.IsSelected ? 2f : 1f;
Gizmo.Draw.Color = Color.Red.WithAlpha( Gizmo.IsSelected ? 0.9f : 0.5f );
Gizmo.Draw.LineBBox( bounds );
}
}