unitStatus/UnitStatusPunched.cs

A UnitStatus subclass representing a 'punched' state for a unit. It sets a short lifetime, handles collisions with Enemy instances to apply damage, stun and knockback based on the unit's explosion velocity, and removes itself after expiry or after impacting an enemy.

Networking
using System;
using Sandbox;

public class UnitStatusPunched : UnitStatus
{
	public Enemy EnemySource { get; set; } // todo: never set
	public Player PlayerSource { get; set; }

	public UnitStatusPunched()
	{
		
	}

	public override void Init( Unit unit )
	{
		base.Init( unit );

		//Unit.SetStateStunned( true );

		Lifetime = 0.5f;
	}

	public override void Update( float dt )
	{
		base.Update( dt );

		if ( !Unit.IsValid() )
			return;

		if ( ElapsedTime > Lifetime )
			Unit.RemoveUnitStatus( this );

		//Gizmo.Draw.Color = Color.White;
		//Gizmo.Draw.Text( $"{Unit.ExplosionVelocity.Length.ToString("N2")}", new global::Transform( Unit.WorldPosition ) );

		// todo: clouds
	}

	public override void Die( Player player )
	{
		base.Die( player );

	}

	public override void Colliding( Thing other, float percent, float dt )
	{
		base.Colliding( other, percent, dt );

		if( other is Enemy enemy )
		{
			// only happen if weight is low enough to make it be moving fast enough
			if ( Unit.ExplosionVelocity.LengthSquared > Math.Pow( 250f, 2f ) )
			{
				var dir = Vector2.Lerp( (enemy.Position2D - Unit.Position2D).Normal, Unit.ExplosionVelocity.Normal, 0.33f );

				enemy.DamageRpc( 3f, PlayerSource, DamageType.Other, enemy.Position2D, force: dir * Unit.ExplosionVelocity.Length * 0.4f, isCrit: false, shouldFlinch: true );
				enemy.Stun( PlayerSource, null, 0.5f );

				//Unit.ExplosionVelocity = (Unit.Position2D - enemy.Position2D).Normal * Unit.ExplosionVelocity.Length * 0.4f;
				Unit.ExplosionVelocity = -dir * Unit.ExplosionVelocity.Length * 0.2f;
				Unit.RemoveUnitStatus( this );
				Unit.Stun( PlayerSource, null, 0.5f );
			}
		}
	}

	public override void OnRemove( bool playEffects = true )
	{
		//Unit.SetStateStunned( false );
	}

	public override void Refresh()
	{
		base.Refresh();

		ElapsedTime = 0f;
	}
}