Items/ChargeStation.cs
/// <summary>
/// A charge station. It can either heal health, or armour.
/// </summary>
public sealed class ChargeStation : Component, Component.IPressable
{
/// <summary>
/// The default / maximum charger power.
/// </summary>
[Property, Title( "Charger Power" )]
public float DefaultChargerPower { get; set; } = 50f;
/// <summary>
/// A synced representation of how much power is in the charge station.
/// </summary>
[Sync( SyncFlags.FromHost )]
public float ChargerPower { get; set; }
/// <summary>
/// How long without use until the charge station resets
/// </summary>
[Property, Title( "Charger Reset Time" )]
public float ChargerResetTime { get; set; } = 60f;
/// <summary>
/// Should this charger charge armour or health?
/// </summary>
[Property, Title( "Is Armour Charger" )]
public bool IsArmourCharger { get; set; } = false;
/// <summary>
/// How fast should we drain this charger
/// </summary>
[Property]
public float AddSpeed { get; set; } = 10f;
/// <summary>
/// The sound to play when we are charging (loop sound)
/// </summary>
[Property]
public SoundEvent ChargeSound { get; set; }
/// <summary>
/// Text to show the current charger power
/// </summary>
[Property]
TextRenderer TextRenderer { get; set; }
/// <summary>
/// The player who is using the charger right now
/// </summary>
[Sync( SyncFlags.FromHost )]
private Player Player { get; set; }
private TimeSince TimeSinceUsed;
private SoundHandle loopSound;
private bool wasCharging;
protected override void OnStart()
{
ChargerPower = DefaultChargerPower;
}
protected override void OnUpdate()
{
TextRenderer.Text = $"Charger Power: {(int)ChargerPower}";
var isCharging = Player.IsValid() && ChargerPower >= 1;
// Start or update sound if charging
if ( isCharging )
{
if ( !loopSound.IsValid() && ChargeSound is not null )
{
loopSound = Sound.Play( ChargeSound, WorldPosition );
}
if ( loopSound.IsValid() )
{
loopSound.Pitch = 0.6f + 1 - (ChargerPower / 50f * 0.8f);
}
}
else if ( wasCharging )
{
if ( loopSound.IsValid() )
{
loopSound.Stop();
loopSound = null;
}
// Play a sound to say we stopped using this
Sound.Play( "items/chargestations/accept_charge.sound", WorldPosition );
}
wasCharging = isCharging;
if ( IsProxy )
return;
if ( TimeSinceUsed > ChargerResetTime )
{
ChargerPower = DefaultChargerPower;
}
if ( isCharging && ShouldCharge( Player ) )
{
if ( IsArmourCharger )
{
ChargePlayer();
}
else
{
HealPlayer();
}
}
}
bool IPressable.Press( IPressable.Event e )
{
if ( ChargerPower < 1 )
return false;
var player = e.Source.GameObject.GetComponent<Player>();
if ( !player.IsValid() )
return false;
StartChargingRpc( player );
return true;
}
void IPressable.Release( IPressable.Event e )
{
StopChargingRpc();
}
bool IPressable.Pressing( IPressable.Event e )
{
return ChargerPower >= 1;
}
[Rpc.Host]
private void StartChargingRpc( Player player )
{
if ( !player.IsValid() )
return;
if ( !ShouldCharge( player ) )
{
PlayRejectSound();
return;
}
Player = player;
}
[Rpc.Broadcast]
private void PlayRejectSound()
{
Sound.Play( "items/chargestations/deny_charge.sound", WorldPosition );
}
[Rpc.Host]
private void StopChargingRpc()
{
if ( !Player.IsValid() )
return;
Player = null;
}
bool DrainPower( float amt )
{
if ( (ChargerPower - amt) <= 0f )
return false;
ChargerPower -= amt;
TimeSinceUsed = 0;
return true;
}
private bool ShouldCharge( Player player )
{
if ( !player.IsValid() )
return false;
// Health check
if ( !IsArmourCharger && player.Health >= player.MaxHealth )
return false;
// Armour check
if ( IsArmourCharger && player.Armour >= player.MaxArmour )
return false;
return true;
}
void HealPlayer()
{
if ( !ShouldCharge( Player ) )
{
StopChargingRpc();
return;
}
var add = AddSpeed * Time.Delta;
if ( DrainPower( add ) )
{
Player.Health = (Player.Health + add).Clamp( 0, Player.MaxHealth );
}
else
{
StopChargingRpc();
}
}
void ChargePlayer()
{
if ( !ShouldCharge( Player ) )
{
StopChargingRpc();
return;
}
var add = AddSpeed * Time.Delta;
if ( DrainPower( add ) )
{
Player.Armour = (Player.Armour + add).Clamp( 0, Player.MaxArmour );
}
else
{
StopChargingRpc();
}
}
}