PaintHitReaction.cs
using Sandbox;
namespace PaintballBaddies;

// Owner-camera presentation only: do not alter shared time, projectile travel or aim.
public sealed class PaintHitReaction : Component
{
    private PaintballCombatant actor;
    private ColorAdjustments color;
    private Vignette vignette;
    private GameObject effects;
    private int observedSerial;
    public int Impulses {get;private set;}
    public float Weight {get;private set;}
    protected override void OnStart(){actor=Components.Get<PaintballCombatant>();observedSerial=actor?.HitSlowSerial ?? 0;}
    protected override void OnUpdate()
    {
        if(!actor.IsValid() || !Components.Get<PlayerController>().IsValid() || IsProxy)return;
        var camera=Scene.Camera;var session=MultiplayerSession.Find(Scene);
        bool play=session?.InRound==true && Scene.GetAllComponents<PaintballControls>().FirstOrDefault()?.Open!=true;
        Weight=play ? actor.HitReactionWeight : 0;
        if(actor.HitSlowSerial!=observedSerial)
        {
            observedSerial=actor.HitSlowSerial;
            if(Weight>0 && camera.IsValid())
            {
                Impulses++;camera.AddShake(.45f,16,.12f);
                camera.AddPunch(new Angles(1.3f,0,-.7f),.7f,.55f,0);
            }
        }
        if(Weight>0 && camera.IsValid() && !effects.IsValid())
        {
            effects=new GameObject(camera.GameObject,true,"Local drone-hit grading"){NetworkMode=NetworkMode.Never};
            color=effects.Components.Create<ColorAdjustments>();color.Saturation=.35f;
            vignette=effects.Components.Create<Vignette>();vignette.Color=new Color(.04f,.05f,.07f);vignette.Smoothness=.8f;
        }
        if(color.IsValid()){color.Blend=Weight*.8f;color.Enabled=Weight>.001f;}
        if(vignette.IsValid()){vignette.Intensity=.3f*Weight;vignette.Enabled=Weight>.001f;}
    }
    protected override void OnDestroy(){if(effects.IsValid())effects.Destroy();}
}