PopRiotTarget.Crash.cs
using Sandbox;
using System;
namespace PaintballBaddies;

public sealed partial class PopRiotTarget
{
    [Sync(SyncFlags.FromHost)] public bool Crashing {get;private set;}
    [Sync(SyncFlags.FromHost)] public float CrashSeconds {get;private set;}
    [Sync(SyncFlags.FromHost)] public Vector3 CrashVelocity {get;private set;}
    private bool crashFinished,crashSoundStarted;
    private float crashFlare;
    private SoundHandle malfunction;
    private void BeginCrash()
    {
        Crashing=true;Charging=Entering=false;AttackTarget=null;
        CrashVelocity=FlightVelocity.WithZ(0)*.45f+Rotation.FromYaw(Seed*137).Forward*(100+Seed%5*12)+Vector3.Up*60;
        NetworkEffects.RiotDroneFlare(WorldPosition,PaintTint,false,Round,Seed);
    }
    private void UpdateCrash()
    {
        if(!crashSoundStarted)
        {
            crashSoundStarted=true;malfunction=DroneAudio.Play("malfunction",WorldPosition);
        }
        if(malfunction is not null){malfunction.Position=WorldPosition;malfunction.Pitch=MathF.Max(.5f,1.2f-CrashSeconds*.35f);}
        crashFlare-=Time.Delta;
        if(crashFlare<=0){DroneDamageFlare.Spawn(Scene,WorldPosition,PaintTint,false,Seed);crashFlare=.18f;}
        if(!MultiplayerSession.Authority || crashFinished)return;
        var session=MultiplayerSession.Find(Scene);
        if(!session.IsValid() || !session.InRound || session.RoundId!=Round){GameObject.Destroy();return;}
        CrashSeconds+=Time.Delta;
        float turn=(Seed%2==0 ? 1 : -1)*(100+Seed%4*25);
        CrashVelocity=Rotation.FromYaw(turn*Time.Delta)*CrashVelocity.WithZ(0)+Vector3.Up*(CrashVelocity.z-260*Time.Delta);
        var end=WorldPosition+CrashVelocity*Time.Delta;
        var hit=Scene.Trace.Sphere(20,WorldPosition,end).IgnoreGameObjectHierarchy(GameObject)
            .WithoutTags("pop_target","paintball_debris").Run();
        if(hit.Hit || CrashSeconds>2.4f)
        {
            var point=hit.Hit ? hit.EndPosition : end;
            if(hit.Hit && !ArenaShield.TryAbsorbImpact(hit,WorldPosition-CrashVelocity.Normal*40,PaintTint))
            {
                PaintballCombatant.Find(hit.GameObject)?.ReceiveRiotCrash(WorldPosition);
                PaintImpactSystem.Find(Scene)?.Spawn(hit,PaintTint);
            }
            FinishCrash(point);return;
        }
        WorldPosition=end;
    }
    private void FinishCrash(Vector3 point)
    {
        if(crashFinished)return;crashFinished=true;
        NetworkEffects.RiotBurst(point,Radius,PaintTint,false,false,Round);
        NetworkEffects.RiotDroneFlare(point,PaintTint,true,Round,Seed);
        GameObject.Destroy();
    }
    protected override void OnDestroy(){malfunction?.Stop();}
}