Weapons/ToolGun/Modes/Thruster/ThrusterEntity.cs
[Alias( "thruster" )]
public sealed class ThrusterEntity : Component, IPlayerControllable
{
[Property, Range( 0, 1 )]
public GameObject OnEffect { get; set; }
[Property, ClientEditable, Range( 0, 1 )]
public float Power { get; set; } = 0.5f;
[Property, ClientEditable]
public bool Invert { get; set; } = false;
[Property, ClientEditable]
public bool HideEffects { get; set; } = false;
/// <summary>
/// While the client input is active we'll apply thrust
/// </summary>
[Property, Sync, ClientEditable]
public ClientInput Activate { get; set; }
/// <summary>
/// While this input is active we'll apply thrust in the opposite direction
/// </summary>
[Property, Sync, ClientEditable]
public ClientInput Reverse { get; set; }
/// <summary>
/// The fallback sound for all thrusters.
/// </summary>
private static SoundDefinition _defaultSound => ResourceLibrary.Get<SoundDefinition>( "entities/thruster/sounds/thruster_basic.sndef" );
/// <summary>
/// Looping sound played while the thruster is active.
/// </summary>
[Property, ClientEditable, Metadata( SoundDefinition.Thruster ), Group( "Sound" )]
public SoundDefinition ThrusterSound { get; set; }
/// <summary>
/// Current thrust output, -1 to 1. Updated every control frame.
/// </summary>
public float ThrustAmount { get; private set; }
private SoundHandle _thrusterSound;
protected override void OnEnabled()
{
base.OnEnabled();
OnEffect?.Enabled = false;
}
protected override void OnDisabled()
{
_state = false;
StopThrusterSound();
}
protected override void OnUpdate()
{
if ( _state )
{
if ( !_thrusterSound.IsValid() )
StartThrusterSound();
}
else
{
if ( _thrusterSound.IsValid() )
StopThrusterSound();
}
}
void AddThrust( float amount )
{
if ( amount.AlmostEqual( 0.0f ) ) return;
var body = GetComponent<Rigidbody>();
if ( body == null ) return;
body.ApplyImpulse( WorldRotation.Up * -10000 * amount * Power * (Invert ? -1f : 1f) );
}
bool _state;
[Rpc.Broadcast]
public void SetActiveState( bool state )
{
if ( _state == state ) return;
_state = state;
if ( !HideEffects )
OnEffect?.Enabled = state;
}
private void StartThrusterSound()
{
if ( _thrusterSound.IsValid() )
StopThrusterSound();
var sound = ThrusterSound ?? _defaultSound;
if ( sound is null ) return;
_thrusterSound = sound.Play( WorldPosition, GameObject );
}
private void StopThrusterSound()
{
if ( _thrusterSound.IsValid() )
{
_thrusterSound.Stop( 0.5f );
_thrusterSound = default;
}
}
public void OnControl()
{
if ( !Networking.IsHost ) return;
var forward = Activate.GetAnalog();
var backward = Reverse.GetAnalog();
var analog = forward - backward;
ThrustAmount = analog;
AddThrust( analog );
var active = MathF.Abs( analog ) > 0.1f;
if ( active != _state )
{
if ( active )
Sandbox.Services.Stats.Increment( "tool.thruster.activate", 1 );
SetActiveState( active );
}
}
}