using System.Diagnostics; namespace ONDServer.Enemies; public class OpportunityTimer { public int Interval{ get; set; } public double MovementChance{ get; set{ field = value; GuaranteeSuccess(value >= 1); } } public bool Running => stopwatch.IsRunning; private Stopwatch stopwatch = new(); private long stopwatchOffset = 0; private Random random = new(); public OpportunityTimer(int intervalMs, double movementChance) { Interval = intervalMs; MovementChance = movementChance; } public OpportunityTimer(int intervalMs) { Interval = intervalMs; MovementChance = 1; } public void Start() { stopwatch.Start(); } public void Stop() { stopwatch.Stop(); } public bool Check() { if (stopwatch.ElapsedMilliseconds - stopwatchOffset >= Interval){ int overshoot = (int)(stopwatch.ElapsedMilliseconds - stopwatchOffset - Interval); stopwatchOffset = stopwatch.ElapsedMilliseconds - overshoot; return true; } return false; } public bool Roll() => roll(); private Func roll = () => true; public bool CheckAndRoll() { if (Check()) return Roll(); return false; } public void GuaranteeSuccess(bool value) { roll = value ? () => true : () => random.NextDouble() <= MovementChance; } }