Utility/Damage.cs
public static class Damage
{
	[Rpc.Broadcast]
	private static void ApplyForce( Rigidbody rb, Vector3 point, Vector3 force )
	{
		if ( !rb.IsValid() ) return;
		if ( rb.Network.Owner is null ) return;
		if ( !rb.Network.Owner.Id.Equals( Connection.Local.Id ) ) return;

		rb.ApplyForceAt( point, force );
	}

	public static void Radius( Vector3 point, float radius, float baseDamage, TagSet tags,
		GameObject source = null, GameObject weapon = null, Curve falloff = default, PlayerData instigator = null, GameObject ignore = null, float extraForce = 0 )
	{
		Assert.True( Networking.IsHost, "Only the host can deal damage!" );
		if ( !Networking.IsHost ) return;

		if ( falloff.Frames.IsDefaultOrEmpty )
		{
			falloff = new Curve( new Curve.Frame( 0.0f, 1.0f ), new Curve.Frame( 1.0f, 0.0f ) );
		}

		var scene = Game.ActiveScene;
		if ( !scene.IsValid() ) return;

		// Try to get the instigator from the source GameObject if not provided
		if ( instigator == null && source.IsValid() )
		{
			var instigatorComponent = source.GetComponent<IInstigator>();
			if ( instigatorComponent != null )
			{
				instigator = instigatorComponent.Instigator;
			}
		}

		var objectsInArea = scene.FindInPhysics( new Sphere( point, radius ) );

		var losTrace = scene.Trace.WithTag( "map" ).WithoutTags( "trigger" );

		if ( weapon.IsValid() )
			losTrace = losTrace.IgnoreGameObjectHierarchy( weapon );

		foreach ( var rb in objectsInArea.SelectMany( x => x.GetComponents<Rigidbody>() ).Distinct() )
		{
			if ( !rb.MotionEnabled )
				continue;

			if ( ignore.IsValid() && ignore.IsDescendant( rb.GameObject ) )
				continue;

			// If the object isn't in line of sight, fuck it off
			var tr = losTrace.Ray( point, rb.WorldPosition ).Run();
			if ( tr.Hit && tr.GameObject.IsValid() )
			{
				if ( !rb.GameObject.Root.IsDescendant( tr.GameObject ) )
					continue;
			}

			var dir = (rb.WorldPosition - point).Normal;
			var distance = rb.WorldPosition.Distance( point );

			// Bullshit, we should pass a force through or invent a scale from damage
			var forceMagnitude = Math.Clamp( 10000000000f / (distance * distance + 1), 0, 10000000000f );

			forceMagnitude += extraForce * (1 - (distance / radius));

			ApplyForce( rb, point, dir * forceMagnitude );
		}

		foreach ( var damageable in objectsInArea.SelectMany( x => x.GetComponentsInParent<Component.IDamageable>().Distinct() ) )
		{
			var target = damageable as Component;

			if ( ignore.IsValid() && ignore.IsDescendant( target.GameObject ) )
				continue;

			// If the object isn't in line of sight, fuck it off
			var tr = losTrace.Ray( point, target.WorldPosition ).Run();
			if ( tr.Hit && tr.GameObject.IsValid() )
			{
				if ( !target.GameObject.Root.IsDescendant( tr.GameObject ) )
					continue;
			}

			var distance = target.WorldPosition.Distance( point );
			var damage = baseDamage * falloff.Evaluate( distance / radius );
			var direction = (target.WorldPosition - point).Normal;
			var force = direction * distance * 50f;

			var position = tr.HitPosition;
			if ( target.GetComponentInChildren<CapsuleCollider>() is { } collider )
			{
				// for dramatic effect, lets just say hit the centre of the guy
				position += collider.End / 2;
			}

			var damageInfo = new DamageInfo( damage, instigator?.Player?.GameObject ?? source, weapon )
			{
				Origin = point,
				Position = position,
				Tags = tags
			};
			damageable.OnDamage( damageInfo );
		}
	}
}