Conveyance/InteractionController.cs
using Sandbox;
/// <summary>
/// Interface implemented by anything in the world a player can interact with.
/// Add this to any component (InteractButton, future levers, pickups, etc.)
/// </summary>
public interface IInteractable
{
string InteractionText { get; }
void OnInteract( GameObject interactor );
}
/// <summary>
/// Attach to the player root alongside Player.
/// Uses Player.EyeTransform for the raycast — consistent with how Physgun
/// and ToolGun do their traces in this codebase.
/// </summary>
public sealed class InteractionController : Component
{
[Property] public float MaxDistance { get; set; } = 120f;
/// <summary>Currently looked-at interactable, or null. Read by GameHUD for prompt.</summary>
public IInteractable Current { get; private set; }
protected override void OnUpdate()
{
if ( IsProxy ) return;
Current = null;
// Use the sandbox-main Player component, same as Physgun/ToolGun do.
var player = Components.Get<Player>();
if ( player == null ) return;
var eye = player.EyeTransform;
var tr = Scene.Trace
.Ray( eye.Position, eye.Position + eye.Rotation.Forward * MaxDistance )
.IgnoreGameObjectHierarchy( GameObject )
.Run();
if ( tr.Hit && tr.GameObject != null )
Current = tr.GameObject.Components.Get<IInteractable>( true );
if ( Current != null && Input.Pressed( "Use" ) )
Current.OnInteract( GameObject );
}
}