Code/AI/Default/ShootState.cs
using Sandbox.Sboku;

namespace Sandbox.AI.Default;
internal class ShootState : StateBase, ICombatState
{
    private Burst burst;
    public ShootState(SbokuBase bot) : base(bot)
    {
    }

    private record Burst
    {
        public float Period;
        public TimeSince Timer = new TimeSince();
        public Burst(float period)
        {
            Period = period;
            Timer = 0;
        }
        public bool CanFire()
            => Timer < Period;
        public bool ShouldStop()
            => Timer > Period;
        public bool CanContinue()
            => Timer > Period * 2;
    }

    public override void Think()
    {
        if (Weapon.HasAmmo())
        {
            if (burst?.CanFire() ?? true)
            {
                Bot.IsShooting = Scene.Trace.Ray(Bot.EyePos, Target.GameObject.WorldPosition + Bot.HeightToAimAt)
                                            .IgnoreGameObjectHierarchy(Bot.GameObject)
                                            .Run().GameObject?.Parent == Target.GameObject;
            }
            else if (burst != null)
            {
                if (burst.CanContinue())
                    burst = null;
                else if (burst.ShouldStop())
                    Bot.IsShooting = false;
            }
            
            if (Bot.IsShooting && burst == null)
            {
                burst = new(Bot.BurstPeriod);
            }
        }
        else
        {
            OnReload();
        }
    }

    public override void OnUnset()
    {
        Bot.IsShooting = false;
    }

    public void OnReload()
    {
        lock (this)
        {
            Bot.IsShooting = false;
            Bot.SetCombatState<ReloadState>();
        }
    }
}