OrbiterShield is a game entity derived from Orbiter that acts as a protective shield orbiting a unit. It handles activation/recharge, scales/alphas its model based on state and time, blocks EnemyProjectile instances by removing them and plays a sound when blocking.
using System;
using Sandbox;
public class OrbiterShield : Orbiter
{
[Sync] public bool IsActive { get; set; }
public float RechargeTime { get; set; }
private TimeSince _timeSinceBlock;
public int ShieldNum { get; set; }
private float _lastAlpha;
protected override void OnStart()
{
base.OnStart();
if ( IsProxy )
return;
CollideWithTags.Add( "enemy_projectile" );
OrbitDistance = 25f;
IsActive = true;
RechargeTime = 1.5f;
_lastAlpha = -1f;
}
protected override void OnUpdate()
{
base.OnUpdate();
float alpha = OrbitedUnit.IsValid() && !OrbitedUnit.IsDying
? (IsActive ? 1f : 0.3f)
: 0f;
if ( alpha != _lastAlpha )
{
Model.Tint = Model.Tint.WithAlpha( alpha );
_lastAlpha = alpha;
}
if ( IsProxy )
return;
if ( !OrbitedUnit.IsValid() || OrbitedUnit.IsDying )
return;
if ( !IsActive )
{
if ( _timeSinceBlock > RechargeTime )
{
IsActive = true;
WorldScale = new Vector3( 1f );
}
else
{
WorldScale = new Vector3( Utils.Map( _timeSinceBlock, 0f, 0.375f, 0.5f, 1f, EasingType.Linear ) );
}
}
WorldRotation = Rotation.LookAt( Position2D - OrbitedUnit.Position2D );
OrbitDistance = OrbitedUnit.Radius + 10f;
}
protected override float GetZPos()
{
return OrbitedUnit.WorldPosition.z + 45f * (1f + Utils.FastSin( Time.Now * 9f ) * 0.185f);
}
public override void Colliding( Thing other, float percent, float dt )
{
base.Colliding( other, percent, dt );
if ( !IsActive || !OrbitedUnit.IsValid() || OrbitedUnit.IsDying )
return;
var enemyProjectile = other as EnemyProjectile;
if ( !enemyProjectile.IsValid() )
return;
enemyProjectile.RemoveRpc( shouldSpawnEffects: false );
Block();
}
void Block()
{
WorldScale = new Vector3( 0.5f );
IsActive = false;
_timeSinceBlock = 0f;
//Manager.Instance.PlaySfxNearbyRpc( "bullet.impact", Position2D, pitch: Game.Random.Float( 0.9f, 1f ), volume: 1.15f, maxDist: 300f );
Manager.Instance.PlaySfxNearbyRpc( "metal_hit", Position2D, pitch: Game.Random.Float( 0.9f, 1f ), volume: 1.15f, maxDist: 300f );
}
}