A UnitStatus subclass that applies a freeze effect to a Unit. It sets frozen state and a time scale, updates lifetime, spawns frozen shard bullets and plays a sound when the frozen unit dies, and restores time scale when removed.
using System;
using Sandbox;
public class UnitStatusFreeze : UnitStatus
{
public Player PlayerSource { get; set; }
public Enemy EnemySource { get; set; }
public float TimeScale { get; set; }
public UnitStatusFreeze()
{
}
public override void Init( Unit unit )
{
base.Init( unit );
TimeScale = float.MaxValue;
Unit.SetStatusFrozen( true );
}
public void SetValues( float timeScale, float lifetime )
{
timeScale = MathF.Max( timeScale, 0.01f );
if ( timeScale < TimeScale )
{
Unit.SetTimeScale( timeScale );
TimeScale = timeScale;
Lifetime = lifetime;
}
}
public override void Update( float dt )
{
base.Update( dt );
if ( !Unit.IsValid() )
return;
//Gizmo.Draw.Color = Color.Red;
//Gizmo.Draw.Text( $"{Damage}\n{BaseDamage}\n{_stackTimes.Count()}", new global::Transform( Unit.WorldPosition ) );
if ( ElapsedTime > Lifetime )
Unit.RemoveUnitStatus( this );
//Unit.Velocity *= (1f - Utils.Map( TimeScale, 0.6f, 0f, 3f, 15f ) * dt);
}
public override void Die( Player player )
{
base.Die( player );
//Unit.AnimSpeedModifier = 1f;
//Unit.TimeScale = 1f;
//Unit.IsFrozen = false;
if ( PlayerSource.IsValid() && PlayerSource.GetSyncStat(PlayerStat.FrozenShardsNum) > 0f )
{
int maxShardsNum = (int)PlayerSource.GetSyncStat(PlayerStat.FrozenShardsNum);
int numShards = Game.Random.Int( 0, maxShardsNum );
if ( numShards == 0 && Game.Random.Float( 0f, 1f ) < 0.8f )
numShards = 1;
if ( numShards > 0 )
{
Vector2 aimDir = Utils.GetRandomVector();
PlayerSource.SpawnBulletRingRpc( Unit.Position2D, numShards, aimDir, isFromClip: false, BulletType.FrozenShard, damageMultMin: 0.1f, damageMultMax: 0.95f );
// todo: particle effect
// todo: sfx
Manager.Instance.PlaySfxNearbyRpc( "frozen", Unit.Position2D, pitch: Game.Random.Float( 2.8f, 3.00f ), volume: 1f, maxDist: 400f );
}
}
}
public override void OnRemove( bool playEffects = true )
{
Unit.SetStatusFrozen( false );
Unit.SetTimeScale( 1f ); // todo: needs to be set on client too?
}
public override void Refresh()
{
base.Refresh();
ElapsedTime = 0f;
}
public override void Colliding( Thing other, float percent, float dt )
{
base.Colliding( other, percent, dt );
}
}