InvestmentTable.cs
using Sandbox;
using SWB.Shared;
// The investment table at the back of the hideout. Put this on a GameObject
// with a trigger Collider covering the table; walk in and hold Use to open
// it, hold Use again (or walk away) to close.
//
// Deliberately the same interaction shape as the Vendor and the job board,
// so there is exactly one thing to learn in the hideout: stand near it,
// hold E.
//
// All the money lives on PlayerLoadout - this is just the door to it.
public sealed class InvestmentTable : Component, Component.ITriggerListener, IInteractable
{
[Property]
public float HoldDuration { get; set; } = 0.4f;
bool _playerInRange = false;
float _holdProgress = 0f;
bool _wasHolding = false;
public bool IsOpen { get; private set; }
// Drives the on-screen prompt - see IInteractable.
public bool PlayerInRange => _playerInRange;
public float HoldFraction => HoldDuration <= 0f ? 0f : _holdProgress / HoldDuration;
public string PromptText => "Hold E to manage investments";
public bool SuppressPrompt => IsOpen;
public void OnTriggerEnter( Collider other )
{
if ( other.GameObject.Root.Tags.Has( "player" ) )
_playerInRange = true;
}
public void OnTriggerExit( Collider other )
{
if ( !other.GameObject.Root.Tags.Has( "player" ) )
return;
_playerInRange = false;
_holdProgress = 0f;
Close();
}
protected override void OnUpdate()
{
if ( !_playerInRange )
return;
var holding = Input.Down( InputButtonHelper.Use );
if ( holding )
{
_holdProgress += Time.Delta;
// Only toggle on the hold completing, then wait for the button
// to come back up - otherwise one long press would flap the
// menu open and shut every HoldDuration seconds.
if ( _holdProgress >= HoldDuration && !_wasHolding )
{
_wasHolding = true;
IsOpen = !IsOpen;
}
}
else
{
_holdProgress = 0f;
_wasHolding = false;
}
}
public void Close()
{
IsOpen = false;
}
}