Level/BaseInteract.cs
using Opium;
using Sandbox;

public abstract class BaseInteract : Component, IInteractable
{
	/// <summary>
	/// An action for when the object is used.
	/// </summary>
	[Property, Category( "Actions" )] public Action UseAction { get; set; }

	/// <summary>
	/// An action that decides if we can use the object we're interacting with.
	/// </summary>
	[Property, Category( "Actions" )] public Func<GameObject, bool> CanUseAction { get; set; }

	/// <summary>
	/// Should we show the interaction UI?
	/// </summary>
	public virtual bool ShowInteractionUI => false;

	/// <summary>
	/// Can we use this object?
	/// </summary>
	/// <param name="player"></param>
	/// <returns></returns>
	public virtual bool CanUse( GameObject player )
	{
		if ( CanUseAction is not null )
		{
			return CanUseAction.Invoke( player );
		}

		return true;
	}

	/// <summary>
	/// Gets an icon (optional)
	/// </summary>
	/// <returns></returns>
	public virtual string GetUseIcon()
	{
		return null;
	}

	/// <summary>
	/// When we can't use the object
	/// </summary>
	/// <param name="player"></param>
	public virtual void OnUseFail( GameObject player )
	{
		//
	}

	public GameObject Source
	{
		get
		{
			return Components?.Get<InteractionSource>( FindMode.EverythingInSelfAndDescendants )?.GameObject ?? null;
		}
	}
		

	/// <summary>
	/// Called when using the object
	/// </summary>
	/// <param name="player"></param>
	public virtual void OnUse( GameObject player )
	{
		UseAction?.Invoke();
	}

	/// <summary>
	/// Called when stopping to use the hold key
	/// </summary>
	/// <param name="player"></param>
	public virtual void OnUseStop( GameObject player )
	{
		//
	}

	/// <summary>
	/// Called when holding the use key
	/// </summary>
	/// <param name="player"></param>
	public virtual void OnUseContinuous( GameObject player )
	{
		//
	}
}