OMRBotController.cs
using Sandbox;
using Sandbox.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;

public enum OMRBotDifficulty
{
	Easy,
	Normal,
	Hard
}

public enum OMRBotBehaviorMode
{
	/// <summary>
	/// Foundation validation mode. The bot participates as a real OMR player but
	/// deliberately supplies no movement/combat decisions.
	/// </summary>
	Stationary,

	/// <summary>
	/// BOT 1 navigation test. The bot is allowed to know the human player's
	/// position directly so navigation can be validated in isolation.
	/// </summary>
	NavigateToOpponent,

	/// <summary>
	/// BOT 2 perception test. The bot only gains a usable target after a field-of-
	/// view + line-of-sight check and a human-like reaction delay. When sight is
	/// broken it navigates to the last observed position, searches briefly, then
	/// forgets the stale information.
	/// </summary>
	PerceptionSearch,

	/// <summary>
	/// BOT 3 combat test. Uses the validated BOT 2 perception data to aim, ADS,
	/// fire and reload a real OneMoreRoundWeapon. It never fires at memory-only
	/// positions and never reads hidden opponent coordinates for combat.
	/// </summary>
	Combat,

	/// <summary>
	/// BOT 4 movement-combat test. Keeps BOT 3's fair perception and real weapon
	/// handling, then layers player-equivalent sprint, strafe, slide, crouch and
	/// jump decisions through PlayerMovementInput. No transform movement cheats.
	/// </summary>
	CombatMovement,

	/// <summary>
	/// BOT 5A+5B tactical combat stack. Adds action arbitration, combat-usable
	/// cover, peeking, suppressive fire, flanking, hearing, intelligent mobile
	/// search, stronger under-fire reactions and traversal anti-loop safeguards
	/// on top of the validated BOT 4 movement/combat stack.
	/// </summary>
	TacticalCombat
}

public enum OMRCoverPosture
{
	None,
	Full,
	Crouch,
	Firing
}

public readonly struct OMRCoverChoice
{
	public Vector3 Anchor { get; }
	public OMRCoverPosture Posture { get; }
	public Vector3 LeftPeek { get; }
	public Vector3 RightPeek { get; }
	public bool HasLeftPeek { get; }
	public bool HasRightPeek { get; }
	public float Score { get; }

	public OMRCoverChoice(
		Vector3 anchor,
		OMRCoverPosture posture,
		Vector3 leftPeek,
		Vector3 rightPeek,
		bool hasLeftPeek,
		bool hasRightPeek,
		float score
	)
	{
		Anchor = anchor;
		Posture = posture;
		LeftPeek = leftPeek;
		RightPeek = rightPeek;
		HasLeftPeek = hasLeftPeek;
		HasRightPeek = hasRightPeek;
		Score = score;
	}
}

/// <summary>
/// Host-side brain for an OMR player bot.
///
/// The bot is a normal player prefab. AI writes synthetic commands into
/// PlayerMovementInput and therefore travels through the exact same
/// PlayerLocomotion / PlayerController pipeline as a human.
///
/// BOT 1 uses Scene.NavMesh.CalculatePath for route finding and consumes the
/// returned straight-path points directly. BOT 2 layers fair perception and
/// memory on top. BOT 3 consumes only that perceived information to drive the
/// real OMR weapon systems for aiming, ADS, firing and reloading. BOT 4 keeps
/// those systems intact and adds contextual movement through the exact same
/// synthetic input contract used by human locomotion. BOT 5A.2 adds a tactical
/// layer that treats incoming damage as directional evidence, scores nearby
/// combat cover, peeks, suppresses last-seen positions, flanks, hears noisy
/// gameplay stimuli and actively searches likely sectors without ever revealing
/// a hidden opponent's live transform.
/// </summary>
public sealed partial class OMRBotController : Component
{
	[Property, Sync( SyncFlags.FromHost )]
	public int BotSlot { get; set; } = 0;

	[Property, Sync( SyncFlags.FromHost )]
	public OMRBotDifficulty Difficulty { get; set; } =
		OMRBotDifficulty.Normal;

	[Property, Sync( SyncFlags.FromHost )]
	public OMRBotBehaviorMode BehaviorMode { get; set; } =
		OMRBotBehaviorMode.Stationary;

	[Property, Sync( SyncFlags.FromHost )]
	public string CurrentIntent { get; set; } =
		"STATIONARY / FOUNDATION TEST";

	[Property, Sync( SyncFlags.FromHost )]
	public string NavigationStatus { get; set; } = "OFF";

	[Property, Sync( SyncFlags.FromHost )]
	public string NavigationTargetName { get; set; } = "NONE";

	[Property, Sync( SyncFlags.FromHost )]
	public float NavigationTargetDistance { get; set; } = 0f;

	// =========================================================
	// BOT 2 PERCEPTION DIAGNOSTICS
	// =========================================================

	[Property, Sync( SyncFlags.FromHost )]
	public string PerceptionStatus { get; set; } = "OFF";

	[Property, Sync( SyncFlags.FromHost )]
	public string PerceptionTargetName { get; set; } = "NONE";

	[Property, Sync( SyncFlags.FromHost )]
	public float PerceptionTargetDistance { get; set; } = 0f;

	[Property, Sync( SyncFlags.FromHost )]
	public float PerceptionLastSeenSeconds { get; set; } = -1f;

	[Property, Sync( SyncFlags.FromHost )]
	public float PerceptionReactionRemaining { get; set; } = 0f;

	[Property, Sync( SyncFlags.FromHost )]
	public bool HasLastKnownPosition { get; set; } = false;

	[Property, Sync( SyncFlags.FromHost )]
	public Vector3 LastKnownPosition { get; set; } = Vector3.Zero;

	// =========================================================
	// BOT 3 COMBAT DIAGNOSTICS
	// =========================================================

	[Property, Sync( SyncFlags.FromHost )]
	public string CombatStatus { get; set; } = "OFF";

	[Property, Sync( SyncFlags.FromHost )]
	public float CombatAimError { get; set; } = 0f;

	[Property, Sync( SyncFlags.FromHost )]
	public bool CombatWantsAim { get; set; } = false;

	[Property, Sync( SyncFlags.FromHost )]
	public int CombatClip { get; set; } = -1;

	[Property, Sync( SyncFlags.FromHost )]
	public int CombatReserve { get; set; } = -1;

	// =========================================================
	// BOT 4 MOVEMENT DIAGNOSTICS
	// =========================================================

	[Property, Sync( SyncFlags.FromHost )]
	public string MovementStatus { get; set; } = "OFF";

	[Property, Sync( SyncFlags.FromHost )]
	public float MovementSpeed { get; set; } = 0f;

	// =========================================================
	// BOT 5A.2 TACTICAL DIAGNOSTICS
	// =========================================================

	[Property, Sync( SyncFlags.FromHost )]
	public string TacticalStatus { get; set; } = "OFF";

	[Property, Sync( SyncFlags.FromHost )]
	public string ThreatStatus { get; set; } = "NONE";

	[Property, Sync( SyncFlags.FromHost )]
	public string ThreatBearing { get; set; } = "NONE";

	[Property, Sync( SyncFlags.FromHost )]
	public float ThreatAgeSeconds { get; set; } = -1f;

	[Property, Sync( SyncFlags.FromHost )]
	public string CoverStatus { get; set; } = "NONE";

	[Property, Sync( SyncFlags.FromHost )]
	public string TacticalContextStatus { get; set; } = "NEUTRAL";

	[Property, Sync( SyncFlags.FromHost )]
	public float TacticalAggression { get; set; } = 0.50f;

	// =========================================================
	// BOT 5A + 5B ADVANCED TACTICAL DIAGNOSTICS
	// =========================================================

	[Property, Sync( SyncFlags.FromHost )]
	public string HearingStatus { get; set; } = "NONE";

	[Property, Sync( SyncFlags.FromHost )]
	public string HearingBearing { get; set; } = "NONE";

	[Property, Sync( SyncFlags.FromHost )]
	public float HearingAgeSeconds { get; set; } = -1f;

	[Property, Sync( SyncFlags.FromHost )]
	public string SearchStatus { get; set; } = "NONE";

	[Property, Sync( SyncFlags.FromHost )]
	public string FlankStatus { get; set; } = "NONE";

	[Property, Sync( SyncFlags.FromHost )]
	public string SuppressionStatus { get; set; } = "NONE";

	// =========================================================
	// BOT 6 MODIFIER / ADAPTIVE DIAGNOSTICS
	// =========================================================

	[Property, Sync( SyncFlags.FromHost )]
	public string ModifierStatus { get; set; } = "STANDARD";

	[Property, Sync( SyncFlags.FromHost )]
	public string AdaptationStatus { get; set; } = "LEARNING";

	[Property, Sync( SyncFlags.FromHost )]
	public float AdaptationConfidence { get; set; } = 0f;

	[Property, Sync( SyncFlags.FromHost )]
	public string SpatialMemoryStatus { get; set; } = "LEARNING";

	[Property, Sync( SyncFlags.FromHost )]
	public string AwarenessStatus { get; set; } = "FAIR";

	// =========================================================
	// NAVIGATION
	// =========================================================

	[Property, Group( "Navigation" )]
	public float RepathInterval { get; set; } = 0.25f;

	[Property, Group( "Navigation" )]
	public float LookAheadDistance { get; set; } = 72f;

	[Property, Group( "Navigation" )]
	public float StopDistance { get; set; } = 105f;

	[Property, Group( "Navigation" )]
	public float SprintDistance { get; set; } = 360f;

	// =========================================================
	// PERCEPTION
	// =========================================================

	[Property, Group( "Perception" )]
	public float PerceptionScanInterval { get; set; } = 0.10f;

	[Property, Group( "Perception" )]
	public float SightRange { get; set; } = 1600f;

	[Property, Group( "Perception" )]
	public float FieldOfView { get; set; } = 110f;

	[Property, Group( "Perception" )]
	public float PersonalSpace { get; set; } = 42f;

	[Property, Group( "Perception" )]
	public float SearchStopDistance { get; set; } = 52f;

	[Property, Group( "Perception" )]
	public float SearchSweepSpeed { get; set; } = 48f;

	[Property, Group( "Perception" )]
	public float IdleSweepSpeed { get; set; } = 26f;

	[Property, Group( "Perception / Difficulty" )]
	public float EasyReactionDelay { get; set; } = 0.55f;

	[Property, Group( "Perception / Difficulty" )]
	public float NormalReactionDelay { get; set; } = 0.32f;

	[Property, Group( "Perception / Difficulty" )]
	public float HardReactionDelay { get; set; } = 0.18f;

	[Property, Group( "Perception / Difficulty" )]
	public float EasyMemoryDuration { get; set; } = 3.5f;

	[Property, Group( "Perception / Difficulty" )]
	public float NormalMemoryDuration { get; set; } = 5.0f;

	[Property, Group( "Perception / Difficulty" )]
	public float HardMemoryDuration { get; set; } = 6.5f;

	// =========================================================
	// COMBAT
	// =========================================================

	[Property, Group( "Combat / Aim" )]
	public float EasyAimFollowSpeed { get; set; } = 3.6f;

	[Property, Group( "Combat / Aim" )]
	public float NormalAimFollowSpeed { get; set; } = 6.2f;

	[Property, Group( "Combat / Aim" )]
	public float HardAimFollowSpeed { get; set; } = 9.5f;

	[Property, Group( "Combat / Aim" )]
	public float EasyAimNoiseDegrees { get; set; } = 3.6f;

	[Property, Group( "Combat / Aim" )]
	public float NormalAimNoiseDegrees { get; set; } = 1.8f;

	[Property, Group( "Combat / Aim" )]
	public float HardAimNoiseDegrees { get; set; } = 0.8f;

	[Property, Group( "Combat / Aim" )]
	public float EasyFireToleranceDegrees { get; set; } = 6.5f;

	[Property, Group( "Combat / Aim" )]
	public float NormalFireToleranceDegrees { get; set; } = 4.0f;

	[Property, Group( "Combat / Aim" )]
	public float HardFireToleranceDegrees { get; set; } = 2.4f;

	[Property, Group( "Combat" )]
	public float MinimumAdsReadyFraction { get; set; } = 0.72f;

	[Property, Group( "Combat" )]
	public float MinimumTriggerReset { get; set; } = 0.035f;

	// =========================================================
	// BOT 4 PLAYER-EQUIVALENT MOVEMENT
	// =========================================================

	[Property, Group( "Movement / Combat" )]
	public float StrafeSwitchInterval { get; set; } = 1.15f;

	[Property, Group( "Movement / Combat" )]
	public float StrafeStrength { get; set; } = 0.88f;

	[Property, Group( "Movement / Combat" )]
	public float RetreatDistanceScale { get; set; } = 0.66f;

	[Property, Group( "Movement / Slide" )]
	public float SlideMinimumTargetDistance { get; set; } = 300f;

	[Property, Group( "Movement / Slide" )]
	public float SlideMaximumTargetDistance { get; set; } = 720f;

	[Property, Group( "Movement / Slide" )]
	public float SlideCooldown { get; set; } = 3.25f;

	[Property, Group( "Movement / Jump" )]
	public float JumpMinimumTargetDistance { get; set; } = 170f;

	[Property, Group( "Movement / Jump" )]
	public float JumpMaximumTargetDistance { get; set; } = 430f;

	[Property, Group( "Movement / Jump" )]
	public float JumpCooldown { get; set; } = 4.25f;

	[Property, Group( "Movement / Crouch" )]
	public float CrouchDodgeDuration { get; set; } = 0.62f;

	[Property, Group( "Movement / Crouch" )]
	public float CrouchDodgeCooldown { get; set; } = 5.0f;

	// =========================================================
	// BOT 5A.2 TACTICAL COVER / THREAT RESPONSE
	// =========================================================

	[Property, Group( "Tactics / Threat" )]
	public float ThreatMemoryDuration { get; set; } = 2.75f;

	[Property, Group( "Tactics / Threat" )]
	public float ThreatProbeDistance { get; set; } = 1100f;

	[Property, Group( "Tactics / Cover" )]
	public float CoverDecisionCooldown { get; set; } = 1.35f;

	[Property, Group( "Tactics / Cover" )]
	public float CoverHoldDuration { get; set; } = 1.85f;

	[Property, Group( "Tactics / Cover" )]
	public float CoverArrivalDistance { get; set; } = 46f;

	[Property, Group( "Tactics / Cover" )]
	public float CoverCandidateMinDistance { get; set; } = 145f;

	[Property, Group( "Tactics / Cover" )]
	public float CoverCandidateMaxDistance { get; set; } = 365f;

	[Property, Group( "Tactics / Cover" )]
	public float LowHealthCoverFraction { get; set; } = 0.38f;

	[Property, Group( "Tactics / Cover" )]
	public float LowHealthDecisionCooldown { get; set; } = 4.5f;

	[Property, Group( "Tactics / Cover Quality" )]
	public float CoverRouteSampleSpacing { get; set; } = 72f;

	[Property, Group( "Tactics / Cover Quality" )]
	public float CoverSideProbeDistance { get; set; } = 78f;

	[Property, Group( "Tactics / Cover Quality" )]
	public float CoverRouteExposurePenalty { get; set; } = 145f;

	[Property, Group( "Tactics / Arbitration" )]
	public float CoverEngageInterruptMargin { get; set; } = 14f;

	[Property, Group( "Tactics / Arbitration" )]
	public float UnderFireEvadeStrength { get; set; } = 0.90f;

	[Property, Group( "Tactics / Cover Combat" )]
	public float CoverPeekDuration { get; set; } = 0.82f;

	[Property, Group( "Tactics / Cover Combat" )]
	public float CoverPeekCooldown { get; set; } = 0.52f;

	[Property, Group( "Tactics / Cover Combat" )]
	public float CoverPeekArrivalDistance { get; set; } = 26f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalProbeDistance { get; set; } = 46f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalLowProbeHeight { get; set; } = 20f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalHighProbeHeight { get; set; } = 54f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalBypassDuration { get; set; } = 0.85f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalJumpCooldown { get; set; } = 1.25f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalNoProgressTimeout { get; set; } = 0.62f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalMinimumProgress { get; set; } = 14f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalOrbitWindow { get; set; } = 0.72f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalOrbitTurnThreshold { get; set; } = 185f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalOrbitMinimumTravel { get; set; } = 86f;

	[Property, Group( "Tactics / Traversal" )]
	public float TraversalRecoveryDuration { get; set; } = 0.58f;

	// =========================================================
	// BOT 5B SEARCH / HEARING / SUPPRESSION / FLANKING
	// =========================================================

	[Property, Group( "Tactics / Hearing" )]
	public float GunshotHearingRange { get; set; } = 1250f;

	[Property, Group( "Tactics / Hearing" )]
	public float SprintHearingRange { get; set; } = 520f;

	[Property, Group( "Tactics / Hearing" )]
	public float WalkHearingRange { get; set; } = 260f;

	[Property, Group( "Tactics / Hearing" )]
	public float SlideHearingRange { get; set; } = 680f;

	[Property, Group( "Tactics / Hearing" )]
	public float HearingMemoryDuration { get; set; } = 4.25f;

	[Property, Group( "Tactics / Hearing" )]
	public float HearingOcclusionRangeScale { get; set; } = 0.58f;

	[Property, Group( "Tactics / Search" )]
	public float SearchPredictionSeconds { get; set; } = 0.85f;

	[Property, Group( "Tactics / Search" )]
	public float SearchLateralDistance { get; set; } = 155f;

	[Property, Group( "Tactics / Search" )]
	public float SearchForwardDistance { get; set; } = 210f;

	[Property, Group( "Tactics / Search" )]
	public float SearchPointPause { get; set; } = 0.42f;

	[Property, Group( "Tactics / Search" )]
	public float SearchPlanLifetime { get; set; } = 6.5f;

	[Property, Group( "Tactics / Suppression" )]
	public float SuppressionMemoryWindow { get; set; } = 1.15f;

	[Property, Group( "Tactics / Suppression" )]
	public float SuppressionCooldown { get; set; } = 2.6f;

	[Property, Group( "Tactics / Suppression" )]
	public int SuppressionBurstShots { get; set; } = 4;

	[Property, Group( "Tactics / Flank" )]
	public float FlankDecisionCooldown { get; set; } = 4.25f;

	[Property, Group( "Tactics / Flank" )]
	public float FlankMinimumContactTime { get; set; } = 1.65f;

	[Property, Group( "Tactics / Flank" )]
	public float FlankMinimumDistance { get; set; } = 210f;

	[Property, Group( "Tactics / Flank" )]
	public float FlankMaximumDistance { get; set; } = 430f;

	// =========================================================
	// BOT 6 MODIFIER AWARENESS / ADAPTIVE OPPONENT MODEL
	// =========================================================

	[Property, Group( "BOT 6 / Adaptation" )]
	public bool AdaptiveLearningEnabled { get; set; } = true;

	[Property, Group( "BOT 6 / Adaptation" ), Range( 0.01f, 0.35f )]
	public float AdaptiveLearningRate { get; set; } = 0.09f;

	[Property, Group( "BOT 6 / Adaptation" ), Range( 4, 80 )]
	public int AdaptiveMinimumSamples { get; set; } = 14;

	[Property, Group( "BOT 6 / Variation" ), Range( 0f, 0.35f )]
	public float DynamicVariationStrength { get; set; } = 0.16f;

	[Property, Group( "BOT 6 / Variation" )]
	public float DynamicDecisionIntervalMin { get; set; } = 2.0f;

	[Property, Group( "BOT 6 / Variation" )]
	public float DynamicDecisionIntervalMax { get; set; } = 4.8f;

	[Property, Group( "BOT 6 / Mobility" ), Range( 0f, 0.65f )]
	public float SearchClearMoveStrength { get; set; } = 0.28f;

	[Property, Group( "BOT 6 / Mobility" ), Range( 0f, 0.65f )]
	public float SuppressionMoveStrength { get; set; } = 0.22f;

	[Property, Group( "BOT 6 / Mobility" )]
	public float RepathFailureGrace { get; set; } = 0.70f;

	// =========================================================
	// BOT 6.1 - FAIR AWARENESS / SPATIAL EPISODIC MEMORY
	// =========================================================

	[Property, Group( "BOT 6.1 / Fair Awareness" ), Range( 0f, 0.5f )]
	public float CrouchHearingRangeScale { get; set; } = 0.08f;

	[Property, Group( "BOT 6.1 / Fair Awareness" ), Range( 0f, 1f )]
	public float RearHearingConfidenceThreshold { get; set; } = 0.52f;

	[Property, Group( "BOT 6.1 / Fair Awareness" ), Range( 0f, 1f )]
	public float SideHearingConfidenceThreshold { get; set; } = 0.30f;

	[Property, Group( "BOT 6.1 / Memory" )]
	public float SpatialMemoryCellSize { get; set; } = 128f;

	[Property, Group( "BOT 6.1 / Memory" )]
	public float SpatialMemoryHalfLife { get; set; } = 55f;

	[Property, Group( "BOT 6.1 / Memory" )]
	public float RouteMemoryHalfLife { get; set; } = 24f;

	[Property, Group( "BOT 6.1 / Memory" )]
	public float LearnedHotspotMinimumScore { get; set; } = 2.40f;

	[Property, Group( "BOT 6.1 / Memory" )]
	public float DeathRoutePenalty { get; set; } = 2.25f;

	[Property, Group( "BOT 6.1 / Memory" )]
	public float RouteSampleInterval { get; set; } = 0.24f;

	[Property, Group( "Diagnostics" )]
	public bool LogState { get; set; } = false;

	private sealed class SpatialMemoryCell
	{
		public float OpponentPresence;
		public float OpponentStationaryPresence;
		public float Danger;
		public float DeathDanger;
		public float RouteUse;
		public float LastUpdatedAt;
		public float LastOpponentSeenAt = -999f;
		public float LastCheckedAt = -999f;
	}

	private readonly struct RecentRouteSample
	{
		public Vector3 Position { get; }
		public float Time { get; }

		public RecentRouteSample( Vector3 position, float time )
		{
			Position = position;
			Time = time;
		}
	}

	private PlayerState _playerState;
	private PlayerController _controller;
	private PlayerMovementInput _movementInput;
	private PlayerSprint _sprint;
	private PlayerCrouch _crouch;
	private PlayerSlide _slide;
	private BaseInventoryComponent _inventory;
	private PlayerHealth _health;

	private PlayerState _navigationTarget;
	private PlayerState _perceptionTarget;

	private readonly List<Vector3> _pathPoints = new();
	private int _pathPointIndex;
	private string _pathStatus = "NO PATH";
	private float _nextRepathAt;
	private float _nextDiagnosticAt;

	private float _nextPerceptionScanAt;
	private float _rawVisibleSince = -1f;
	private float _lastConfirmedSeenAt = -999f;
	private bool _hasConfirmedSight;
	private Vector3 _observedTargetPosition;
	private Vector3 _observedTargetAimPoint;
	private float _nextSearchTurnAt;
	private float _searchTurnDirection = 1f;

	private float _nextBotTriggerAt;
	private OneMoreRoundWeapon _lastCombatWeapon;

	// BOT 4 movement state. These timers decide when to press the same synthetic
	// buttons a human would press; PlayerLocomotion still owns the physical result.
	private float _nextStrafeSwitchAt;
	private float _strafeDirection = 1f;
	private float _nextSlideAt;
	private float _nextJumpAt;
	private bool _airJumpAttemptPending;
	private float _airJumpAttemptAt;
	private float _nextCrouchDodgeAt;
	private float _crouchDodgeEndAt = -1f;
	private float _crouchButtonHeldUntil = -1f;
	private bool _wasSliding;

	// BOT 5A.2 tactical state. Damage only produces a noisy direction vector, not
	// the attacker's hidden live position. Cover points are projected onto the
	// same runtime navmesh used by BOT 1 and reached through normal locomotion.
	private int _lastProcessedDamageSequence = -1;
	private float _lastThreatAt = -999f;
	private Vector3 _lastThreatDirection = Vector3.Zero;
	private float _threatOrientUntil = -1f;
	private float _nextCoverDecisionAt;
	private float _nextLowHealthCoverAt;
	private bool _hasCoverTarget;
	private Vector3 _coverTarget = Vector3.Zero;
	private string _coverReason = string.Empty;
	private float _coverHoldUntil = -1f;
	private OMRCoverPosture _coverPosture = OMRCoverPosture.None;
	private Vector3 _coverLeftPeek = Vector3.Zero;
	private Vector3 _coverRightPeek = Vector3.Zero;
	private bool _coverHasLeftPeek;
	private bool _coverHasRightPeek;
	private bool _coverPeekActive;
	private bool _coverPeekReturning;
	private Vector3 _coverPeekTarget = Vector3.Zero;
	private float _coverPeekUntil = -1f;
	private float _nextCoverPeekAt;
	private int _coverPeekSide = 1;
	private float _nextTraversalJumpAt;
	private float _traversalBypassUntil = -1f;
	private Vector3 _traversalBypassDirection = Vector3.Zero;
	private string _traversalFrameStatus = string.Empty;
	private float _traversalProgressStartedAt = -1f;
	private float _traversalBestDistance = float.MaxValue;
	private Vector3 _traversalProgressTarget = Vector3.Zero;
	private int _traversalPreferredBypassSign = 1;
	private float _traversalOrbitWindowStartedAt = -1f;
	private Vector3 _traversalOrbitStartPosition = Vector3.Zero;
	private Vector3 _traversalOrbitTarget = Vector3.Zero;
	private Vector3 _traversalOrbitLastPosition = Vector3.Zero;
	private Vector3 _traversalOrbitPreviousDirection = Vector3.Zero;
	private float _traversalOrbitStartDistance = float.MaxValue;
	private float _traversalOrbitTravelDistance;
	private float _traversalOrbitTurnDegrees;
	private float _traversalRecoveryUntil = -1f;
	private Vector3 _traversalRecoveryDirection = Vector3.Zero;

	// BOT 5B sensory/search/tactical state. These fields never grant hidden live
	// target coordinates to combat. They cache only visual memory, noisy auditory
	// evidence, or deliberate tactical destinations derived from those facts.
	private Vector3 _lastSeenVelocity = Vector3.Zero;
	private Vector3 _lastSeenDirection = Vector3.Zero;
	private Vector3 _previousObservedPosition = Vector3.Zero;
	private float _previousObservedAt = -1f;
	private float _confirmedSightStartedAt = -1f;
	private bool _sightWasConfirmedLastFrame;
	private float _lostSightAt = -999f;

	private OneMoreRoundWeapon _heardOpponentWeapon;
	private int _heardOpponentWeaponEventCount = -1;
	private float _nextMovementHearingAt;
	private Vector3 _lastHeardPosition = Vector3.Zero;
	private float _lastHeardAt = -999f;
	private float _lastHeardConfidence;
	private string _lastHeardKind = string.Empty;

	private readonly List<Vector3> _searchPoints = new();
	private int _searchPointIndex;
	private float _searchPlanCreatedAt = -999f;
	private float _searchPauseUntil = -1f;
	private Vector3 _searchFacingDirection = Vector3.Zero;
	private string _searchEvidence = string.Empty;

	private bool _flankActive;
	private Vector3 _flankTarget = Vector3.Zero;
	private float _nextFlankDecisionAt;
	private int _flankSide = 1;

	private float _suppressionUntil = -1f;
	private float _nextSuppressionAt;
	private int _suppressionShotsRemaining;
	private Vector3 _suppressionAimPoint = Vector3.Zero;

	// BOT 6 modifier-awareness and lightweight online opponent model. This is not
	// an opaque neural network: it is a bounded, inspectable set of exponentially
	// weighted observations gathered only from information a human could perceive.
	private RoundManager _roundManager;
	private OMRRoundRuleDirector _roundRuleDirector;
	private OMRRoundRuleProfile _activeRoundRule;
	private RoundModifier _activeModifier = RoundModifier.Standard;
	private HighNoonStage _lastHighNoonStage = HighNoonStage.Inactive;
	private float _highNoonFireAt = -1f;

	private int _adaptiveSampleCount;
	private float _nextAdaptiveSampleAt;
	private float _adaptiveOpponentAggression = 0.50f;
	private float _adaptiveOpponentMobility = 0.50f;
	private float _adaptiveOpponentAirUse = 0.10f;
	private float _adaptiveOpponentCrouchUse = 0.10f;
	private float _adaptivePreferredDistance = 0.50f;
	private float _adaptivePreviousDistance = -1f;
	private float _adaptivePreviousSampleAt = -1f;

	private float _nextDynamicVariationAt;
	private float _dynamicPressureBias;
	private float _dynamicCoverBias;
	private float _dynamicFlankBias;
	private float _dynamicMovementBias;
	private int _dynamicDecisionSerial;

	// BOT 6.1 persistent-within-session spatial memory. Values are learned only
	// from confirmed sight, received damage, the bot's own movement and its own
	// deaths. The bot never writes the opponent's hidden live transform here.
	private readonly Dictionary<(int X, int Y), SpatialMemoryCell> _spatialMemory = new();
	private readonly List<RecentRouteSample> _recentRouteSamples = new();
	private float _nextRouteMemorySampleAt;
	private float _nextSpatialMemoryDiagnosticAt;
	private bool _memoryWasAlive;
	private bool _memoryLifeInitialized;
	private int _spatialDeathCount;
	private int _learnedHotspotChecks;
	private ArenaController _memoryArena;
	private ArenaLayoutState _memoryLayoutState = ArenaLayoutState.Invalid;
	private bool _memoryLayoutInitialized;

	private float _lastSuccessfulPathAt = -999f;

	protected override void OnStart()
	{
		ResolveReferences();
		SuppressHumanControl();

		if ( LogState && _playerState?.IsBot == true )
		{
			Log.Info(
				$"[OMR BOT] Started | {_playerState.DisplayName} | Team:{_playerState.TeamId} | Difficulty:{Difficulty}"
			);
		}
	}

	private float _nextUpdateExceptionLogAt;
	private string _lastUpdateException = string.Empty;

	protected override void OnUpdate()
	{
		// The bot object is host-controlled. Remote peers only render the
		// replicated result and must never make AI decisions locally.
		if ( !Networking.IsHost || IsProxy )
			return;

		try
		{
			UpdateHostBrain();
		}
		catch ( Exception exception )
		{
			HandleUpdateException( exception );
		}
	}

	private void UpdateHostBrain()
	{
		ResolveReferences();

		if ( _playerState?.IsValid != true || _playerState.IsBot != true )
			return;

		SuppressHumanControl();
		UpdateSpatialMemoryLifecycle();
		UpdatePerformanceCounters();
		if ( !PrepareBotSessionLifecycle() ) return;

		switch ( BehaviorMode )
		{
			case OMRBotBehaviorMode.TacticalCombat:
				UpdateCombat();
				break;

			case OMRBotBehaviorMode.CombatMovement:
				UpdateCombat();
				break;

			case OMRBotBehaviorMode.Combat:
				UpdateCombat();
				break;

			case OMRBotBehaviorMode.PerceptionSearch:
				ResetCombatDiagnostics( "OFF" );
				UpdatePerceptionSearch();
				break;

			case OMRBotBehaviorMode.NavigateToOpponent:
				ResetCombatDiagnostics( "OFF" );
				UpdateNavigationToOpponent();
				break;

			case OMRBotBehaviorMode.Stationary:
			default:
				ReleaseBotWeaponIntent();
				ResetCombatDiagnostics( "OFF" );
				ResetPerceptionDiagnostics( "OFF" );
				StopNavigation(
					"STATIONARY / FOUNDATION TEST",
					"OFF"
				);
				break;
		}
	}

	private void HandleUpdateException( Exception exception )
	{
		// Do not leave stale movement or ADS held if a transient component is
		// invalidated during sandbox respawn/hotload/teardown. S&box otherwise
		// reports only the generic "Exception when calling Update" line, which
		// is wonderfully unhelpful when debugging an AI made of many systems.
		StopMovementOnly();
		SafeReleaseLastCombatWeapon();

		CurrentIntent = "AI UPDATE RECOVERY";
		NavigationStatus = "RECOVERING";
		CombatStatus = "UPDATE ERROR";

		string signature =
			$"{exception.GetType().FullName}: {exception.Message}";

		if ( signature != _lastUpdateException || Time.Now >= _nextUpdateExceptionLogAt )
		{
			_lastUpdateException = signature;
			_nextUpdateExceptionLogAt = Time.Now + 1.0f;

			Log.Error(
				$"[OMR BOT] Update exception in {BehaviorMode}: {exception}"
			);
		}

		// Force reference reacquisition on the next frame. This covers objects
		// replaced during Sandbox respawn and hotload without treating a stale
		// Component reference as a valid non-null object forever.
		_playerState = null;
		_controller = null;
		_movementInput = null;
		_sprint = null;
		_crouch = null;
		_slide = null;
		_inventory = null;
		MovementStatus = "RECOVERING";
		MovementSpeed = 0f;
	}

	public void Configure(
		int slot,
		OMRBotDifficulty difficulty,
		OMRBotBehaviorMode behaviorMode
	)
	{
		if ( !Networking.IsHost )
			return;

		BotSlot = slot;
		Difficulty = difficulty;

		if ( BehaviorMode != behaviorMode )
		{
			BehaviorMode = behaviorMode;
			ResetRuntimeBehaviorState();
		}
	}

	private void ResolveReferences()
	{
		if ( _playerState?.IsValid != true )
			_playerState = Components.Get<PlayerState>();

		if ( _controller?.IsValid != true )
			_controller = Components.Get<PlayerController>();

		if ( _movementInput?.IsValid != true )
			_movementInput = Components.Get<PlayerMovementInput>();

		if ( _sprint?.IsValid != true )
			_sprint = Components.Get<PlayerSprint>();

		if ( _crouch?.IsValid != true )
			_crouch = Components.Get<PlayerCrouch>();

		if ( _slide?.IsValid != true )
			_slide = Components.Get<PlayerSlide>();

		if ( _inventory?.IsValid != true )
			_inventory = Components.Get<BaseInventoryComponent>();

		if ( _health?.IsValid != true )
			_health = Components.Get<PlayerHealth>();
	}

	// =========================================================
	// BOT 1 - OMNISCIENT NAVIGATION TEST
	// =========================================================

	private void UpdateNavigationToOpponent()
	{
		ResetPerceptionDiagnostics( "BOT 1 OMNISCIENT" );

		if ( !CanUseNavigation() )
			return;

		_navigationTarget =
			ResolveHumanTarget( _navigationTarget );

		if (
			_navigationTarget?.GameObject is null ||
			!_navigationTarget.IsAlive
		)
		{
			StopNavigation(
				"NO LIVE TARGET",
				"IDLE"
			);
			return;
		}

		NavigateToWorldPosition(
			_navigationTarget.WorldPosition,
			_navigationTarget.DisplayName,
			StopDistance,
			"NAVIGATING"
		);
	}

	// =========================================================
	// BOT 2 - PERCEPTION + MEMORY + SEARCH
	// =========================================================

	private void UpdatePerceptionSearch()
	{
		if ( !CanUseNavigation() )
		{
			PerceptionStatus = "WAITING";
			return;
		}

		UpdatePerception();
		UpdatePerceptionTimers();

		if ( PerceptionStatus == "REACTING" )
		{
			// Do not instantly turn or move toward a contact the bot has not
			// consciously reacted to yet. Holding its current look direction also
			// prevents the idle scan from sweeping away during the reaction window.
			_pathPoints.Clear();
			_pathPointIndex = 0;
			StopMovementOnly();
			NavigationStatus = "REACTING";
			NavigationTargetName = "NONE";
			NavigationTargetDistance = 0f;
			CurrentIntent = "REACTION DELAY / HOLD";
			return;
		}

		if ( _hasConfirmedSight && _perceptionTarget?.IsAlive == true )
		{
			NavigateToWorldPosition(
				_observedTargetPosition,
				_perceptionTarget.DisplayName,
				StopDistance,
				"TRACKING VISIBLE TARGET"
			);
			return;
		}

		if ( HasFreshMemory() )
		{
			Vector3 toLastKnown =
				( LastKnownPosition - WorldPosition )
					.WithZ( 0f );

			if ( toLastKnown.Length <= SearchStopDistance )
			{
				_pathPoints.Clear();
				_pathPointIndex = 0;
				StopMovementOnly();
				NavigationStatus = "SEARCHING";
				NavigationTargetName = "LAST KNOWN";
				NavigationTargetDistance =
					MathF.Round( toLastKnown.Length );
				CurrentIntent = "SEARCHING LAST KNOWN POSITION";
				SweepLook( SearchSweepSpeed );
				return;
			}

			NavigateToWorldPosition(
				LastKnownPosition,
				"LAST KNOWN",
				SearchStopDistance,
				"SEARCHING LAST KNOWN"
			);
			return;
		}

		// No valid visual contact and no recent memory. Do not use the actual
		// opponent position. Slowly scan the arena until the FOV/LOS system sees
		// something again.
		_pathPoints.Clear();
		_pathPointIndex = 0;
		StopMovementOnly();
		NavigationStatus = "IDLE";
		NavigationTargetName = "NONE";
		NavigationTargetDistance = 0f;
		CurrentIntent = "NO CONTACT / SCANNING";
		SweepLook( IdleSweepSpeed );
	}

	private void UpdatePerception()
	{
		_perceptionTarget =
			ResolveHumanTarget( _perceptionTarget );

		if ( _perceptionTarget?.GameObject is null || !_perceptionTarget.IsAlive )
		{
			_hasConfirmedSight = false;
			_rawVisibleSince = -1f;
			PerceptionTargetName = "NONE";
			PerceptionTargetDistance = 0f;
			PerceptionReactionRemaining = 0f;
			PerceptionStatus = HasFreshMemory()
				? "MEMORY / TARGET DOWN"
				: "NO TARGET";
			return;
		}

		if ( Time.Now < _nextPerceptionScanAt )
			return;

		_nextPerceptionScanAt =
			Time.Now + MathF.Max( 0.02f, PerceptionScanInterval );

		Vector3 toTarget =
			( _perceptionTarget.WorldPosition - WorldPosition );

		float targetDistance =
			toTarget.Length;

		PerceptionTargetName =
			_perceptionTarget.DisplayName;

		PerceptionTargetDistance =
			MathF.Round( targetDistance );

		bool withinRange =
			targetDistance <= SightRange;

		bool inViewCone =
			withinRange &&
			IsInViewCone( _perceptionTarget, targetDistance );

		bool hasLineOfSight =
			inViewCone &&
			HasLineOfSight( _perceptionTarget );

		bool rawVisible =
			withinRange &&
			inViewCone &&
			hasLineOfSight;

		if ( rawVisible )
		{
			if ( _rawVisibleSince < 0f )
				_rawVisibleSince = Time.Now;

			float reactionDelay =
				GetReactionDelay();

			float visibleFor =
				MathF.Max( 0f, Time.Now - _rawVisibleSince );

			PerceptionReactionRemaining =
				MathF.Max( 0f, reactionDelay - visibleFor );

			if ( visibleFor >= reactionDelay )
			{
				Vector3 newlyObservedPosition = _perceptionTarget.WorldPosition;

				if ( !_hasConfirmedSight )
				{
					_confirmedSightStartedAt = Time.Now;
				}

				if ( _previousObservedAt > 0f && Time.Now - _previousObservedAt <= 0.30f &&
					( newlyObservedPosition - _previousObservedPosition ).Length <= 160f )
				{
					float sampleDelta = MathF.Max( 0.02f, Time.Now - _previousObservedAt );
					Vector3 observedVelocity =
						( newlyObservedPosition - _previousObservedPosition ) / sampleDelta;
					_lastSeenVelocity = Vector3.Lerp( _lastSeenVelocity, observedVelocity, 0.45f );
					Vector3 planarVelocity = _lastSeenVelocity.WithZ( 0f );
					if ( !planarVelocity.IsNearlyZero( 1f ) )
						_lastSeenDirection = planarVelocity.Normal;
				}
				else _lastSeenVelocity = Vector3.Zero;

				_previousObservedPosition = newlyObservedPosition;
				_previousObservedAt = Time.Now;
				_sightWasConfirmedLastFrame = true;
				_hasConfirmedSight = true;
				_lastConfirmedSeenAt = Time.Now;
				_observedTargetPosition = newlyObservedPosition;
				_observedTargetAimPoint = ResolveCombatAimPoint( _perceptionTarget );

				HasLastKnownPosition = true;
				LastKnownPosition = _observedTargetPosition;

				PerceptionStatus = "VISIBLE";
			}
			else
			{
				// The physical ray can already see the opponent, but the AI is not
				// allowed to use that information until its reaction delay elapses.
				_hasConfirmedSight = false;
				PerceptionStatus = "REACTING";
			}

			return;
		}

		_rawVisibleSince = -1f;
		PerceptionReactionRemaining = 0f;

		if ( _hasConfirmedSight || _sightWasConfirmedLastFrame )
		{
			_lostSightAt = Time.Now;
			_sightWasConfirmedLastFrame = false;
		}

		_hasConfirmedSight = false;

		if ( HasFreshMemory() )
		{
			PerceptionStatus = "MEMORY";
		}
		else
		{
			HasLastKnownPosition = false;
			PerceptionStatus = !withinRange
				? "OUT OF RANGE"
				: !inViewCone
					? "OUT OF FOV"
					: "OCCLUDED";
		}
	}

	private bool IsInViewCone(
		PlayerState target,
		float distance
	)
	{
		if ( target?.GameObject is null || _controller is null )
			return false;

		Vector3 toTarget =
			( target.WorldPosition - WorldPosition )
				.WithZ( 0f );

		if ( toTarget.IsNearlyZero( 0.01f ) )
			return true;

		Vector3 forward =
			_controller
				.EyeTransform
				.Rotation
				.Forward
				.WithZ( 0f );

		if ( forward.IsNearlyZero( 0.01f ) )
			forward = WorldRotation.Forward.WithZ( 0f );

		forward = forward.Normal;

		float dot =
			forward.Dot( toTarget.Normal );

		// Nearby opponents are easier to notice in peripheral vision, but never
		// become magically visible behind the bot. The old 360-degree PersonalSpace
		// shortcut was the main source of uncanny close-range 180-degree snaps.
		float effectiveFieldOfView =
			distance <= MathF.Max( 12f, PersonalSpace )
				? MathF.Max( FieldOfView, 155f )
				: FieldOfView;

		float halfAngleRadians =
			MathF.Max( 1f, effectiveFieldOfView ) *
			0.5f *
			MathF.PI /
			180f;

		float threshold =
			MathF.Cos( halfAngleRadians );

		return dot >= threshold;
	}

	private bool HasLineOfSight(
		PlayerState target
	)
	{
		if (
			Scene is null ||
			target?.GameObject is null ||
			_controller is null
		)
			return false;

		Vector3 eyePosition =
			_controller.EyePosition;

		PlayerController targetController =
			target.Components.Get<PlayerController>();

		Vector3 targetEye =
			targetController is not null
				? targetController.EyePosition
				: target.WorldPosition + Vector3.Up * 60f;

		Vector3 targetTorso =
			target.WorldPosition + Vector3.Up * 34f;

		// Two samples make peeking/partial cover behave more naturally: seeing the
		// head OR a central torso point is enough to notice the opponent.
		return
			TraceCanSeeTarget( target, eyePosition, targetEye ) ||
			TraceCanSeeTarget( target, eyePosition, targetTorso );
	}

	private bool TraceCanSeeTarget(
		PlayerState target,
		Vector3 from,
		Vector3 to
	)
	{
		SceneTraceResult trace =
			Scene
				.Trace
				.Ray( from, to )
				.IgnoreGameObjectHierarchy( GameObject )
				.WithoutTags( "trigger" )
				.UseHitboxes( true )
				.Run();

		if ( !trace.Hit )
			return true;

		if ( trace.GameObject == target.GameObject )
			return true;

		// Player collision/hitboxes can live below the PlayerState root. This is
		// the same hierarchy-aware pattern used by Facepunch's current SensesLayer.
		return
			trace.GameObject is not null &&
			target.GameObject.IsDescendant( trace.GameObject );
	}

	private bool HasFreshMemory()
	{
		if ( !HasLastKnownPosition )
			return false;

		float age =
			Time.Now - _lastConfirmedSeenAt;

		return
			age >= 0f &&
			age <= GetMemoryDuration();
	}

	private void UpdatePerceptionTimers()
	{
		if ( HasLastKnownPosition )
		{
			PerceptionLastSeenSeconds =
				MathF.Round(
					MathF.Max( 0f, Time.Now - _lastConfirmedSeenAt ) * 10f
				) / 10f;
		}
		else
		{
			PerceptionLastSeenSeconds = -1f;
		}

		if ( _rawVisibleSince >= 0f && !_hasConfirmedSight )
		{
			PerceptionReactionRemaining =
				MathF.Max(
					0f,
					GetReactionDelay() -
					( Time.Now - _rawVisibleSince )
				);
		}
	}

	private float GetReactionDelay() =>
		Difficulty switch
		{
			OMRBotDifficulty.Easy => EasyReactionDelay,
			OMRBotDifficulty.Hard => HardReactionDelay,
			_ => NormalReactionDelay
		};

	private float GetMemoryDuration() =>
		Difficulty switch
		{
			OMRBotDifficulty.Easy => EasyMemoryDuration,
			OMRBotDifficulty.Hard => HardMemoryDuration,
			_ => NormalMemoryDuration
		};

	private void SweepLook(
		float degreesPerSecond
	)
	{
		if ( _controller is null || degreesPerSecond <= 0f )
			return;

		if ( Time.Now >= _nextSearchTurnAt )
		{
			// Sweep far enough that an opponent who moved behind the bot can
			// eventually re-enter the view cone without the AI consulting their
			// actual position. Faster search modes cover the same arc sooner.
			float sweepArc = 145f;
			float sweepSeconds =
				MathF.Max( 1.0f, sweepArc / degreesPerSecond );

			_nextSearchTurnAt = Time.Now + sweepSeconds;
			_searchTurnDirection *= -1f;
		}

		Angles eyeAngles =
			_controller.EyeAngles;

		_controller.EyeAngles =
			new Angles(
				0f,
				eyeAngles.yaw +
					degreesPerSecond *
					_searchTurnDirection *
					Time.Delta,
				0f
			);
	}


	// =========================================================
	// BOT 5B - HEARING / EVIDENCE
	// =========================================================

	private void UpdateHearing()
	{
		if ( !UsesTacticalBehavior() )
		{
			HearingStatus = "OFF";
			HearingBearing = "NONE";
			HearingAgeSeconds = -1f;
			return;
		}

		PlayerState human = ResolveHumanTarget( _perceptionTarget );
		if ( human?.GameObject is null || !human.IsAlive )
		{
			UpdateHearingDiagnostics();
			return;
		}

		OneMoreRoundWeapon humanWeapon = ResolveActiveWeaponFor( human );
		if ( humanWeapon?.IsValid == true )
		{
			if ( _heardOpponentWeapon != humanWeapon )
			{
				_heardOpponentWeapon = humanWeapon;
				_heardOpponentWeaponEventCount = humanWeapon.PresentationEventCount;
			}
			else if ( humanWeapon.PresentationEventCount != _heardOpponentWeaponEventCount )
			{
				_heardOpponentWeaponEventCount = humanWeapon.PresentationEventCount;

				if ( humanWeapon.LastPresentationEvent == WeaponPresentationEventKind.ShotFired )
				{
					float range = GetGunshotHearingRange( humanWeapon );
					RegisterHeardStimulus(
						human.WorldPosition + Vector3.Up * 42f,
						range,
						"GUNSHOT",
						1.0f
					);
				}
				else if ( humanWeapon.LastPresentationEvent == WeaponPresentationEventKind.ReloadStarted )
				{
					RegisterHeardStimulus(
						human.WorldPosition + Vector3.Up * 36f,
						240f,
						"RELOAD",
						0.35f
					);
				}
			}
		}
		else
		{
			_heardOpponentWeapon = null;
			_heardOpponentWeaponEventCount = -1;
		}

		if ( Time.Now >= _nextMovementHearingAt )
		{
			_nextMovementHearingAt = Time.Now + 0.16f;
			RegisterMovementHearing( human );
		}

		UpdateHearingDiagnostics();
	}

	private OneMoreRoundWeapon ResolveActiveWeaponFor( PlayerState player )
	{
		if ( player?.GameObject is null )
			return null;

		BaseInventoryComponent inventory =
			player.GameObject.Components.Get<BaseInventoryComponent>();
		OneMoreRoundWeapon weapon = inventory?.ActiveItem as OneMoreRoundWeapon;
		return weapon?.IsValid == true ? weapon : null;
	}

	private float GetGunshotHearingRange( OneMoreRoundWeapon weapon )
	{
		string id = ( weapon?.WeaponId ?? string.Empty ).Trim().ToLowerInvariant();
		float baseRange = MathF.Max( 400f, GunshotHearingRange );

		return id switch
		{
			"m700" => baseRange * 1.28f,
			"spm4" => baseRange * 1.08f,
			"m4a1" => baseRange,
			"revolver" => baseRange * 0.92f,
			"mp5" => baseRange * 0.82f,
			"usp" => baseRange * 0.72f,
			_ => baseRange * 0.85f
		};
	}

	private void RegisterMovementHearing( PlayerState human )
	{
		if ( human?.GameObject is null )
			return;

		PlayerController controller = human.GameObject.Components.Get<PlayerController>();
		if ( controller?.IsValid != true )
			return;

		float speed = controller.Velocity.WithZ( 0f ).Length;
		PlayerSprint sprint = human.GameObject.Components.Get<PlayerSprint>();
		PlayerSlide slide = human.GameObject.Components.Get<PlayerSlide>();
		PlayerCrouch crouch = human.GameObject.Components.Get<PlayerCrouch>();

		float range = 0f;
		string kind = string.Empty;
		float confidence = 0f;

		if ( slide?.IsValid == true && slide.IsSliding )
		{
			range = SlideHearingRange;
			kind = "SLIDE";
			confidence = 0.72f;
		}
		else if ( sprint?.IsValid == true && sprint.IsSprinting && speed > 180f )
		{
			range = SprintHearingRange;
			kind = "SPRINT";
			confidence = 0.58f;
		}
		else if ( crouch?.IsValid == true && crouch.WantsCrouch )
		{
			// Crouch walking is intentionally close to silent. This is a gameplay
			// fairness rule, not a simulation claim: a human who deliberately sneaks
			// behind ROOK should not trip a supernatural rear-facing motion sensor.
			if ( speed <= 34f )
				return;

			range =
				WalkHearingRange *
				MathX.Clamp( CrouchHearingRangeScale, 0f, 0.5f );
			kind = "CROUCH STEPS";
			confidence = 0.08f;
		}
		else if ( speed > 85f )
		{
			range = WalkHearingRange * MathX.Clamp( speed / 230f, 0.45f, 1.15f );
			kind = "FOOTSTEPS";
			confidence = 0.38f;
		}

		if ( range <= 1f )
			return;

		RegisterHeardStimulus(
			human.WorldPosition + Vector3.Up * 24f,
			range,
			kind,
			confidence
		);
	}

	private void RegisterHeardStimulus(
		Vector3 sourcePosition,
		float baseRange,
		string kind,
		float baseConfidence
	)
	{
		if ( _controller?.IsValid != true || Scene is null )
			return;

		Vector3 ear = _controller.EyePosition;
		float distance = ( sourcePosition - ear ).Length;
		bool occluded = IsAuditoryPathOccluded( sourcePosition );
		float effectiveRange = MathF.Max( 40f, baseRange );
		if ( occluded )
			effectiveRange *= MathX.Clamp( HearingOcclusionRangeScale, 0.25f, 0.95f );

		if ( distance > effectiveRange )
			return;

		float distanceFraction = MathX.Clamp( distance / effectiveRange, 0f, 1f );
		float difficultyError = Difficulty switch
		{
			OMRBotDifficulty.Easy => 1.40f,
			OMRBotDifficulty.Hard => 0.62f,
			_ => 1.0f
		};

		float uncertainty =
			MathX.Lerp( 24f, 130f, distanceFraction ) *
			difficultyError *
			( occluded ? 1.65f : 1f ) *
			MathX.Lerp( 1.35f, 0.72f, MathX.Clamp( baseConfidence, 0f, 1f ) );

		float errorYaw = Game.Random.Float( -180f, 180f );
		float errorRadius = Game.Random.Float( uncertainty * 0.25f, uncertainty );
		Vector3 noisyOffset =
			Rotation.FromYaw( errorYaw ).Forward.WithZ( 0f ).Normal * errorRadius;

		_lastHeardPosition = sourcePosition + noisyOffset;
		_lastHeardAt = Time.Now;
		_lastHeardKind = string.IsNullOrWhiteSpace( kind ) ? "SOUND" : kind;
		_lastHeardConfidence =
			MathX.Clamp(
				baseConfidence * ( 1f - distanceFraction * 0.45f ) * ( occluded ? 0.72f : 1f ),
				0.08f,
				1f
			);
	}

	private bool IsAuditoryPathOccluded( Vector3 sourcePosition )
	{
		if ( Scene is null || _controller?.IsValid != true )
			return false;

		SceneTrace trace =
			Scene.Trace
				.Ray( _controller.EyePosition, sourcePosition )
				.IgnoreGameObjectHierarchy( GameObject )
				.WithoutTags( "trigger" )
				.UseHitboxes( false );

		if ( _perceptionTarget?.GameObject is not null )
			trace = trace.IgnoreGameObjectHierarchy( _perceptionTarget.GameObject );

		return trace.Run().Hit;
	}

	private bool HasFreshHearing() =>
		_lastHeardAt > 0f &&
		Time.Now - _lastHeardAt <= MathF.Max( 0.75f, HearingMemoryDuration );

	private bool HasActionableHearing()
	{
		if ( !HasFreshHearing() || _controller?.IsValid != true )
			return false;

		Vector3 planar =
			( _lastHeardPosition - WorldPosition )
				.WithZ( 0f );

		if ( planar.IsNearlyZero( 0.01f ) )
			return true;

		Vector3 forward =
			_controller.EyeTransform.Rotation.Forward.WithZ( 0f );

		if ( forward.IsNearlyZero( 0.01f ) )
			forward = WorldRotation.Forward.WithZ( 0f );

		forward = forward.Normal;
		float dot = forward.Dot( planar.Normal );

		// Rear sounds require much stronger evidence before the bot commits to an
		// investigation. Gunshots/slides/sprints can still trigger it; quiet steps
		// cannot cause an uncanny instant 180-degree response.
		float threshold =
			dot <= -0.35f
				? MathX.Clamp( RearHearingConfidenceThreshold, 0f, 1f )
				: dot <= 0.35f
					? MathX.Clamp( SideHearingConfidenceThreshold, 0f, 1f )
					: 0.16f;

		if ( string.Equals( _lastHeardKind, "CROUCH STEPS", StringComparison.OrdinalIgnoreCase ) )
			threshold = MathF.Max( threshold, 0.65f );

		return _lastHeardConfidence >= threshold;
	}

	private void UpdateHearingDiagnostics()
	{
		if ( HasFreshHearing() )
		{
			string action = HasActionableHearing() ? "ACTION" : "NOTICE ONLY";
			HearingStatus = $"{_lastHeardKind} · CONF {_lastHeardConfidence * 100f:0}% · {action}";
			HearingAgeSeconds = MathF.Round( MathF.Max( 0f, Time.Now - _lastHeardAt ) * 10f ) / 10f;
			HearingBearing = DescribeWorldBearing( _lastHeardPosition - WorldPosition );
		}
		else
		{
			HearingStatus = "NONE";
			HearingBearing = "NONE";
			HearingAgeSeconds = -1f;
		}
	}

	private string DescribeWorldBearing( Vector3 direction )
	{
		if ( _controller?.IsValid != true || direction.WithZ( 0f ).IsNearlyZero( 0.01f ) )
			return "NONE";

		float targetYaw = Rotation.LookAt( direction.WithZ( 0f ).Normal, Vector3.Up ).Angles().yaw;
		float delta = MathX.DeltaDegrees( _controller.EyeAngles.yaw, targetYaw );
		float abs = MathF.Abs( delta );

		if ( abs <= 22.5f ) return "FRONT";
		if ( abs >= 157.5f ) return "REAR";
		if ( delta > 0f )
			return abs <= 67.5f ? "RIGHT" : abs <= 112.5f ? "REAR-RIGHT" : "REAR-RIGHT";
		return abs <= 67.5f ? "LEFT" : abs <= 112.5f ? "REAR-LEFT" : "REAR-LEFT";
	}


	// =========================================================
	// BOT 3 - COMBAT
	// =========================================================

	private void UpdateCombat()
	{
		if ( !CanUseNavigation() )
		{
			PerceptionStatus = "WAITING";
			ReleaseBotWeaponIntent();
			ResetCombatDiagnostics( "WAITING" );
			return;
		}

		UpdateModifierAwareness();
		UpdateDynamicTacticalVariation();
		UpdatePerception();
		UpdatePerceptionTimers();
		UpdateSpatialOpponentMemory();
		UpdateHearing();
		UpdateThreatMemory();
		OneMoreRoundWeapon weapon = ResolveActiveWeapon();
		RefreshCombatSequenceContext( weapon );
		if ( ShouldSampleStrategy( weapon ) )
		{
			UpdatePlayerPrediction();
			UpdateOpponentBelief();
			UpdateOpponentLearning();
			UpdateTacticalContext();
			RefreshBrainArchitecture( weapon );
		}
		UpdateTacticalMapContext( weapon );
		UpdateCombatAmmoDiagnostics( weapon );

		if ( _hasConfirmedSight )
			InitiativeStatus = "CONTACT";
		else if ( HasFreshMemory() || HasActionableHearing() || HasRecentThreat() )
			InitiativeStatus = "EVIDENCE";

		if ( UsesTacticalBehavior() && TryHandleHighNoonBehavior( weapon ) )
			return;

		// Automatic weapons get a tiny, fair stale-contact retention window before
		// strategic search takes over. This uses only the last observed aim sample.
		if ( !_hasConfirmedSight && TryHandleAutomaticTargetRetention( weapon ) )
			return;

		if ( UsesTacticalBehavior() && TryHandleTacticalPriority( weapon ) )
			return;

		if ( PerceptionStatus == "REACTING" )
		{
			ReleaseBotWeaponIntent( weapon );
			_pathPoints.Clear();
			_pathPointIndex = 0;

			if ( UsesTacticalBehavior() )
				MaintainReactionMomentum();
			else
				StopMovementOnly();

			NavigationStatus = "REACTING";
			NavigationTargetName = "NONE";
			NavigationTargetDistance = 0f;
			CurrentIntent = "REACTION DELAY / HOLD";
			CombatStatus = "REACTION DELAY";
			return;
		}

		if ( _hasConfirmedSight && _perceptionTarget?.IsAlive == true )
		{
			UpdateVisibleCombat( weapon );
			return;
		}

		ReleaseBotWeaponIntent( weapon );
		TryReloadWhileSafe( weapon );
		CombatAimError = 0f;
		CombatWantsAim = false;

		if ( HasFreshMemory() )
		{
			Vector3 toLastKnown =
				( LastKnownPosition - WorldPosition )
					.WithZ( 0f );

			CombatStatus = weapon?.IsReloading == true
				? "RELOADING IN COVER"
				: "NO VISUAL / MEMORY";

			if ( toLastKnown.Length <= SearchStopDistance )
			{
				_pathPoints.Clear();
				_pathPointIndex = 0;
				StopMovementOnly();
				NavigationStatus = "SEARCHING";
				NavigationTargetName = "LAST KNOWN";
				NavigationTargetDistance = MathF.Round( toLastKnown.Length );
				CurrentIntent = "COMBAT SEARCH / LAST KNOWN";
				SweepLook( SearchSweepSpeed );
				return;
			}

			NavigateToWorldPosition(
				LastKnownPosition,
				"LAST KNOWN",
				SearchStopDistance,
				"COMBAT SEARCHING LAST KNOWN",
				allowSprint: true,
				faceMovement: true,
				advancedMovement: UsesAdvancedMovement(),
				movementWeapon: weapon,
				visibleCombatTarget: false
			);
			return;
		}

		if ( TryHandleProactiveNoContact( weapon ) )
			return;

		_pathPoints.Clear();
		_pathPointIndex = 0;
		StopMovementOnly();
		NavigationStatus = "IDLE";
		NavigationTargetName = "NONE";
		NavigationTargetDistance = 0f;
		CurrentIntent = "COMBAT / NO CONTACT / SCANNING";
		CombatStatus = weapon?.IsReloading == true
			? "RELOADING / NO CONTACT"
			: "NO CONTACT";
		SweepLook( IdleSweepSpeed );
	}

	private void UpdateVisibleCombat( OneMoreRoundWeapon weapon )
	{
		if ( weapon?.IsValid != true )
		{
			CombatStatus = "NO ACTIVE WEAPON";
			CombatAimError = 0f;
			CombatWantsAim = false;
			NavigateToWorldPosition(
				_observedTargetPosition,
				_perceptionTarget.DisplayName,
				StopDistance,
				"COMBAT / UNARMED APPROACH",
				allowSprint: false
			);
			return;
		}

		if ( _lastCombatWeapon != weapon )
		{
			if ( _lastCombatWeapon?.IsValid == true )
				_lastCombatWeapon.SetBotAimIntent( false );

			_lastCombatWeapon = weapon;
			_nextBotTriggerAt = 0f;
		}

		float distance =
			( _observedTargetPosition - WorldPosition )
				.WithZ( 0f )
				.Length;

		float holdDistance = GetCombatHoldDistance( weapon );

		if ( UsesTacticalBehavior() )
		{
			// Health/context changes *how strongly* the bot presses without changing
			// the weapon's underlying preferred role. High aggression closes the
			// distance modestly; low aggression gives the weapon a little more room.
			holdDistance *=
				MathX.Lerp(
					1.12f,
					0.88f,
					MathX.Clamp( TacticalAggression, 0f, 1f )
				);
		}

		// BOT 7D may deliberately press closer or preserve more space. The actual
		// movement/weapon execution below remains the same shared player-equivalent
		// pipeline.
		holdDistance *= GetUtilityRangeScale();

		bool shouldAdvance = distance > holdDistance;

		// Aim at the most recent *observed* sample from BOT 2. Do not read the
		// target's live transform here; if they duck behind cover between
		// perception scans, combat keeps aiming at the stale seen point until the
		// next scan revokes visibility.
		UpdateCombatAim( _observedTargetAimPoint );

		bool advancedMovement =
			UsesAdvancedMovement();

		bool wantsAds = ShouldUseAds( weapon, distance );

		CombatWantsAim = wantsAds;
		weapon.SetBotAimIntent( wantsAds );

		if ( shouldAdvance )
		{
			NavigateToWorldPosition(
				_observedTargetPosition,
				_perceptionTarget.DisplayName,
				holdDistance,
				"COMBAT APPROACH",
				allowSprint: advancedMovement && !_hasConfirmedSight,
				faceMovement: false,
				advancedMovement: advancedMovement,
				movementWeapon: weapon,
				visibleCombatTarget: true
			);
		}
		else if ( advancedMovement )
		{
			UpdateCombatStrafe( weapon, distance, holdDistance );
		}
		else
		{
			_pathPoints.Clear();
			_pathPointIndex = 0;
			StopMovementOnly();
			NavigationStatus = "COMBAT HOLD";
			NavigationTargetName = _perceptionTarget.DisplayName;
			NavigationTargetDistance = MathF.Round( distance );
			CurrentIntent = "COMBAT / HOLDING RANGE";
		}

		UpdateVisibleWeaponAttack( weapon, distance, wantsAds );
	}

	private void UpdateVisibleWeaponAttack(
		OneMoreRoundWeapon weapon,
		float distance,
		bool wantsAds
	)
	{
		UpdateCombatAmmoDiagnostics( weapon );

		if ( weapon?.IsValid != true )
		{
			CombatStatus = "NO ACTIVE WEAPON";
			return;
		}

		if ( weapon.IsReloading )
		{
			CombatStatus = "RELOADING";
			return;
		}

		if ( weapon.Clip1 == 0 )
		{
			weapon.SetBotAimIntent( false );
			CombatWantsAim = false;

			if ( weapon.BotTryReload() )
				CombatStatus = "STARTING RELOAD";
			else
				CombatStatus = "EMPTY / CANNOT RELOAD";

			return;
		}

		if ( weapon.IsCyclePendingOrActive )
		{
			CombatStatus = "CYCLING";
			return;
		}

		float maximumFireDistance = GetMaximumFireDistance( weapon );
		if ( distance > maximumFireDistance )
		{
			CombatStatus = "CLOSING TO FIRE RANGE";
			return;
		}

		if (
			wantsAds &&
			weapon.IsAiming &&
			weapon.AimFraction < MathX.Clamp( MinimumAdsReadyFraction, 0f, 1f )
		)
		{
			CombatStatus = "SETTLING ADS";
			return;
		}

		float tolerance = GetFireToleranceDegrees();
		if ( weapon.IsAutomaticWeapon )
			tolerance *= MathF.Max( 1f, AutomaticFireToleranceScale );

		if ( weapon.IsAutomaticWeapon
			? !AllowAutomaticTrackingFire( weapon, tolerance )
			: CombatAimError > tolerance )
		{
			CombatStatus = $"ALIGNING ({CombatAimError:0.0}°)";
			return;
		}

		if ( Time.Now < _nextBotTriggerAt )
		{
			CombatStatus = "TRIGGER RESET";
			return;
		}

		if ( !TryAllowCombatSequenceShot( weapon, distance, out string sequenceHoldReason ) )
		{
			CombatStatus = sequenceHoldReason;
			return;
		}

		if ( weapon.BotTryPrimaryFire() )
		{
			OnCombatSequenceShotFired( weapon, distance );
			CombatStatus = weapon.IsAutomaticWeapon ? "AUTOMATIC FIRE" : "FIRED";
			_nextBotTriggerAt = Time.Now + GetCombatSequenceTriggerInterval( weapon );
			UpdateCombatAmmoDiagnostics( weapon );
			return;
		}

		CombatStatus = weapon.CanPrimaryAttack()
			? "HOLDING FIRE"
			: weapon.ActionState.ToString().ToUpperInvariant();
	}

	private OneMoreRoundWeapon ResolveActiveWeapon()
	{
		if ( _inventory?.IsValid != true )
			_inventory = Components.Get<BaseInventoryComponent>();

		if ( _inventory?.IsValid != true )
			return null;

		OneMoreRoundWeapon weapon =
			_inventory.ActiveItem as OneMoreRoundWeapon;

		return weapon?.IsValid == true
			? weapon
			: null;
	}

	private void UpdateCombatAmmoDiagnostics( OneMoreRoundWeapon weapon )
	{
		if ( weapon?.IsValid != true )
		{
			CombatClip = -1;
			CombatReserve = -1;
			return;
		}

		CombatClip = weapon.Clip1;
		CombatReserve = weapon.Ammo1;
	}

	private void ReleaseBotWeaponIntent( OneMoreRoundWeapon weapon = null )
	{
		if ( weapon?.IsValid != true )
			weapon = ResolveActiveWeapon();

		if ( weapon?.IsValid == true )
			weapon.SetBotAimIntent( false );

		CombatWantsAim = false;
	}

	private void SafeReleaseLastCombatWeapon()
	{
		if ( _lastCombatWeapon?.IsValid == true )
		{
			try
			{
				_lastCombatWeapon.SetBotAimIntent( false );
			}
			catch
			{
				// Lifecycle cleanup must never generate a second exception while
				// handling the original invalidation.
			}
		}

		_lastCombatWeapon = null;
		CombatWantsAim = false;
	}

	private void TryReloadWhileSafe( OneMoreRoundWeapon weapon )
	{
		if ( weapon?.IsValid != true || weapon.IsReloading )
			return;

		bool empty = weapon.Clip1 == 0;
		bool tacticalLargeCaliberReload =
			ActiveModifierIs( RoundModifier.LargeCaliber ) &&
			weapon.UsesPrimaryClip &&
			weapon.PrimaryClipSize > 0 &&
			weapon.Ammo1 > 0 &&
			weapon.Clip1 > 0 &&
			weapon.Clip1 <= Math.Max( 1, (int)MathF.Floor( weapon.PrimaryClipSize * 0.28f ) );

		if ( !empty && !tacticalLargeCaliberReload )
			return;

		weapon.BotTryReload();
		UpdateCombatAmmoDiagnostics( weapon );
	}

	private Vector3 ResolveCombatAimPoint( PlayerState target )
	{
		if ( target?.GameObject is null )
			return _observedTargetPosition + Vector3.Up * 48f;

		PlayerController targetController =
			target.Components.Get<PlayerController>();

		Vector3 torso = target.WorldPosition + Vector3.Up * 34f;
		Vector3 eye = targetController is not null
			? targetController.EyePosition
			: target.WorldPosition + Vector3.Up * 60f;

		if ( ActiveModifierIs( RoundModifier.HeadshotOnly ) )
		{
			// The target is currently confirmed visible, so using the observed eye/head
			// sample is fair. Difficulty still matters through aim noise/follow speed
			// and fire tolerance rather than by deliberately aiming at the torso.
			return eye - Vector3.Up * 2f;
		}

		float eyeBias = Difficulty switch
		{
			OMRBotDifficulty.Easy => 0.30f,
			OMRBotDifficulty.Hard => 0.72f,
			_ => 0.52f
		};

		return torso + ( eye - torso ) * eyeBias;
	}

	private void UpdateCombatAim( Vector3 aimPoint )
	{
		if ( _controller is null )
			return;

		Vector3 from = _controller.EyePosition;
		Vector3 trueDirection = ResolveTrackedAimPoint( aimPoint ) - from;
		if ( trueDirection.IsNearlyZero( 0.001f ) )
			return;

		Angles trueAngles =
			Rotation.LookAt( trueDirection.Normal, Vector3.Up ).Angles();

		float noise = GetAimNoiseDegrees();
		float phase = Time.Now + BotSlot * 0.71f;
		float yawNoise = MathF.Sin( phase * 1.73f ) * noise;
		float pitchNoise = MathF.Sin( phase * 1.19f + 1.4f ) * noise * 0.55f;

		Angles noisyAngles = new(
			trueAngles.pitch + pitchNoise,
			trueAngles.yaw + yawNoise,
			0f
		);

		float followSpeed = GetAimFollowSpeed();
		float follow = 1f - MathF.Exp(
			-MathF.Max( followSpeed, 0.01f ) * MathF.Max( Time.Delta, 0f )
		);

		Rotation smoothed = Rotation.Slerp(
			_controller.EyeAngles.ToRotation(),
			noisyAngles.ToRotation(),
			MathX.Clamp( follow, 0f, 1f )
		);

		Angles resolved = smoothed.Angles();
		_controller.EyeAngles = new Angles(
			MathX.Clamp( resolved.pitch, -89f, 89f ),
			resolved.yaw,
			0f
		);

		float pitchError = MathF.Abs(
			MathX.DeltaDegrees( _controller.EyeAngles.pitch, trueAngles.pitch )
		);
		float yawError = MathF.Abs(
			MathX.DeltaDegrees( _controller.EyeAngles.yaw, trueAngles.yaw )
		);

		CombatAimError = MathF.Sqrt(
			pitchError * pitchError + yawError * yawError
		);
	}

	private bool ShouldUseAds( OneMoreRoundWeapon weapon, float distance )
	{
		if ( weapon is null || !weapon.AllowAim || !weapon.RoundAllowsAim )
			return false;

		if ( ActiveModifierIs( RoundModifier.HighNoon ) )
			return false;

		OMRBotWeaponDoctrine doctrine = GetWeaponDoctrine( weapon );
		if ( doctrine.LegacyDisableAds )
			return false;

		float threshold =
			ActiveModifierIs( RoundModifier.HeadshotOnly )
				? doctrine.LegacyHeadshotAdsStartDistance
				: doctrine.LegacyAdsStartDistance;

		return distance >= threshold;
	}

	private float GetCombatHoldDistance( OneMoreRoundWeapon weapon )
	{
		OMRBotWeaponDoctrine doctrine = GetWeaponDoctrine( weapon );
		float distance = doctrine.LegacyHoldDistance;

		if ( ActiveModifierIs( RoundModifier.HipfireOnly ) )
			distance *= 0.78f;
		else if ( ActiveModifierIs( RoundModifier.HeadshotOnly ) )
			distance *= 1.10f;
		else if ( ActiveModifierIs( RoundModifier.LargeCaliber ) )
			distance *= 1.06f;

		distance *= GetAdaptiveHoldDistanceScale( weapon );
		return distance;
	}

	private float GetMaximumFireDistance( OneMoreRoundWeapon weapon )
	{
		OMRBotWeaponDoctrine doctrine = GetWeaponDoctrine( weapon );
		float distance = doctrine.LegacyMaximumFireDistance;

		if ( ActiveModifierIs( RoundModifier.HipfireOnly ) )
			distance *= 0.72f;

		return distance;
	}

	private float GetAimFollowSpeed() =>
		Difficulty switch
		{
			OMRBotDifficulty.Easy => EasyAimFollowSpeed,
			OMRBotDifficulty.Hard => HardAimFollowSpeed,
			_ => NormalAimFollowSpeed
		};

	private float GetAimNoiseDegrees() =>
		Difficulty switch
		{
			OMRBotDifficulty.Easy => EasyAimNoiseDegrees,
			OMRBotDifficulty.Hard => HardAimNoiseDegrees,
			_ => NormalAimNoiseDegrees
		};

	private float GetFireToleranceDegrees()
	{
		float tolerance = Difficulty switch
		{
			OMRBotDifficulty.Easy => EasyFireToleranceDegrees,
			OMRBotDifficulty.Hard => HardFireToleranceDegrees,
			_ => NormalFireToleranceDegrees
		};

		if ( ActiveModifierIs( RoundModifier.HeadshotOnly ) )
			tolerance *= 0.78f;
		else if ( ActiveModifierIs( RoundModifier.HipfireOnly ) )
			tolerance *= 1.08f;

		return tolerance;
	}

	private float GetBotTriggerInterval( OneMoreRoundWeapon weapon )
	{
		float authored = MathF.Max( weapon?.PrimaryDelay ?? 0.1f, 0.01f );
		float humanDelay = weapon?.IsAutomaticWeapon == true
			? Difficulty switch
			{
				OMRBotDifficulty.Easy => 0.020f,
				OMRBotDifficulty.Hard => 0.003f,
				_ => 0.008f
			}
			: Difficulty switch
			{
				OMRBotDifficulty.Easy => 0.075f,
				OMRBotDifficulty.Hard => 0.015f,
				_ => 0.035f
			};

		float interval = authored + humanDelay;

		if ( ActiveModifierIs( RoundModifier.LargeCaliber ) )
			interval += 0.045f;
		else if ( ActiveModifierIs( RoundModifier.HeadshotOnly ) )
			interval += 0.030f;
		else if ( ActiveModifierIs( RoundModifier.Blitz ) )
			interval -= 0.010f;

		return MathF.Max(
			interval,
			MathF.Max( MinimumTriggerReset, 0.01f )
		);
	}

	private void ResetCombatDiagnostics( string status )
	{
		CombatStatus = status;
		CombatAimError = 0f;
		CombatWantsAim = false;
		CombatClip = -1;
		CombatReserve = -1;
	}

	// =========================================================
	// BOT 4 - PLAYER-EQUIVALENT MOVEMENT
	// =========================================================

	private void UpdateCombatStrafe(
		OneMoreRoundWeapon weapon,
		float distance,
		float holdDistance
	)
	{
		if ( FluidMovementEnabled )
		{
			UpdateFluidCombatMovement( weapon, distance, holdDistance );
			return;
		}

		UpdateLegacyCombatStrafe( weapon, distance, holdDistance );
	}

	private void UpdateLegacyCombatStrafe(
		OneMoreRoundWeapon weapon,
		float distance,
		float holdDistance
	)
	{
		_pathPoints.Clear();
		_pathPointIndex = 0;

		NavigationStatus = "COMBAT STRAFE";
		NavigationTargetName = _perceptionTarget?.DisplayName ?? "PLAYER";
		NavigationTargetDistance = MathF.Round( distance );

		if ( Time.Now >= _nextStrafeSwitchAt )
		{
			// Usually reverse, occasionally keep the current side for one more beat.
			// The latter prevents a perfectly learnable left/right metronome.
			float keepChance =
				MathX.Clamp(
					0.12f + MathF.Max( 0f, _dynamicMovementBias ) * 0.35f,
					0.08f,
					0.28f
				);

			if ( Game.Random.Float( 0f, 1f ) > keepChance )
				_strafeDirection *= -1f;

			_nextStrafeSwitchAt =
				Time.Now + MathF.Max( 0.38f, GetStrafeSwitchInterval() );
		}

		float forward = 0f;
		float retreatDistance =
			holdDistance * MathX.Clamp( RetreatDistanceScale, 0.35f, 0.9f );

		if ( distance < retreatDistance )
			forward = -0.62f;
		else if ( distance > holdDistance * 0.92f )
			forward = 0.22f;

		float lateral =
			MathX.Clamp( StrafeStrength, 0.2f, 1f ) * _strafeDirection;

		Vector3 moveInput =
			new Vector3( forward, lateral, 0f )
				.ClampLength( 1f );

		bool crouchDown = false;
		bool jumpPressed = false;
		bool sprint = false;

		ApplyCombatEvasionActions(
			weapon,
			distance,
			ref crouchDown,
			ref jumpPressed
		);

		_movementInput.SetBotInput(
			moveInput,
			sprintDown: sprint,
			crouchDown: crouchDown,
			jumpPressed: jumpPressed
		);

		string direction = _strafeDirection >= 0f ? "RIGHT" : "LEFT";

		if ( _slide?.IsSliding == true )
		{
			SetMovementDiagnostics( "SLIDE" );
			CurrentIntent = "COMBAT / SLIDING";
		}
		else if ( jumpPressed )
		{
			SetMovementDiagnostics( _controller.IsAirborne ? "AIR JUMP REQUEST" : "JUMP REQUEST" );
			CurrentIntent = $"COMBAT / STRAFE {direction} / JUMP";
		}
		else if ( _controller?.IsDucking == true || _crouch?.WantsCrouch == true )
		{
			SetMovementDiagnostics( $"CROUCH STRAFE {direction}" );
			CurrentIntent = $"COMBAT / CROUCH STRAFE {direction}";
		}
		else if ( forward < -0.01f )
		{
			SetMovementDiagnostics( $"RETREAT + STRAFE {direction}" );
			CurrentIntent = $"COMBAT / RETREAT + STRAFE {direction}";
		}
		else
		{
			SetMovementDiagnostics( $"STRAFE {direction}" );
			CurrentIntent = $"COMBAT / STRAFE {direction}";
		}
	}

	private void ApplyAdvancedTraversalActions(
		OneMoreRoundWeapon weapon,
		float targetDistance,
		bool visibleCombatTarget,
		ref bool sprint,
		ref bool crouchDown,
		ref bool jumpPressed
	)
	{
		if ( _controller?.IsValid != true )
			return;

		UpdateScheduledCrouchRelease();

		// If a round grants an extra air jump, this synthetic second press will be
		// accepted by PlayerLocomotion. Standard rounds simply ignore it. This keeps
		// BOT 4 compatible with Double Jump without reading or bypassing the rule.
		if (
			_airJumpAttemptPending &&
			_controller.IsAirborne &&
			Time.Now >= _airJumpAttemptAt
		)
		{
			jumpPressed = true;
			_airJumpAttemptPending = false;
		}

		bool canSlide =
			visibleCombatTarget &&
			CanUseSlideWithWeapon( weapon ) &&
			targetDistance >= SlideMinimumTargetDistance &&
			targetDistance <= SlideMaximumTargetDistance &&
			Time.Now >= _nextSlideAt &&
			_controller.IsOnGround &&
			_slide?.IsValid == true &&
			!_slide.IsSliding &&
			_sprint?.IsSprinting == true &&
			_controller.Velocity.WithZ( 0f ).Length >= _slide.MinimumStartSpeed;

		if ( canSlide )
		{
			PulseCrouchButton();
			_nextSlideAt = Time.Now + MathF.Max( 1.5f, GetSlideCooldown() );
		}

		crouchDown = GetBotCrouchButtonDown();
	}

	private void ApplyCombatEvasionActions(
		OneMoreRoundWeapon weapon,
		float targetDistance,
		ref bool crouchDown,
		ref bool jumpPressed
	)
	{
		if ( _controller?.IsValid != true )
			return;

		UpdateScheduledCrouchRelease();

		if (
			_airJumpAttemptPending &&
			_controller.IsAirborne &&
			Time.Now >= _airJumpAttemptAt
		)
		{
			jumpPressed = true;
			_airJumpAttemptPending = false;
		}

		float jumpMinDistance = JumpMinimumTargetDistance;
		float jumpMaxDistance = JumpMaximumTargetDistance;

		if ( ActiveModifierIs( RoundModifier.DoubleJump ) )
		{
			jumpMinDistance *= 0.72f;
			jumpMaxDistance *= 1.42f;
		}
		else if ( ActiveModifierIs( RoundModifier.LowGravity ) )
		{
			jumpMinDistance *= 0.82f;
			jumpMaxDistance *= 1.28f;
		}

		bool canGroundJump =
			!jumpPressed &&
			_controller.IsOnGround &&
			Time.Now >= _nextJumpAt &&
			targetDistance >= jumpMinDistance &&
			targetDistance <= jumpMaxDistance &&
			!IsPrecisionMovementWeapon( weapon ) &&
			_slide?.IsSliding != true &&
			_crouch?.WantsCrouch != true;

		if ( canGroundJump )
		{
			float jumpChance =
				MathX.Clamp(
					0.72f + _dynamicMovementBias * 0.75f,
					0.38f,
					0.92f
				);

			if ( ActiveModifierIs( RoundModifier.DoubleJump ) )
				jumpChance = MathF.Min( 0.96f, jumpChance + 0.16f );
			else if ( ActiveModifierIs( RoundModifier.LowGravity ) )
				jumpChance = MathF.Min( 0.92f, jumpChance + 0.10f );

			if ( Game.Random.Float( 0f, 1f ) <= jumpChance )
			{
				jumpPressed = true;
				_nextJumpAt = Time.Now + MathF.Max( 1.25f, GetJumpCooldown() );

				bool hasExtraAirJump =
					ActiveModifierIs( RoundModifier.DoubleJump ) ||
					( _activeRoundRule?.AdditionalAirJumps ?? 0 ) > 0;

				_airJumpAttemptPending = hasExtraAirJump;
				_airJumpAttemptAt =
					Time.Now + Game.Random.Float( 0.20f, 0.31f );
			}
			else
			{
				_nextJumpAt = Time.Now + Game.Random.Float( 0.45f, 0.85f );
			}
		}

		bool canStartCrouchDodge =
			!jumpPressed &&
			_controller.IsOnGround &&
			_slide?.IsSliding != true &&
			_crouch?.IsValid == true &&
			!_crouch.WantsCrouch &&
			Time.Now >= _nextCrouchDodgeAt &&
			targetDistance <= MathF.Max( 520f, GetCombatHoldDistance( weapon ) * 1.25f );

		if ( canStartCrouchDodge )
		{
			PulseCrouchButton();
			_crouchDodgeEndAt =
				Time.Now + MathF.Max( 0.25f, CrouchDodgeDuration );
			_nextCrouchDodgeAt =
				Time.Now + MathF.Max( 2.5f, GetCrouchDodgeCooldown() );
		}

		crouchDown = GetBotCrouchButtonDown();
	}

	private void UpdateScheduledCrouchRelease()
	{
		bool slidingNow =
			_slide?.IsValid == true && _slide.IsSliding;

		// A slide is entered through the same crouch press as a human. If sprint
		// stops before locomotion has a chance to clear that crouch intent, send the
		// matching release-toggle after the slide so ROOK does not stay crouched by
		// accident.
		if (
			_wasSliding &&
			!slidingNow &&
			_crouchDodgeEndAt < 0f &&
			_crouch?.IsValid == true &&
			_crouch.WantsCrouch
		)
		{
			PulseCrouchButton();
		}

		_wasSliding = slidingNow;

		if (
			_airJumpAttemptPending &&
			_controller?.IsOnGround == true &&
			Time.Now >= _airJumpAttemptAt + 0.35f
		)
		{
			_airJumpAttemptPending = false;
		}

		if (
			_crouchDodgeEndAt < 0f ||
			Time.Now < _crouchDodgeEndAt
		)
			return;

		_crouchDodgeEndAt = -1f;

		if ( _crouch?.IsValid == true && _crouch.WantsCrouch )
			PulseCrouchButton();
	}

	private void PulseCrouchButton()
	{
		_crouchButtonHeldUntil =
			MathF.Max( _crouchButtonHeldUntil, Time.Now + 0.08f );
	}

	private bool GetBotCrouchButtonDown() =>
		Time.Now < _crouchButtonHeldUntil;

	private bool CanUseSlideWithWeapon( OneMoreRoundWeapon weapon ) =>
		GetWeaponDoctrine( weapon ).CanUseCombatSlide;

	private bool IsPrecisionMovementWeapon( OneMoreRoundWeapon weapon ) =>
		GetWeaponDoctrine( weapon ).IsPrecisionMovementWeapon;

	private float GetStrafeSwitchInterval()
	{
		float interval = Difficulty switch
		{
			OMRBotDifficulty.Easy => StrafeSwitchInterval * 1.35f,
			OMRBotDifficulty.Hard => StrafeSwitchInterval * 0.78f,
			_ => StrafeSwitchInterval
		};

		interval *=
			MathX.Clamp( 1f + _dynamicMovementBias * 0.75f, 0.68f, 1.30f );

		if ( ActiveModifierIs( RoundModifier.Blitz ) )
			interval *= 0.82f;
		else if ( ActiveModifierIs( RoundModifier.HipfireOnly ) )
			interval *= 0.88f;

		// Randomize each committed strafe window, not every frame. This preserves
		// readable movement while removing the metronomic left/right rhythm.
		interval *= Game.Random.Float( 0.82f, 1.18f );

		return MathF.Max( 0.38f, interval );
	}

	private float GetSlideCooldown() =>
		Difficulty switch
		{
			OMRBotDifficulty.Easy => SlideCooldown * 1.35f,
			OMRBotDifficulty.Hard => SlideCooldown * 0.82f,
			_ => SlideCooldown
		};

	private float GetJumpCooldown()
	{
		float cooldown = Difficulty switch
		{
			OMRBotDifficulty.Easy => JumpCooldown * 1.35f,
			OMRBotDifficulty.Hard => JumpCooldown * 0.80f,
			_ => JumpCooldown
		};

		if ( ActiveModifierIs( RoundModifier.DoubleJump ) )
			cooldown *= 0.58f;
		else if ( ActiveModifierIs( RoundModifier.LowGravity ) )
			cooldown *= 0.72f;
		else if ( ActiveModifierIs( RoundModifier.Blitz ) )
			cooldown *= 0.82f;

		cooldown *=
			MathX.Clamp( 1f - _dynamicMovementBias * 0.55f, 0.72f, 1.28f );

		return MathF.Max( 1.25f, cooldown );
	}

	private float GetCrouchDodgeCooldown() =>
		Difficulty switch
		{
			OMRBotDifficulty.Easy => CrouchDodgeCooldown * 1.35f,
			OMRBotDifficulty.Hard => CrouchDodgeCooldown * 0.82f,
			_ => CrouchDodgeCooldown
		};

	private void SetMovementDiagnostics( string status )
	{
		MovementStatus = status;
		MovementSpeed =
			_controller?.IsValid == true
				? MathF.Round( _controller.Velocity.WithZ( 0f ).Length )
				: 0f;
	}


	// =========================================================
	// BOT 5A + 5B - TACTICAL COMBAT / SEARCH / HEARING
	// =========================================================

	private bool UsesAdvancedMovement() =>
		BehaviorMode == OMRBotBehaviorMode.CombatMovement ||
		BehaviorMode == OMRBotBehaviorMode.TacticalCombat;

	private bool UsesTacticalBehavior() =>
		BehaviorMode == OMRBotBehaviorMode.TacticalCombat;


	private bool TryHandleSuppressiveFire( OneMoreRoundWeapon weapon )
	{
		if ( !UsesTacticalBehavior() || weapon?.IsValid != true )
			return false;

		if ( _hasConfirmedSight )
		{
			_suppressionUntil = -1f;
			_suppressionShotsRemaining = 0;
			SuppressionStatus = "NONE";
			return false;
		}

		if ( Time.Now < _suppressionUntil && _suppressionShotsRemaining > 0 )
		{
			if ( weapon.IsReloading || weapon.Clip1 <= 0 )
			{
				_suppressionUntil = -1f;
				_suppressionShotsRemaining = 0;
				SuppressionStatus = "ABORT / AMMO";
				return false;
			}

			UpdateSuppressiveMovement();
			UpdateCombatAim( _suppressionAimPoint );
			float distance = ( _suppressionAimPoint - WorldPosition ).WithZ( 0f ).Length;
			bool wantsAds = ShouldUseAds( weapon, distance );
			CombatWantsAim = wantsAds;
			weapon.SetBotAimIntent( wantsAds );

			if ( Time.Now >= _nextBotTriggerAt && CombatAimError <= GetFireToleranceDegrees() * 1.55f )
			{
				if ( weapon.BotTryPrimaryFire() )
				{
					_suppressionShotsRemaining--;
					_nextBotTriggerAt = Time.Now + GetBotTriggerInterval( weapon );
				}
			}

			SuppressionStatus = $"BURST · {_suppressionShotsRemaining} LEFT";
			TacticalStatus = "SUPPRESS LAST SEEN";
			CombatStatus = "SUPPRESSIVE FIRE";
			NavigationStatus = "SUPPRESSING";
			NavigationTargetName = "LAST SEEN";
			NavigationTargetDistance = MathF.Round( distance );
			CurrentIntent = "TACTICAL / SUPPRESSIVE FIRE";

			if ( _suppressionShotsRemaining <= 0 || Time.Now >= _suppressionUntil )
			{
				_suppressionUntil = -1f;
				_suppressionShotsRemaining = 0;
				SuppressionStatus = "COMPLETE";
			}

			return true;
		}

		SuppressionStatus = "NONE";

		if (
			!CanUseSuppressiveFireWithWeapon( weapon ) ||
			weapon.Clip1 < 3 ||
			Time.Now < _nextSuppressionAt ||
			!HasFreshMemory() ||
			Time.Now - _lastConfirmedSeenAt > MathF.Max( 0.35f, SuppressionMemoryWindow ) ||
			HasRecentThreat() ||
			TacticalAggression < 0.38f
		)
			return false;

		float chance = Difficulty switch
		{
			OMRBotDifficulty.Easy => 0.32f,
			OMRBotDifficulty.Hard => 0.72f,
			_ => 0.52f
		};
		chance *= MathX.Lerp( 0.65f, 1.20f, TacticalAggression );
		chance *= MathX.Clamp( 1f + _dynamicPressureBias * 0.85f, 0.65f, 1.30f );

		if ( ActiveModifierIs( RoundModifier.LargeCaliber ) )
			chance *= 0.32f;
		if ( ActiveModifierIs( RoundModifier.Blitz ) )
			chance *= 0.72f;

		if ( Game.Random.Float( 0f, 1f ) > MathX.Clamp( chance, 0.05f, 0.92f ) )
		{
			_nextSuppressionAt = Time.Now + MathF.Max( 1.2f, SuppressionCooldown * 0.55f );
			return false;
		}

		Vector3 lateral = _lastSeenDirection.IsNearlyZero( 0.01f )
			? Vector3.Zero
			: new Vector3( -_lastSeenDirection.y, _lastSeenDirection.x, 0f );
		float sideNoise = Game.Random.Float( -22f, 22f );
		_suppressionAimPoint = _observedTargetAimPoint + lateral * sideNoise;
		int desiredSuppressionShots =
			ActiveModifierIs( RoundModifier.LargeCaliber )
				? 2
				: Math.Max( 2, SuppressionBurstShots );

		_suppressionShotsRemaining =
			Math.Min(
				desiredSuppressionShots,
				Math.Max( 2, weapon.Clip1 - 1 )
			);
		_suppressionUntil = Time.Now + 1.25f;
		_nextSuppressionAt = Time.Now + MathF.Max( 1.4f, SuppressionCooldown );
		SuppressionStatus = $"START · {_suppressionShotsRemaining} SHOTS";
		return TryHandleSuppressiveFire( weapon );
	}

	private bool CanUseSuppressiveFireWithWeapon( OneMoreRoundWeapon weapon )
	{
		if (
			ActiveModifierIs( RoundModifier.HeadshotOnly ) ||
			ActiveModifierIs( RoundModifier.HighNoon )
		)
		{
			return false;
		}

		return GetWeaponDoctrine( weapon ).SupportsSuppressiveFire;
	}

	private bool TryHandleFlankPlan( OneMoreRoundWeapon weapon )
	{
		if ( !_flankActive )
			return false;

		if ( _health?.IsValid == true && _health.Health <= 0f )
		{
			CancelFlank( "CANCEL / DEAD" );
			return false;
		}

		float distance = ( _flankTarget - WorldPosition ).WithZ( 0f ).Length;
		if ( distance <= 42f )
		{
			_flankActive = false;
			FlankStatus = "COMPLETE";
			TacticalStatus = "FLANK COMPLETE / REACQUIRE";
			_pathPoints.Clear();
			_pathPointIndex = 0;
			return false;
		}

		bool stillHasEvidence = _hasConfirmedSight || HasFreshMemory() || HasActionableHearing();
		if ( !stillHasEvidence )
		{
			CancelFlank( "CANCEL / LOST INTEL" );
			return false;
		}

		if ( _hasConfirmedSight && _perceptionTarget?.IsAlive == true )
		{
			UpdateCombatAim( _observedTargetAimPoint );
			if ( weapon?.IsValid == true && weapon.Clip1 > 0 && !weapon.IsReloading )
			{
				float targetDistance = ( _observedTargetPosition - WorldPosition ).WithZ( 0f ).Length;
				bool wantsAds = ShouldUseAds( weapon, targetDistance ) && targetDistance < 700f;
				CombatWantsAim = wantsAds;
				weapon.SetBotAimIntent( wantsAds );
				UpdateVisibleWeaponAttack( weapon, targetDistance, wantsAds );
			}
		}
		else
		{
			ReleaseBotWeaponIntent( weapon );
		}

		NavigateToWorldPosition(
			_flankTarget,
			"FLANK POSITION",
			38f,
			"TACTICAL FLANK",
			allowSprint: !_hasConfirmedSight && distance > 260f,
			faceMovement: !_hasConfirmedSight,
			advancedMovement: true,
			movementWeapon: weapon,
			visibleCombatTarget: _hasConfirmedSight
		);

		FlankStatus = $"MOVING · {distance:0}u";
		TacticalStatus = "FLANK / CHANGE ANGLE";
		CurrentIntent = "TACTICAL / FLANKING";
		return true;
	}

	private bool TryStartFlank( OneMoreRoundWeapon weapon )
	{
		if (
			_flankActive ||
			!_hasConfirmedSight ||
			_perceptionTarget?.IsAlive != true ||
			weapon?.IsValid != true ||
			weapon.IsReloading ||
			weapon.Clip1 <= 0 ||
			HasRecentThreat() ||
			Time.Now < _nextFlankDecisionAt ||
			_confirmedSightStartedAt < 0f ||
			Time.Now - _confirmedSightStartedAt < MathF.Max( 0.8f, FlankMinimumContactTime ) ||
			TacticalAggression < 0.34f
		)
			return false;

		float chance = Difficulty switch
		{
			OMRBotDifficulty.Easy => 0.20f,
			OMRBotDifficulty.Hard => 0.62f,
			_ => 0.40f
		};
		chance *= MathX.Lerp( 0.75f, 1.20f, TacticalAggression );
		chance *= MathX.Clamp( 1f + _dynamicFlankBias * 1.15f, 0.55f, 1.45f );

		float adaptiveConfidence = GetAdaptiveConfidenceWeight();
		if ( adaptiveConfidence > 0f )
		{
			// Static/passive opponents are more flankable; highly mobile players make
			// long committed rotations less attractive.
			float adaptiveFlankScale =
				MathX.Lerp(
					1.18f,
					0.82f,
					_adaptiveOpponentMobility
				);
			chance *= MathX.Lerp( 1f, adaptiveFlankScale, adaptiveConfidence );
		}

		if ( ActiveModifierIs( RoundModifier.Blitz ) )
			chance *= 1.18f;
		else if ( ActiveModifierIs( RoundModifier.HeadshotOnly ) )
			chance *= 0.88f;

		_nextFlankDecisionAt = Time.Now + MathF.Max( 2.1f, FlankDecisionCooldown );

		if ( Game.Random.Float( 0f, 1f ) > MathX.Clamp( chance, 0.05f, 0.92f ) )
			return false;

		if ( !TryChooseFlankPosition( weapon, out Vector3 flank ) )
		{
			FlankStatus = "NO ROUTE";
			return false;
		}

		_flankActive = true;
		_flankTarget = flank;
		_flankSide *= -1;
		FlankStatus = "START / ANGLE CHANGE";
		return TryHandleFlankPlan( weapon );
	}

	private bool TryChooseFlankPosition( OneMoreRoundWeapon weapon, out Vector3 best )
	{
		best = Vector3.Zero;
		if ( Scene?.NavMesh is null || _perceptionTarget?.IsAlive != true )
			return false;

		Vector3 toTarget = ( _observedTargetPosition - WorldPosition ).WithZ( 0f );
		if ( toTarget.IsNearlyZero( 0.01f ) )
			return false;

		Vector3 forward = toTarget.Normal;
		Vector3 lateral = new Vector3( -forward.y, forward.x, 0f ).Normal;
		float hold = GetCombatHoldDistance( weapon );
		float minDistance = MathF.Max( 140f, FlankMinimumDistance );
		float maxDistance = MathF.Max( minDistance + 60f, FlankMaximumDistance );
		float[] distances = { minDistance, ( minDistance + maxDistance ) * 0.5f, maxDistance };
		int[] sides = { _flankSide, -_flankSide };
		List<Vector3> candidates = new();

		foreach ( int side in sides )
		{
			foreach ( float distance in distances )
			{
				Vector3 raw =
					WorldPosition +
					lateral * side * distance +
					forward * MathF.Min( 90f, distance * 0.22f );
				candidates.Add( raw );
			}
		}

		// Optional authored anchors are additional candidates, never commands. They
		// still have to survive the same route/exposure/range evaluation as procedural
		// positions.
		AddAuthoredTacticalCandidates(
			candidates,
			OMRBotTacticalQueryPurpose.Flank,
			WorldPosition,
			maxDistance * 1.55f
		);

		OMRBotWeaponDoctrine doctrine = GetWeaponDoctrine( weapon );
		Vector3 threatReference =
			_observedTargetAimPoint.IsNearlyZero( 0.01f )
				? _observedTargetPosition + Vector3.Up * 46f
				: _observedTargetAimPoint;

		float bestScore = float.MinValue;
		OMRBotTacticalPositionEvaluation bestEvaluation = default;

		foreach ( Vector3 raw in candidates )
		{
			if (
				!TryEvaluateTacticalPosition(
					raw,
					OMRBotTacticalQueryPurpose.Flank,
					doctrine,
					threatReference,
					true,
					_observedTargetPosition,
					hold,
					out OMRBotTacticalPositionEvaluation evaluation
				)
			)
				continue;

			// Small commitment bias prevents left/right candidates with nearly identical
			// tactical value from oscillating solely because traces moved a fraction.
			Vector3 candidateDirection =
				( evaluation.Position - WorldPosition ).WithZ( 0f );
			float preferredSideBonus = 0f;
			if ( !candidateDirection.IsNearlyZero( 0.01f ) )
			{
				float sideDot = candidateDirection.Normal.Dot( lateral ) * _flankSide;
				preferredSideBonus = MathF.Max( 0f, sideDot ) * 14f;
			}

			float score = evaluation.Score + preferredSideBonus;
			if ( score <= bestScore )
				continue;

			bestScore = score;
			best = evaluation.Position;
			bestEvaluation = evaluation;
		}

		if ( bestScore <= float.MinValue )
			return false;

		SetTacticalQueryDiagnostic( OMRBotTacticalQueryPurpose.Flank, bestEvaluation );
		return true;
	}

	private void CancelFlank( string status )
	{
		_flankActive = false;
		_flankTarget = Vector3.Zero;
		FlankStatus = status;
	}

	private bool TryHandleIntelligentSearch( OneMoreRoundWeapon weapon )
	{
		if ( _hasConfirmedSight )
		{
			ClearSearchPlan( "CONTACT" );
			return false;
		}

		bool visualEvidence = HasFreshMemory();
		bool hearingEvidence = HasActionableHearing();
		bool hearingIsNewer = hearingEvidence && ( !visualEvidence || _lastHeardAt > _lastConfirmedSeenAt + 0.18f );

		bool evidenceChangedSincePlan =
			( hearingIsNewer && _lastHeardAt > _searchPlanCreatedAt + 0.10f ) ||
			( visualEvidence && _lastConfirmedSeenAt > _searchPlanCreatedAt + 0.10f );

		float effectiveSearchLifetime =
			MathF.Max(
				1.5f,
				SearchPlanLifetime *
				( ActiveModifierIs( RoundModifier.Blitz ) ? 0.62f : 1f )
			);

		if (
			_searchPoints.Count == 0 ||
			_searchPointIndex >= _searchPoints.Count ||
			evidenceChangedSincePlan ||
			Time.Now - _searchPlanCreatedAt > effectiveSearchLifetime
		)
		{
			Vector3 origin;
			Vector3 direction;
			string evidence;

			if ( hearingIsNewer )
			{
				origin = _lastHeardPosition;
				direction = ( origin - WorldPosition ).WithZ( 0f ).Normal;
				evidence = $"HEARD {_lastHeardKind}";
			}
			else if ( visualEvidence )
			{
				origin = LastKnownPosition;
				direction = !_lastSeenDirection.IsNearlyZero( 0.01f )
					? _lastSeenDirection
					: ( origin - WorldPosition ).WithZ( 0f ).Normal;
				evidence = "LAST SEEN";
			}
			else if ( hearingEvidence )
			{
				origin = _lastHeardPosition;
				direction = ( origin - WorldPosition ).WithZ( 0f ).Normal;
				evidence = $"HEARD {_lastHeardKind}";
			}
			else if ( HasRecentThreat() )
			{
				direction = _lastThreatDirection;
				origin = WorldPosition + direction * 360f;
				evidence = "FIRE DIRECTION";
			}
			else
			{
				return TryHandleNoContactPatrol( weapon );
			}

			if ( !BuildSearchPlan( origin, direction, evidence ) )
				return TryHandleNoContactPatrol( weapon );
		}

		if ( _searchPointIndex >= _searchPoints.Count )
			return false;

		Vector3 point = _searchPoints[_searchPointIndex];
		float distance = ( point - WorldPosition ).WithZ( 0f ).Length;
		float arrival = 48f;

		if ( distance > arrival )
		{
			ReleaseBotWeaponIntent( weapon );
			NavigateToWorldPosition(
				point,
				$"SEARCH {_searchPointIndex + 1}/{_searchPoints.Count}",
				arrival,
				"TACTICAL SEARCH / CLEARING",
				allowSprint: distance > 260f && _lastHeardConfidence < 0.8f,
				faceMovement: true,
				advancedMovement: true,
				movementWeapon: weapon,
				visibleCombatTarget: false
			);
			SearchStatus = $"MOVING {_searchPointIndex + 1}/{_searchPoints.Count} · {_searchEvidence}";
			TacticalStatus = "SEARCH / CLEAR SECTOR";
			CombatStatus = "SEARCHING";
			return true;
		}

		UpdateSearchClearMovement();
		ReleaseBotWeaponIntent( weapon );
		NavigationStatus = "SEARCH CLEAR";
		NavigationTargetName = $"SEARCH {_searchPointIndex + 1}";
		NavigationTargetDistance = MathF.Round( distance );

		if ( _searchPauseUntil < 0f )
			_searchPauseUntil = Time.Now + GetEffectiveSearchPause();

		UpdateSearchLook();
		SearchStatus = $"CLEARING {_searchPointIndex + 1}/{_searchPoints.Count} · {_searchEvidence}";
		TacticalStatus = "SEARCH / CHECK ANGLES";
		CombatStatus = "CLEARING CORNER";

		if ( Time.Now >= _searchPauseUntil )
		{
			MarkOpponentBeliefAreaCleared( point );
			_searchPointIndex++;
			_searchPauseUntil = -1f;
			if ( _searchPointIndex < _searchPoints.Count )
			{
				Vector3 next = ( _searchPoints[_searchPointIndex] - WorldPosition ).WithZ( 0f );
				if ( !next.IsNearlyZero( 0.01f ) )
					_searchFacingDirection = next.Normal;
			}
		}

		return true;
	}

	private bool BuildSearchPlan( Vector3 origin, Vector3 direction, string evidence )
	{
		_searchPoints.Clear();
		_searchPointIndex = 0;
		_searchPauseUntil = -1f;
		_searchPlanCreatedAt = Time.Now;
		_searchEvidence = evidence;

		Vector3 planarDirection = direction.WithZ( 0f );
		if ( planarDirection.IsNearlyZero( 0.01f ) )
			planarDirection = WorldRotation.Forward.WithZ( 0f );
		planarDirection = planarDirection.Normal;
		Vector3 lateral = new Vector3( -planarDirection.y, planarDirection.x, 0f ).Normal;

		Vector3 predicted = origin;
		if ( evidence == "LAST SEEN" && !_lastSeenVelocity.WithZ( 0f ).IsNearlyZero( 1f ) )
		{
			Vector3 prediction =
				_lastSeenVelocity.WithZ( 0f ) *
				MathF.Max( 0.15f, SearchPredictionSeconds * GetModifierSearchPredictionScale() );
			prediction = prediction.ClampLength( MathF.Max( 80f, SearchForwardDistance * 1.15f ) );
			predicted += prediction;
		}

		TryAddSearchPoint( predicted );
		TryAddSearchPoint( predicted + planarDirection * MathF.Max( 90f, SearchForwardDistance ) );

		float sideDistance = MathF.Max( 70f, SearchLateralDistance );
		int firstSide = _flankSide >= 0 ? 1 : -1;
		TryAddSearchPoint( predicted + lateral * sideDistance * firstSide );
		TryAddSearchPoint( predicted - lateral * sideDistance * firstSide );

		// BOT 7E adds the strongest *inferred* current locations. These cells are
		// produced only from fair evidence and uncertainty propagation, not from the
		// opponent's hidden transform.
		AddBeliefSearchCandidates( 4 );

		// If repeated confirmed observations say the player favors a nearby spot,
		// include that *historical* location as another search hypothesis. This is
		// memory, not wall vision: it is only populated while the opponent was seen.
		if (
			TryGetLearnedOpponentHotspot(
				predicted,
				MathF.Max( 260f, SearchForwardDistance * 2.0f ),
				out Vector3 nearbyHotspot,
				out _
			)
		)
		{
			TryAddSearchPoint( nearbyHotspot );
		}

		// Authored search/choke/ambush hints are optional hypotheses. They do not
		// reveal the player and remain subject to reachability plus tactical scoring.
		List<Vector3> authored = new();
		AddAuthoredTacticalCandidates(
			authored,
			OMRBotTacticalQueryPurpose.Search,
			predicted,
			MathF.Max( 300f, SearchForwardDistance * 2.25f )
		);
		foreach ( Vector3 point in authored )
			TryAddSearchPoint( point );

		ReorderSearchPointsByMemoryRisk( predicted, evidence );

		_searchFacingDirection = planarDirection;
		SearchStatus = _searchPoints.Count > 0 ? $"PLAN {_searchPoints.Count} · {evidence}" : "NO PLAN";
		return _searchPoints.Count > 0;
	}

	private void TryAddSearchPoint( Vector3 raw )
	{
		if ( Scene?.NavMesh is null )
			return;

		Vector3? projected = Scene.NavMesh.GetClosestPoint( raw, 130f );
		if ( projected is null )
			return;

		foreach ( Vector3 existing in _searchPoints )
		{
			if ( ( existing - projected.Value ).WithZ( 0f ).Length < 70f )
				return;
		}

		if ( !TryEvaluateTacticalRoute( projected.Value, Vector3.Zero, false, out _ ) ) return;

		_searchPoints.Add( projected.Value );
	}

	private void ReorderSearchPointsByMemoryRisk(
		Vector3 evidenceOrigin,
		string evidence
	)
	{
		if ( _searchPoints.Count <= 1 || Scene?.NavMesh is null )
			return;

		OMRBotWeaponDoctrine doctrine = GetWeaponDoctrine( ResolveActiveWeapon() );
		float desiredRange = MathF.Max( 90f, doctrine.LegacyHoldDistance );
		Vector3 threatReference = evidenceOrigin + Vector3.Up * 34f;
		List<(Vector3 Point, float Score, OMRBotTacticalPositionEvaluation Evaluation)> scored = new();

		foreach ( Vector3 point in _searchPoints )
		{
			if (
				!TryEvaluateTacticalPosition(
					point,
					OMRBotTacticalQueryPurpose.Search,
					doctrine,
					threatReference,
					true,
					evidenceOrigin,
					desiredRange,
					out OMRBotTacticalPositionEvaluation evaluation
				)
			)
				continue;

			float score = evaluation.Score;
			score += GetOpponentBeliefAt( evaluation.Position ) * MathF.Max( 0f, BeliefSearchScoreWeight );
			if ( string.Equals( evidence, "LEARNED HOTSPOT", StringComparison.OrdinalIgnoreCase ) )
			{
				// Historical evidence is intentionally weaker than fresh visual/audio
				// evidence. Route quality therefore has more room to influence the order.
				score -= ( 1f - evaluation.EvidenceRelevance ) * 24f;
			}

			scored.Add( ( evaluation.Position, score, evaluation ) );
		}

		if ( scored.Count == 0 )
			return;

		scored.Sort( ( a, b ) => b.Score.CompareTo( a.Score ) );
		_searchPoints.Clear();

		foreach ( var item in scored )
			_searchPoints.Add( item.Point );

		SetTacticalQueryDiagnostic( OMRBotTacticalQueryPurpose.Search, scored[0].Evaluation );
	}

	private void UpdateSearchLook()
	{
		if ( _controller?.IsValid != true )
			return;

		Vector3 direction = _searchFacingDirection;
		if ( direction.IsNearlyZero( 0.01f ) )
			direction = WorldRotation.Forward.WithZ( 0f );

		if ( TryGetBestOpponentBelief( out Vector3 beliefLook, out float beliefLookConfidence ) )
		{
			Vector3 toBelief = ( beliefLook - WorldPosition ).WithZ( 0f );
			if ( !toBelief.IsNearlyZero( 0.01f ) )
			{
				float blend = MathX.Clamp( beliefLookConfidence * 1.35f, 0f, 0.48f );
				direction = Vector3.Lerp( direction.Normal, toBelief.Normal, blend ).Normal;
			}
		}

		float sweep = MathF.Sin( ( Time.Now + BotSlot * 0.31f ) * 3.2f ) * 34f;
		Angles baseAngles = Rotation.LookAt( direction.Normal, Vector3.Up ).Angles();
		Angles desired = new( 0f, baseAngles.yaw + sweep, 0f );
		float follow = 1f - MathF.Exp( -7f * MathF.Max( Time.Delta, 0f ) );
		_controller.EyeAngles = Rotation.Slerp(
			_controller.EyeAngles.ToRotation(),
			desired.ToRotation(),
			MathX.Clamp( follow, 0f, 1f )
		).Angles();
	}

	private bool TryHandleNoContactPatrol( OneMoreRoundWeapon weapon )
	{
		if ( _searchPoints.Count == 0 || _searchPointIndex >= _searchPoints.Count || Time.Now - _searchPlanCreatedAt > 4.5f )
		{
			Vector3 forward = WorldRotation.Forward.WithZ( 0f );
			if ( _controller?.IsValid == true )
				forward = _controller.EyeTransform.Rotation.Forward.WithZ( 0f );
			if ( forward.IsNearlyZero( 0.01f ) ) forward = new Vector3( 1f, 0f, 0f );
			forward = forward.Normal;

			bool usedLearnedHotspot = false;

			// Prefer the current belief peak over long-term historical habits. The peak
			// fades/clears as ROOK disproves areas, so this is a search hypothesis rather
			// than a permanent camp marker.
			if (
				TryGetBestOpponentBelief( out Vector3 beliefPeak, out float beliefPeakConfidence ) &&
				beliefPeakConfidence >= MathF.Max( 0.035f, BeliefMinimumCellProbability * 2f )
			)
			{
				Vector3 beliefDirection = ( beliefPeak - WorldPosition ).WithZ( 0f );
				if ( !beliefDirection.IsNearlyZero( 0.01f ) )
				{
					usedLearnedHotspot = BuildSearchPlan( beliefPeak, beliefDirection.Normal, "BELIEF PEAK" );
					if ( usedLearnedHotspot )
						SearchStatus = $"BELIEF PEAK · {beliefPeakConfidence * 100f:0}%";
				}
			}

			float hotspotUseChance = Difficulty switch
			{
				OMRBotDifficulty.Easy => 0.30f,
				OMRBotDifficulty.Hard => 0.72f,
				_ => 0.50f
			};

			if (
				!usedLearnedHotspot &&
				TryGetLearnedOpponentHotspot(
					WorldPosition,
					MathF.Max( 700f, SightRange ),
					out Vector3 hotspot,
					out float hotspotScore
				) &&
				Game.Random.Float( 0f, 1f ) <= hotspotUseChance
			)
			{
				Vector3 hotspotDirection =
					( hotspot - WorldPosition ).WithZ( 0f );
				if ( !hotspotDirection.IsNearlyZero( 0.01f ) )
				{
					hotspotDirection = hotspotDirection.Normal;
					usedLearnedHotspot =
						BuildSearchPlan(
							hotspot,
							hotspotDirection,
							"LEARNED HOTSPOT"
						);

					if ( usedLearnedHotspot )
					{
						MarkLearnedHotspotChecked( hotspot );
						SearchStatus = $"LEARNED HOTSPOT · {hotspotScore:0.0}";
					}
				}
			}

			if ( !usedLearnedHotspot )
			{
				Vector3 lateral = new Vector3( -forward.y, forward.x, 0f );
				Vector3 origin = WorldPosition + forward * 180f + lateral * _flankSide * 150f;
				if ( !BuildSearchPlan( origin, forward, "AREA PATROL" ) )
				{
					StopMovementOnly();
					SweepLook( IdleSweepSpeed * 0.55f );
					SearchStatus = "FALLBACK SCAN";
					return true;
				}
			}
		}

		return TryHandleIntelligentSearch( weapon );
	}

	private void ClearSearchPlan( string status )
	{
		_searchPoints.Clear();
		_searchPointIndex = 0;
		_searchPauseUntil = -1f;
		_searchPlanCreatedAt = -999f;
		_searchEvidence = string.Empty;
		SearchStatus = status;
	}
	// =========================================================
	// BOT 6 - MODIFIER AWARENESS / ONLINE ADAPTATION
	// =========================================================

	private void UpdateModifierAwareness()
	{
		if ( !UsesTacticalBehavior() )
		{
			_activeModifier = RoundModifier.Standard;
			_activeRoundRule = null;
			ModifierStatus = "OFF";
			return;
		}

		if ( _roundManager?.IsValid != true )
		{
			_roundManager =
				Scene?
					.GetAllComponents<RoundManager>()
					.FirstOrDefault();
		}

		if ( _roundRuleDirector?.IsValid != true )
		{
			_roundRuleDirector =
				Scene?
					.GetAllComponents<OMRRoundRuleDirector>()
					.FirstOrDefault();
		}

		RoundModifier resolved =
			_roundManager is not null &&
			_roundManager.Mode == SessionMode.Sandbox
				? _roundManager.SandboxBotTestModifier
				: _roundManager?.ActiveModifier ?? RoundModifier.Standard;

		if ( resolved != _activeModifier )
		{
			_activeModifier = resolved;
			_highNoonFireAt = -1f;
			_lastHighNoonStage = HighNoonStage.Inactive;
		}

		_activeRoundRule =
			_roundRuleDirector?.
				ResolveRule( _activeModifier );

		string modifierName =
			_activeRoundRule?.GetDisplayName() ??
			_activeModifier.ToString().ToUpperInvariant();

		string adaptation = _activeModifier switch
		{
			RoundModifier.HighNoon => "DUEL DISCIPLINE",
			RoundModifier.LowGravity => "AIR / FLOAT TRACKING",
			RoundModifier.HeadshotOnly => "HEAD PRIORITY",
			RoundModifier.LargeCaliber => "AMMO DISCIPLINE",
			RoundModifier.DoubleJump => "AIR MOBILITY",
			RoundModifier.HipfireOnly => "HIPFIRE / CLOSE",
			RoundModifier.Blitz => "FAST TEMPO",
			_ => "BASELINE"
		};

		ModifierStatus = $"{modifierName} · {adaptation}";
	}

	private bool ActiveModifierIs( RoundModifier modifier ) =>
		UsesTacticalBehavior() &&
		_activeModifier == modifier;

	private void UpdateDynamicTacticalVariation()
	{
		if ( !UsesTacticalBehavior() )
			return;

		if ( Time.Now < _nextDynamicVariationAt )
			return;

		float strength =
			MathX.Clamp( DynamicVariationStrength, 0f, 0.35f );

		// Hard still varies tactically, but its swings are a little tighter so
		// unpredictability does not become deliberate stupidity.
		float difficultyScale = Difficulty switch
		{
			OMRBotDifficulty.Easy => 1.15f,
			OMRBotDifficulty.Hard => 0.82f,
			_ => 1f
		};

		strength *= difficultyScale;

		_dynamicPressureBias = Game.Random.Float( -strength, strength );
		_dynamicCoverBias =
			Game.Random.Float( -strength, strength ) -
			_dynamicPressureBias * 0.35f;
		_dynamicFlankBias = Game.Random.Float( -strength, strength );
		_dynamicMovementBias = Game.Random.Float( -strength, strength );
		_dynamicDecisionSerial++;

		float minInterval =
			MathF.Max( 0.8f, MathF.Min( DynamicDecisionIntervalMin, DynamicDecisionIntervalMax ) );
		float maxInterval =
			MathF.Max( minInterval + 0.1f, MathF.Max( DynamicDecisionIntervalMin, DynamicDecisionIntervalMax ) );

		_nextDynamicVariationAt =
			Time.Now + Game.Random.Float( minInterval, maxInterval );
	}

	private void UpdateOpponentLearning()
	{
		if ( !UsesTacticalBehavior() || !AdaptiveLearningEnabled )
		{
			AdaptationStatus = "DISABLED";
			AdaptationConfidence = 0f;
			return;
		}

		if (
			!_hasConfirmedSight ||
			_perceptionTarget?.IsAlive != true ||
			Time.Now < _nextAdaptiveSampleAt
		)
		{
			UpdateAdaptationDiagnostics();
			return;
		}

		PlayerController targetController =
			_perceptionTarget.Components.Get<PlayerController>();

		if ( targetController?.IsValid != true )
		{
			UpdateAdaptationDiagnostics();
			return;
		}

		_nextAdaptiveSampleAt = Time.Now + 0.18f;

		Vector3 targetVelocity =
			targetController.Velocity.WithZ( 0f );
		float speed = targetVelocity.Length;
		float distance =
			( _observedTargetPosition - WorldPosition )
				.WithZ( 0f )
				.Length;

		Vector3 towardBot =
			( WorldPosition - _observedTargetPosition )
				.WithZ( 0f );
		if ( !towardBot.IsNearlyZero( 0.01f ) )
			towardBot = towardBot.Normal;

		float approachSpeed =
			!towardBot.IsNearlyZero( 0.01f )
				? targetVelocity.Dot( towardBot )
				: 0f;

		// Blend kinematic approach with actual distance trend. The second term
		// catches aggressive pushes even when collision/strafe makes velocity noisy.
		if ( _adaptivePreviousDistance >= 0f && _adaptivePreviousSampleAt > 0f )
		{
			float dt = MathF.Max( 0.05f, Time.Now - _adaptivePreviousSampleAt );
			float distanceClosing =
				( _adaptivePreviousDistance - distance ) / dt;
			approachSpeed =
				MathX.Lerp(
					approachSpeed,
					distanceClosing,
					0.45f
				);
		}

		_adaptivePreviousDistance = distance;
		_adaptivePreviousSampleAt = Time.Now;

		PlayerSlide targetSlide =
			_perceptionTarget.Components.Get<PlayerSlide>();
		PlayerCrouch targetCrouch =
			_perceptionTarget.Components.Get<PlayerCrouch>();
		PlayerSprint targetSprint =
			_perceptionTarget.Components.Get<PlayerSprint>();

		float mobilitySample =
			MathX.Clamp( speed / 285f, 0f, 1f );

		if ( targetSlide?.IsSliding == true )
			mobilitySample = MathF.Max( mobilitySample, 0.95f );
		else if ( targetSprint?.IsSprinting == true )
			mobilitySample = MathF.Max( mobilitySample, 0.78f );

		float airSample =
			targetController.IsAirborne ? 1f : 0f;
		float crouchSample =
			( targetController.IsDucking || targetCrouch?.WantsCrouch == true )
				? 1f
				: 0f;

		float aggressionSample =
			MathX.Clamp(
				0.50f + approachSpeed / 360f,
				0f,
				1f
			);

		if (
			HasFreshHearing() &&
			_lastHeardKind == "GUNSHOT" &&
			Time.Now - _lastHeardAt <= 0.32f
		)
		{
			aggressionSample =
				MathF.Min( 1f, aggressionSample + 0.10f );
		}

		float distanceSample =
			MathX.Clamp(
				distance / MathF.Max( 500f, SightRange ),
				0f,
				1f
			);

		float rate =
			MathX.Clamp( AdaptiveLearningRate, 0.01f, 0.35f );

		_adaptiveOpponentAggression =
			AdaptiveBlend( _adaptiveOpponentAggression, aggressionSample, rate );
		_adaptiveOpponentMobility =
			AdaptiveBlend( _adaptiveOpponentMobility, mobilitySample, rate );
		_adaptiveOpponentAirUse =
			AdaptiveBlend( _adaptiveOpponentAirUse, airSample, rate * 0.75f );
		_adaptiveOpponentCrouchUse =
			AdaptiveBlend( _adaptiveOpponentCrouchUse, crouchSample, rate * 0.70f );
		_adaptivePreferredDistance =
			AdaptiveBlend( _adaptivePreferredDistance, distanceSample, rate * 0.60f );

		_adaptiveSampleCount++;
		UpdateAdaptationDiagnostics();
	}

	private static float AdaptiveBlend( float current, float sample, float rate )
	{
		return MathX.Lerp(
			current,
			MathX.Clamp( sample, 0f, 1f ),
			MathX.Clamp( rate, 0f, 1f )
		);
	}

	private void UpdateAdaptationDiagnostics()
	{
		if ( !UsesTacticalBehavior() )
		{
			AdaptationStatus = "OFF";
			AdaptationConfidence = 0f;
			return;
		}

		if ( !AdaptiveLearningEnabled )
		{
			AdaptationStatus = "DISABLED";
			AdaptationConfidence = 0f;
			return;
		}

		int minimumSamples =
			Math.Max( 1, AdaptiveMinimumSamples );

		AdaptationConfidence =
			MathX.Clamp(
				_adaptiveSampleCount / (float)( minimumSamples * 2 ),
				0f,
				1f
			);

		if ( _adaptiveSampleCount < minimumSamples )
		{
			AdaptationStatus =
				$"LEARNING {_adaptiveSampleCount}/{minimumSamples} · VAR {_dynamicDecisionSerial}";
			return;
		}

		string style;
		if ( _adaptiveOpponentAggression >= 0.66f && _adaptiveOpponentMobility >= 0.58f )
			style = "RUSH / MOBILE";
		else if ( _adaptiveOpponentAggression >= 0.66f )
			style = "PRESSURE";
		else if ( _adaptivePreferredDistance >= 0.62f )
			style = "RANGE";
		else if ( _adaptiveOpponentMobility >= 0.68f || _adaptiveOpponentAirUse >= 0.34f )
			style = "MOBILE";
		else if ( _adaptiveOpponentCrouchUse >= 0.34f )
			style = "LOW PROFILE";
		else if ( _adaptiveOpponentAggression <= 0.38f )
			style = "CAUTIOUS";
		else
			style = "BALANCED";

		AdaptationStatus =
			$"{style} · AGG {_adaptiveOpponentAggression * 100f:0}% · MOB {_adaptiveOpponentMobility * 100f:0}%";
	}

	private float GetAdaptiveConfidenceWeight()
	{
		if ( !AdaptiveLearningEnabled )
			return 0f;

		return MathX.Clamp( AdaptationConfidence, 0f, 1f );
	}

	private float GetAdaptivePressureAdjustment()
	{
		float confidence = GetAdaptiveConfidenceWeight();

		if ( confidence <= 0f )
			return 0f;

		// Counter-style instead of mirror-style: repeated hard pushes make a
		// long-range bot value space, while a passive/ranged opponent invites angle
		// changes and pressure. The effect is intentionally modest.
		float opponentPressure =
			( _adaptiveOpponentAggression - 0.50f ) * 0.18f;

		return -opponentPressure * confidence;
	}

	private float GetAdaptiveHoldDistanceScale( OneMoreRoundWeapon weapon )
	{
		float confidence = GetAdaptiveConfidenceWeight();
		if ( confidence <= 0f || weapon?.IsValid != true )
			return 1f;

		OMRBotWeaponDoctrine doctrine = GetWeaponDoctrine( weapon );
		float scale = 1f;

		if ( _adaptiveOpponentAggression >= 0.62f )
		{
			// Preserve space with rifles/precision weapons against a habitual pusher.
			if ( doctrine.PreserveSpaceAgainstRush )
				scale += 0.12f * confidence;
		}
		else if ( _adaptivePreferredDistance >= 0.62f )
		{
			// Close-range weapons should not politely accept the opponent's favorite
			// long-range duel forever.
			if ( doctrine.CloseDistanceAgainstRangedOpponent )
				scale -= 0.14f * confidence;
		}

		return MathX.Clamp( scale, 0.82f, 1.18f );
	}

	private float GetEffectiveSearchPause()
	{
		float pause = MathF.Max( 0.16f, SearchPointPause );

		pause *= Difficulty switch
		{
			OMRBotDifficulty.Easy => 1.12f,
			OMRBotDifficulty.Hard => 0.72f,
			_ => 0.88f
		};

		if ( ActiveModifierIs( RoundModifier.Blitz ) )
			pause *= 0.58f;

		float confidence = GetAdaptiveConfidenceWeight();
		pause *= MathX.Lerp(
			1f,
			MathX.Lerp( 1.05f, 0.72f, _adaptiveOpponentMobility ),
			confidence
		);

		return MathF.Max( 0.14f, pause );
	}

	private float GetModifierSearchPredictionScale()
	{
		float scale = 1f;

		if ( ActiveModifierIs( RoundModifier.Blitz ) )
			scale *= 1.08f;
		if ( ActiveModifierIs( RoundModifier.LowGravity ) )
			scale *= 1.10f;

		float confidence = GetAdaptiveConfidenceWeight();
		scale *= MathX.Lerp(
			1f,
			MathX.Lerp( 0.88f, 1.22f, _adaptiveOpponentMobility ),
			confidence
		);

		return MathX.Clamp( scale, 0.78f, 1.30f );
	}

	private bool TryHandleHighNoonBehavior( OneMoreRoundWeapon weapon )
	{
		if (
			!ActiveModifierIs( RoundModifier.HighNoon ) ||
			_roundManager?.Mode != SessionMode.Match ||
			!_roundManager.ActiveUsesHighNoonFlow
		)
		{
			_highNoonFireAt = -1f;
			_lastHighNoonStage = HighNoonStage.Inactive;
			return false;
		}

		if ( _hasCoverTarget )
			ClearCoverPlan( "HIGH NOON" );
		if ( _flankActive )
			CancelFlank( "HIGH NOON" );
		if ( _searchPoints.Count > 0 )
			ClearSearchPlan( "HIGH NOON" );

		_suppressionUntil = -1f;
		_suppressionShotsRemaining = 0;
		SuppressionStatus = "OFF / HIGH NOON";

		StopMovementOnly();
		NavigationStatus = "HIGH NOON / LOCKED";
		NavigationTargetName = _perceptionTarget?.DisplayName ?? "OPPONENT";
		NavigationTargetDistance =
			_perceptionTarget?.IsAlive == true
				? MathF.Round( ( _perceptionTarget.WorldPosition - WorldPosition ).WithZ( 0f ).Length )
				: 0f;

		if ( _hasConfirmedSight && _perceptionTarget?.IsAlive == true )
			UpdateCombatAim( ResolveCombatAimPoint( _perceptionTarget ) );

		weapon?.SetBotAimIntent( false );
		CombatWantsAim = false;

		HighNoonStage stage = _roundManager.HighNoonState;

		if ( stage != _lastHighNoonStage )
		{
			_lastHighNoonStage = stage;
			_highNoonFireAt = -1f;
		}

		if (
			_roundManager.Phase != RoundPhase.Fighting ||
			stage == HighNoonStage.Inactive
		)
		{
			TacticalStatus = "HIGH NOON / READY";
			CombatStatus = "HIGH NOON / LOCKED";
			CurrentIntent = "HIGH NOON / HOLD";
			return true;
		}

		if ( stage == HighNoonStage.WaitingForDraw )
		{
			TacticalStatus = "HIGH NOON / WAIT DRAW";
			CombatStatus = "WAITING FOR DRAW";
			CurrentIntent = "HIGH NOON / DISCIPLINE";
			return true;
		}

		if ( stage == HighNoonStage.DrawOpen )
		{
			if ( _highNoonFireAt < 0f )
				_highNoonFireAt = Time.Now + GetHighNoonReactionDelay();

			float remaining = MathF.Max( 0f, _highNoonFireAt - Time.Now );
			TacticalStatus = "HIGH NOON / DRAW";
			CurrentIntent = "HIGH NOON / DRAW";

			if ( Time.Now < _highNoonFireAt )
			{
				CombatStatus = $"REACTION {remaining:0.00}s";
				return true;
			}

			if (
				_hasConfirmedSight &&
				_perceptionTarget?.IsAlive == true &&
				weapon?.IsValid == true &&
				weapon.Clip1 > 0 &&
				!weapon.IsReloading &&
				!weapon.IsCyclePendingOrActive
			)
			{
				float tolerance = GetFireToleranceDegrees() * 1.35f;
				if ( CombatAimError <= tolerance || Time.Now - _highNoonFireAt >= 0.16f )
				{
					if ( weapon.BotTryPrimaryFire() )
					{
						CombatStatus = "DRAW FIRED";
						_highNoonFireAt = Time.Now + MathF.Max( 0.22f, GetBotTriggerInterval( weapon ) );
						return true;
					}
				}
			}

			CombatStatus = "DRAW / ALIGNING";
			return true;
		}

		return true;
	}

	private float GetHighNoonReactionDelay()
	{
		float min;
		float max;

		switch ( Difficulty )
		{
			case OMRBotDifficulty.Easy:
				min = 0.34f;
				max = 0.52f;
				break;
			case OMRBotDifficulty.Hard:
				min = 0.16f;
				max = 0.27f;
				break;
			default:
				min = 0.23f;
				max = 0.38f;
				break;
		}

		return Game.Random.Float( min, max );
	}

	private void MaintainReactionMomentum()
	{
		if ( _movementInput?.IsValid != true || _controller?.IsValid != true )
		{
			StopMovementOnly();
			return;
		}

		Vector3 velocity = _controller.Velocity.WithZ( 0f );
		Vector3 localInput;

		if ( velocity.Length >= 36f )
		{
			Rotation basis = Rotation.FromYaw( _controller.EyeAngles.yaw );
			localInput =
				( basis.Inverse * velocity.Normal )
					.WithZ( 0f )
					.ClampLength( 0.72f );
		}
		else
		{
			float side = _strafeDirection >= 0f ? 1f : -1f;
			float strength =
				MathX.Clamp(
					0.14f + MathF.Abs( _dynamicMovementBias ) * 0.30f,
					0.12f,
					0.28f
				);
			localInput = new Vector3( 0f, side * strength, 0f );
		}

		_movementInput.SetBotInput(
			localInput,
			sprintDown: false,
			crouchDown: GetBotCrouchButtonDown(),
			jumpPressed: false
		);

		SetMovementDiagnostics( "REACTION / MOMENTUM" );
	}

	private void UpdateSearchClearMovement()
	{
		if ( _movementInput?.IsValid != true || _controller?.IsValid != true )
			return;

		float strength =
			MathX.Clamp( SearchClearMoveStrength, 0f, 0.65f );

		if ( strength <= 0.01f )
		{
			StopMovementOnly();
			return;
		}

		float side = _flankSide >= 0 ? 1f : -1f;
		Vector3 local = new Vector3( 0.05f, side * strength, 0f ).ClampLength( 1f );
		Rotation basis = Rotation.FromYaw( _controller.EyeAngles.yaw );
		Vector3 worldDirection = ( basis * local ).WithZ( 0f );

		if ( !worldDirection.IsNearlyZero( 0.01f ) && !IsTraversalDirectionClear( worldDirection ) )
		{
			side *= -1f;
			_flankSide *= -1;
			local = new Vector3( 0.03f, side * strength, 0f ).ClampLength( 1f );
		}

		_movementInput.SetBotInput(
			local,
			sprintDown: false,
			crouchDown: GetBotCrouchButtonDown(),
			jumpPressed: false
		);

		SetMovementDiagnostics( side > 0f ? "SEARCH CLEAR / DRIFT RIGHT" : "SEARCH CLEAR / DRIFT LEFT" );
	}

	private void UpdateSuppressiveMovement()
	{
		if ( _movementInput?.IsValid != true || _controller?.IsValid != true )
			return;

		float strength =
			MathX.Clamp( SuppressionMoveStrength, 0f, 0.65f );

		if ( strength <= 0.01f )
		{
			StopMovementOnly();
			return;
		}

		float side = _strafeDirection >= 0f ? 1f : -1f;
		Vector3 local = new Vector3( -0.04f, side * strength, 0f ).ClampLength( 1f );

		_movementInput.SetBotInput(
			local,
			sprintDown: false,
			crouchDown: GetBotCrouchButtonDown(),
			jumpPressed: false
		);

		SetMovementDiagnostics( side > 0f ? "SUPPRESS / STRAFE RIGHT" : "SUPPRESS / STRAFE LEFT" );
	}

	// =========================================================
	// BOT 6.1 - SPATIAL / EPISODIC MEMORY
	// =========================================================

	private (int X, int Y) GetSpatialMemoryKey( Vector3 position )
	{
		float size = MathF.Max( 48f, SpatialMemoryCellSize );
		return (
			(int)MathF.Floor( position.x / size ),
			(int)MathF.Floor( position.y / size )
		);
	}

	private Vector3 GetSpatialMemoryCellCenter( (int X, int Y) key, float z = 0f )
	{
		float size = MathF.Max( 48f, SpatialMemoryCellSize );
		return new Vector3(
			( key.X + 0.5f ) * size,
			( key.Y + 0.5f ) * size,
			z
		);
	}

	private SpatialMemoryCell GetSpatialMemoryCell( (int X, int Y) key, bool create )
	{
		if ( !_spatialMemory.TryGetValue( key, out SpatialMemoryCell cell ) )
		{
			if ( !create )
				return null;

			cell = new SpatialMemoryCell
			{
				LastUpdatedAt = Time.Now
			};
			_spatialMemory[key] = cell;
			return cell;
		}

		DecaySpatialMemoryCell( cell );
		return cell;
	}

	private void DecaySpatialMemoryCell( SpatialMemoryCell cell )
	{
		if ( cell is null )
			return;

		float dt = MathF.Max( 0f, Time.Now - cell.LastUpdatedAt );
		if ( dt <= 0.001f )
			return;

		float tacticalHalfLife = MathF.Max( 8f, SpatialMemoryHalfLife );
		float routeHalfLife = MathF.Max( 6f, RouteMemoryHalfLife );
		float tacticalDecay = MathF.Pow( 0.5f, dt / tacticalHalfLife );
		float routeDecay = MathF.Pow( 0.5f, dt / routeHalfLife );

		cell.OpponentPresence *= tacticalDecay;
		cell.OpponentStationaryPresence *= tacticalDecay;
		cell.Danger *= tacticalDecay;
		cell.DeathDanger *= tacticalDecay;
		cell.RouteUse *= routeDecay;
		cell.LastUpdatedAt = Time.Now;
	}

	private void UpdateSpatialMemoryLayoutScope()
	{
		if ( _memoryArena?.IsValid != true )
		{
			_memoryArena =
				Scene?
					.GetAllComponents<ArenaController>()
					.FirstOrDefault();
		}

		if ( _memoryArena?.IsValid != true )
			return;

		ArenaLayoutState state = _memoryArena.CurrentLayoutState;
		if ( !state.IsValid )
			return;

		if ( !_memoryLayoutInitialized )
		{
			_memoryLayoutInitialized = true;
			_memoryLayoutState = state;
			return;
		}

		if ( state == _memoryLayoutState )
			return;

		// Spatial coordinates mean something different after OMR swaps modular
		// layout pieces. Keep the opponent-style model, but clear map-specific
		// danger/hotspot memory so old geometry never turns into fake knowledge.
		_memoryLayoutState = state;
		ResetPerformanceCaches();
		ClearCoverPlan( "LAYOUT CHANGED" );
		_pathPoints.Clear();
		_pathPointIndex = 0;
		_nextRepathAt = 0f;
		_spatialMemory.Clear();
		_recentRouteSamples.Clear();
		ResetOpponentBelief( "LAYOUT RESET" );
		ResetPlayerPrediction( clearStyle: false );
		_spatialDeathCount = 0;
		_learnedHotspotChecks = 0;
		ClearSearchPlan( "LAYOUT CHANGED" );
		CancelFlank( "LAYOUT CHANGED" );
		SpatialMemoryStatus = "LAYOUT RESET";
	}

	private void UpdateSpatialMemoryLifecycle()
	{
		if ( !UsesTacticalBehavior() )
		{
			SpatialMemoryStatus = "OFF";
			AwarenessStatus = "LEGACY";
			return;
		}

		UpdateSpatialMemoryLayoutScope();

		bool alive =
			_playerState?.IsAlive == true &&
			( _health?.IsValid != true || !_health.IsDead );

		if ( !_memoryLifeInitialized )
		{
			_memoryLifeInitialized = true;
			_memoryWasAlive = alive;
			if ( alive )
				BeginNewBotLife();
		}
		else
		{
			if ( _memoryWasAlive && !alive )
				RecordBotDeathMemory();
			else if ( !_memoryWasAlive && alive )
				BeginNewBotLife();

			_memoryWasAlive = alive;
		}

		if ( alive && Time.Now >= _nextRouteMemorySampleAt )
		{
			_nextRouteMemorySampleAt =
				Time.Now + MathF.Max( 0.08f, RouteSampleInterval );
			RecordRouteMemorySample();
		}

		if ( Time.Now >= _nextSpatialMemoryDiagnosticAt )
		{
			_nextSpatialMemoryDiagnosticAt = Time.Now + 0.35f;
			UpdateSpatialMemoryDiagnostics();
		}
	}

	private void RecordRouteMemorySample()
	{
		(int X, int Y) key = GetSpatialMemoryKey( WorldPosition );
		SpatialMemoryCell cell = GetSpatialMemoryCell( key, true );
		cell.RouteUse = MathF.Min( 8f, cell.RouteUse + 0.10f );

		_recentRouteSamples.Add(
			new RecentRouteSample( WorldPosition, Time.Now )
		);

		float cutoff = Time.Now - 7.5f;
		while ( _recentRouteSamples.Count > 0 && _recentRouteSamples[0].Time < cutoff )
			_recentRouteSamples.RemoveAt( 0 );

		if ( _recentRouteSamples.Count > 40 )
			_recentRouteSamples.RemoveRange( 0, _recentRouteSamples.Count - 40 );
	}

	private void UpdateSpatialOpponentMemory()
	{
		if (
			!UsesTacticalBehavior() ||
			!_hasConfirmedSight ||
			_perceptionTarget?.IsAlive != true
		)
			return;

		PlayerController targetController =
			_perceptionTarget.Components.Get<PlayerController>();

		float speed =
			targetController?.IsValid == true
				? targetController.Velocity.WithZ( 0f ).Length
				: 0f;

		RecordOpponentSpatialObservation(
			_observedTargetPosition,
			speed,
			MathF.Max( 0.01f, Time.Delta )
		);
	}

	private void RecordOpponentSpatialObservation(
		Vector3 position,
		float speed,
		float sampleSeconds
	)
	{
		if ( !UsesTacticalBehavior() || !_hasConfirmedSight )
			return;

		SpatialMemoryCell cell =
			GetSpatialMemoryCell( GetSpatialMemoryKey( position ), true );

		float seconds = MathX.Clamp( sampleSeconds, 0.01f, 0.20f );
		cell.OpponentPresence =
			MathF.Min( 10f, cell.OpponentPresence + seconds * 0.22f );

		if ( speed <= 55f )
		{
			cell.OpponentStationaryPresence =
				MathF.Min(
					10f,
					cell.OpponentStationaryPresence + seconds * 0.45f
				);
		}

		cell.LastOpponentSeenAt = Time.Now;
	}

	private void RecordBotDeathMemory()
	{
		_spatialDeathCount++;

		SpatialMemoryCell deathCell =
			GetSpatialMemoryCell( GetSpatialMemoryKey( WorldPosition ), true );
		deathCell.DeathDanger = MathF.Min( 12f, deathCell.DeathDanger + 3.0f );
		deathCell.Danger = MathF.Min( 12f, deathCell.Danger + 1.25f );

		// "Scent of death": mark the recent approach, not only the exact death
		// coordinate. Repeatedly dying on the same route therefore makes later
		// search/flank/cover queries prefer another avenue instead of marching back
		// into the same ambush.
		Dictionary<(int X, int Y), float> routeWeights = new();
		for ( int i = _recentRouteSamples.Count - 1; i >= 0; --i )
		{
			RecentRouteSample sample = _recentRouteSamples[i];
			float age = MathF.Max( 0f, Time.Now - sample.Time );
			if ( age > 7.5f )
				break;

			float weight = 1f - MathX.Clamp( age / 7.5f, 0f, 1f );
			(int X, int Y) key = GetSpatialMemoryKey( sample.Position );

			if ( !routeWeights.TryGetValue( key, out float previous ) || weight > previous )
				routeWeights[key] = weight;
		}

		foreach ( KeyValuePair<(int X, int Y), float> entry in routeWeights )
		{
			SpatialMemoryCell cell = GetSpatialMemoryCell( entry.Key, true );
			cell.Danger =
				MathF.Min(
					12f,
					cell.Danger +
					MathF.Max( 0.25f, DeathRoutePenalty ) *
					entry.Value
				);
		}

		_recentRouteSamples.Clear();
		ResetOpponentBelief( "DEATH RESET" );
		ClearSearchPlan( "DEATH / REPLAN" );
		CancelFlank( "DEATH / REPLAN" );
	}

	private float GetSpatialMemoryRiskAt( Vector3 position )
	{
		SpatialMemoryCell cell =
			GetSpatialMemoryCell( GetSpatialMemoryKey( position ), false );

		if ( cell is null )
			return 0f;

		return
			cell.Danger * 0.70f +
			cell.DeathDanger * 1.20f +
			cell.RouteUse * 0.10f;
	}

	private float EvaluatePathMemoryRisk( NavMeshPath path )
	{
		if ( path.Points is null )
			return 0f;

		HashSet<(int X, int Y)> visited = new();
		float total = 0f;

		foreach ( NavMeshPathPoint pathPoint in path.Points )
		{
			Vector3 point = pathPoint.Position;
			(int X, int Y) key = GetSpatialMemoryKey( point );
			if ( !visited.Add( key ) )
				continue;

			total += GetSpatialMemoryRiskAt( point );
		}

		return visited.Count > 0 ? total / visited.Count : 0f;
	}

	private bool TryGetLearnedOpponentHotspot(
		Vector3 reference,
		float radius,
		out Vector3 hotspot,
		out float hotspotScore
	)
	{
		hotspot = Vector3.Zero;
		hotspotScore = 0f;

		float maxRadius = MathF.Max( 180f, radius );
		foreach ( KeyValuePair<(int X, int Y), SpatialMemoryCell> entry in _spatialMemory )
		{
			SpatialMemoryCell cell = entry.Value;
			DecaySpatialMemoryCell( cell );

			float learned =
				cell.OpponentPresence +
				cell.OpponentStationaryPresence * 1.35f;

			if ( learned <= 0.10f )
				continue;

			Vector3 center = GetSpatialMemoryCellCenter( entry.Key, reference.z );
			float distance = ( center - reference ).WithZ( 0f ).Length;
			if ( distance > maxRadius )
				continue;

			float recentCheckPenalty =
				Time.Now - cell.LastCheckedAt <= 5f ? 1.10f : 0f;
			float score =
				learned -
				( distance / maxRadius ) * 0.75f -
				recentCheckPenalty;

			if ( score <= hotspotScore )
				continue;

			hotspotScore = score;
			hotspot = center;
		}

		return hotspotScore >= MathF.Max( 0.25f, LearnedHotspotMinimumScore );
	}

	private void MarkLearnedHotspotChecked( Vector3 position )
	{
		SpatialMemoryCell cell =
			GetSpatialMemoryCell( GetSpatialMemoryKey( position ), false );

		if ( cell is null )
			return;

		cell.LastCheckedAt = Time.Now;
		_learnedHotspotChecks++;
	}

	private void UpdateSpatialMemoryDiagnostics()
	{
		float strongestDanger = 0f;
		float strongestHotspot = 0f;

		foreach ( SpatialMemoryCell cell in _spatialMemory.Values )
		{
			DecaySpatialMemoryCell( cell );
			strongestDanger =
				MathF.Max(
					strongestDanger,
					cell.Danger + cell.DeathDanger * 1.25f
				);
			strongestHotspot =
				MathF.Max(
					strongestHotspot,
					cell.OpponentPresence + cell.OpponentStationaryPresence * 1.35f
				);
		}

		SpatialMemoryStatus =
			$"CELLS {_spatialMemory.Count} · DEATHS {_spatialDeathCount} · HOT {strongestHotspot:0.0} · RISK {strongestDanger:0.0}";

		AwarenessStatus =
			HasFreshHearing()
				? HasActionableHearing()
					? $"AUDIO ACTION · {HearingBearing}"
					: $"AUDIO NOTICED / NO SNAP · {HearingBearing}"
				: "VISUAL FOV / LOS · QUIET";
	}

	private void UpdateTacticalContext()
	{
		if ( !UsesTacticalBehavior() )
		{
			TacticalAggression = 0.50f;
			TacticalContextStatus = "OFF";
			return;
		}

		float ownHealthValue =
			_health?.IsValid == true ? _health.Health : 0f;
		float ownMaxHealth =
			_health?.IsValid == true ? MathF.Max( _health.MaxHealth, 1f ) : 1f;
		float ownHealthFraction =
			_health?.IsValid == true
				? MathX.Clamp( ownHealthValue / ownMaxHealth, 0f, 1f )
				: 1f;

		PlayerState human = ResolveHumanTarget( _perceptionTarget );
		PlayerHealth opponentHealth =
			human?.GameObject?.Components.Get<PlayerHealth>();

		float opponentHealthFraction = ownHealthFraction;
		bool knowsOpponentHealth =
			opponentHealth?.IsValid == true && opponentHealth.MaxHealth > 0f;

		if ( knowsOpponentHealth )
		{
			opponentHealthFraction =
				MathX.Clamp(
					opponentHealth.Health / opponentHealth.MaxHealth,
					0f,
					1f
				);
		}

		float healthAdvantage =
			ownHealthFraction - opponentHealthFraction;

		// Outside a timed Match (Sandbox, for example), health advantage gently
		// encourages pressure. This information is fair because OMR already exposes
		// both health bars to human players in the HUD.
		float aggression =
			0.50f + healthAdvantage * 0.30f;

		// BOT 6 adds bounded tactical variation plus a learned counter-style. These
		// are intentionally small nudges, never stat cheats or hidden information.
		aggression += _dynamicPressureBias * 0.55f;
		aggression += GetAdaptivePressureAdjustment();

		if ( ActiveModifierIs( RoundModifier.Blitz ) )
			aggression += 0.14f;
		else if ( ActiveModifierIs( RoundModifier.HipfireOnly ) )
			aggression += 0.07f;
		else if ( ActiveModifierIs( RoundModifier.LargeCaliber ) )
			aggression -= 0.04f;
		else if ( ActiveModifierIs( RoundModifier.HeadshotOnly ) )
			aggression -= 0.025f;

		if ( opponentHealthFraction <= 0.30f )
			aggression += 0.14f;

		if ( ownHealthFraction <= 0.30f )
			aggression -= 0.10f;

		float timeRemaining = -1f;
		RoundManager roundManager =
			Scene?
				.GetAllComponents<RoundManager>()
				.FirstOrDefault();

		if (
			roundManager?.Mode == SessionMode.Match &&
			roundManager.Phase == RoundPhase.Fighting &&
			roundManager.FightEndsAt > 0f
		)
		{
			timeRemaining =
				MathF.Max( 0f, roundManager.FightEndsAt - Time.Now );

			if ( timeRemaining <= 12f )
			{
				float urgency =
					1f - MathX.Clamp( timeRemaining / 12f, 0f, 1f );

				if ( healthAdvantage > 0.035f )
				{
					// OMR awards timeout by remaining health. When ahead late, a human
					// has a strong reason to protect the lead rather than donate a duel.
					aggression -= 0.42f * urgency;
				}
				else if ( healthAdvantage < -0.035f )
				{
					// When behind and the clock is dying, caution is already a losing
					// strategy. Force a fight instead of politely timing out.
					aggression += 0.48f * urgency;
				}
			}
		}

		TacticalAggression = MathX.Clamp( aggression, 0.08f, 0.95f );

		string posture;
		if ( timeRemaining >= 0f && timeRemaining <= 12f && healthAdvantage > 0.035f )
			posture = "PROTECT LEAD";
		else if ( timeRemaining >= 0f && timeRemaining <= 12f && healthAdvantage < -0.035f )
			posture = "FORCE FIGHT";
		else if ( opponentHealthFraction <= 0.30f && ownHealthFraction > opponentHealthFraction )
			posture = "FINISH PRESSURE";
		else if ( healthAdvantage >= 0.16f )
			posture = "PRESS ADVANTAGE";
		else if ( healthAdvantage <= -0.16f )
			posture = "RECOVER / TRADE CAREFULLY";
		else
			posture = "BALANCED";

		string timeText =
			timeRemaining >= 0f
				? $" · {timeRemaining:0.0}s"
				: string.Empty;

		if ( knowsOpponentHealth )
		{
			TacticalContextStatus =
				$"{posture} · HP {ownHealthValue:0}/{ownMaxHealth:0} vs {opponentHealth.Health:0}/{opponentHealth.MaxHealth:0}{timeText}";
		}
		else
		{
			TacticalContextStatus = $"{posture}{timeText}";
		}
	}

	private void UpdateThreatMemory()
	{
		if ( !UsesTacticalBehavior() )
		{
			ThreatStatus = "OFF";
			ThreatBearing = "NONE";
			ThreatAgeSeconds = -1f;
			return;
		}

		if ( _health?.IsValid != true )
			_health = Components.Get<PlayerHealth>();

		if ( _health?.IsValid != true )
		{
			ThreatStatus = "NO HEALTH";
			ThreatBearing = "NONE";
			ThreatAgeSeconds = -1f;
			return;
		}

		int sequence = _health.DamageFeedbackSequence;

		if ( _lastProcessedDamageSequence < 0 )
			_lastProcessedDamageSequence = sequence;

		if ( sequence != _lastProcessedDamageSequence )
		{
			_lastProcessedDamageSequence = sequence;

			if (
				_health.DamageFeedbackAmount > 0f &&
				_health.DamageFeedbackHasDirectionalSource
			)
			{
				RegisterBlindThreatHit();
				SpatialMemoryCell hitCell =
					GetSpatialMemoryCell( GetSpatialMemoryKey( WorldPosition ), true );
				hitCell.Danger =
					MathF.Min(
						12f,
						hitCell.Danger +
						MathX.Clamp( _health.DamageFeedbackAmount / 90f, 0.15f, 1.15f )
					);

				Vector3 rawDirection =
					( _health.DamageFeedbackSourcePosition - WorldPosition )
						.WithZ( 0f );

				if ( !rawDirection.IsNearlyZero( 0.01f ) )
				{
					float uncertainty = GetThreatDirectionUncertainty();
					float phase =
						sequence * 1.731f +
						BotSlot * 0.917f;
					float noisyYaw =
						Rotation.LookAt( rawDirection.Normal, Vector3.Up ).Angles().yaw +
						MathF.Sin( phase ) * uncertainty;

					Vector3 previousThreatDirection = _lastThreatDirection;

					_lastThreatDirection =
						Rotation.FromYaw( noisyYaw )
							.Forward
							.WithZ( 0f )
							.Normal;

					_lastThreatAt = Time.Now;
					_threatOrientUntil = Time.Now + GetThreatOrientDuration();
					ThreatStatus = "RECENT DAMAGE";
					ThreatBearing = DescribeThreatBearing();
					ThreatAgeSeconds = 0f;

					// Re-evaluate an existing cover route only when the new hit suggests a
					// materially different attack sector. Recomputing on every automatic-
					// weapon hit would make the bot jitter between candidate walls.
					if (
						_hasCoverTarget &&
						!previousThreatDirection.IsNearlyZero( 0.01f ) &&
						previousThreatDirection.Dot( _lastThreatDirection ) < 0.5f
					)
					{
						_hasCoverTarget = false;
						_coverHoldUntil = -1f;
						CoverStatus = "REASSESSING";
						_nextCoverDecisionAt = Time.Now + 0.10f;
					}
				}
			}
		}

		if ( HasRecentThreat() )
		{
			ThreatStatus = "RECENT DAMAGE";
			ThreatAgeSeconds =
				MathF.Round( MathF.Max( 0f, Time.Now - _lastThreatAt ) * 10f ) / 10f;
			ThreatBearing = DescribeThreatBearing();
		}
		else
		{
			ThreatStatus = "NONE";
			ThreatBearing = "NONE";
			ThreatAgeSeconds = -1f;
		}
	}

	private bool HasRecentThreat() =>
		!_lastThreatDirection.IsNearlyZero( 0.01f ) &&
		Time.Now - _lastThreatAt >= 0f &&
		Time.Now - _lastThreatAt <= MathF.Max( 0.5f, ThreatMemoryDuration );

	private float GetThreatDirectionUncertainty() =>
		Difficulty switch
		{
			OMRBotDifficulty.Easy => 30f,
			OMRBotDifficulty.Hard => 14f,
			_ => 22f
		};

	private float GetThreatOrientDuration() =>
		Difficulty switch
		{
			OMRBotDifficulty.Easy => 0.60f,
			OMRBotDifficulty.Hard => 0.38f,
			_ => 0.48f
		};

	private void OrientTowardThreat()
	{
		if ( _controller?.IsValid != true || _lastThreatDirection.IsNearlyZero( 0.01f ) )
			return;

		Angles desired =
			Rotation.LookAt( _lastThreatDirection, Vector3.Up ).Angles();

		float orientSpeed = Difficulty switch
		{
			OMRBotDifficulty.Easy => 4.8f,
			OMRBotDifficulty.Hard => 7.0f,
			_ => 5.8f
		};

		float follow =
			1f - MathF.Exp( -orientSpeed * MathF.Max( Time.Delta, 0f ) );

		Rotation smoothed = Rotation.Slerp(
			_controller.EyeAngles.ToRotation(),
			new Angles( 0f, desired.yaw, 0f ).ToRotation(),
			MathX.Clamp( follow, 0f, 1f )
		);

		Angles result = smoothed.Angles();
		_controller.EyeAngles = new Angles( 0f, result.yaw, 0f );
	}

	private string DescribeThreatBearing()
	{
		if ( _controller?.IsValid != true || _lastThreatDirection.IsNearlyZero( 0.01f ) )
			return "UNKNOWN";

		float threatYaw =
			Rotation.LookAt( _lastThreatDirection, Vector3.Up ).Angles().yaw;
		float delta =
			MathX.DeltaDegrees( _controller.EyeAngles.yaw, threatYaw );
		float absolute = MathF.Abs( delta );

		if ( absolute <= 22.5f )
			return "FRONT";
		if ( absolute >= 157.5f )
			return "REAR";
		if ( absolute <= 67.5f )
			return delta > 0f ? "FRONT-RIGHT" : "FRONT-LEFT";
		if ( absolute <= 112.5f )
			return delta > 0f ? "RIGHT" : "LEFT";
		return delta > 0f ? "REAR-RIGHT" : "REAR-LEFT";
	}

	private float GetOwnHealthFraction()
	{
		if ( _health?.IsValid != true || _health.MaxHealth <= 0f )
			return 1f;

		return MathX.Clamp( _health.Health / _health.MaxHealth, 0f, 1f );
	}

	private bool TryGetOpponentHealthFraction( out float fraction )
	{
		fraction = 1f;
		PlayerState human = ResolveHumanTarget( _perceptionTarget );
		PlayerHealth health = human?.GameObject?.Components.Get<PlayerHealth>();

		if ( health?.IsValid != true || health.MaxHealth <= 0f )
			return false;

		fraction = MathX.Clamp( health.Health / health.MaxHealth, 0f, 1f );
		return true;
	}

	private void EvaluateTacticalActionScores(
		OneMoreRoundWeapon weapon,
		bool hasVisual,
		bool recentThreat,
		bool lowHealth,
		bool needsReload,
		out float engageScore,
		out float coverScore
	)
	{
		float ownHealth = GetOwnHealthFraction();
		float opponentHealth = 1f;
		TryGetOpponentHealthFraction( out opponentHealth );

		engageScore = hasVisual ? 58f : 0f;
		coverScore = 18f;

		engageScore += MathX.Clamp( TacticalAggression, 0f, 1f ) * 58f;
		coverScore += ( 1f - MathX.Clamp( TacticalAggression, 0f, 1f ) ) * 48f;

		engageScore += _dynamicPressureBias * 30f;
		coverScore += _dynamicCoverBias * 28f;

		float adaptiveConfidence = GetAdaptiveConfidenceWeight();
		if ( adaptiveConfidence > 0f )
		{
			// A habitual rusher makes cover/space slightly more valuable; a passive
			// opponent makes proactive engagement and angle changes more attractive.
			coverScore +=
				MathF.Max( 0f, _adaptiveOpponentAggression - 0.55f ) *
				28f *
				adaptiveConfidence;
			engageScore +=
				MathF.Max( 0f, 0.48f - _adaptiveOpponentAggression ) *
				24f *
				adaptiveConfidence;
		}

		if ( ActiveModifierIs( RoundModifier.Blitz ) )
		{
			engageScore += 16f;
			coverScore -= 8f;
		}
		else if ( ActiveModifierIs( RoundModifier.LargeCaliber ) )
		{
			coverScore += 7f;
		}
		else if ( ActiveModifierIs( RoundModifier.HeadshotOnly ) )
		{
			coverScore += 4f;
		}

		if ( weapon?.IsValid == true )
		{
			if ( weapon.Clip1 > 0 && !weapon.IsReloading )
				engageScore += 24f;
			else
				engageScore -= 35f;

			if (
				ActiveModifierIs( RoundModifier.LargeCaliber ) &&
				weapon.UsesPrimaryClip &&
				weapon.PrimaryClipSize > 0 &&
				weapon.Clip1 <= Math.Max( 2, (int)MathF.Ceiling( weapon.PrimaryClipSize * 0.34f ) )
			)
			{
				coverScore += 18f;
				engageScore -= 8f;
			}

			if ( hasVisual )
			{
				float distance =
					( _observedTargetPosition - WorldPosition ).WithZ( 0f ).Length;
				float maxRange = GetMaximumFireDistance( weapon );
				float holdRange = MathF.Max( 80f, GetCombatHoldDistance( weapon ) );

				if ( distance <= maxRange )
					engageScore += 18f;
				else
					engageScore -= 18f;

				float rangeError = MathF.Abs( distance - holdRange ) / holdRange;
				engageScore += MathF.Max( 0f, 18f - rangeError * 18f );
			}
		}

		if ( opponentHealth <= 0.35f )
			engageScore += 28f;
		if ( opponentHealth <= 0.18f )
			engageScore += 14f;

		if ( ownHealth <= 0.38f )
			coverScore += 34f;
		if ( ownHealth <= 0.22f )
			coverScore += 22f;

		if ( lowHealth )
			coverScore += 30f;

		if ( recentThreat )
		{
			coverScore += hasVisual ? 18f : 42f;
			engageScore -= hasVisual ? 4f : 38f;
		}

		if ( needsReload )
		{
			coverScore += 105f;
			engageScore -= 85f;
		}

		if ( hasVisual )
			coverScore -= 16f;
		else
			coverScore += 12f;

		if ( opponentHealth <= 0.30f && hasVisual )
			coverScore -= 24f;
	}

	private bool ShouldInterruptCoverForEngage( OneMoreRoundWeapon weapon )
	{
		if (
			!_hasCoverTarget ||
			_coverReason == "RELOAD" ||
			_coverPeekActive ||
			!_hasConfirmedSight ||
			_perceptionTarget?.IsAlive != true ||
			weapon?.IsValid != true ||
			weapon.IsReloading ||
			weapon.Clip1 <= 0
		)
			return false;

		float coverDistance = ( _coverTarget - WorldPosition ).WithZ( 0f ).Length;
		if ( coverDistance <= MathF.Max( 36f, CoverArrivalDistance * 1.5f ) )
			return false;

		float ownHealth = GetOwnHealthFraction();
		bool lowHealth = ownHealth <= MathX.Clamp( LowHealthCoverFraction, 0.15f, 0.75f );

		EvaluateTacticalActionScores(
			weapon,
			hasVisual: true,
			recentThreat: HasRecentThreat(),
			lowHealth: lowHealth,
			needsReload: false,
			out float engageScore,
			out float coverScore
		);

		return engageScore >= coverScore + MathF.Max( 0f, CoverEngageInterruptMargin );
	}

	private void UpdateUnderFireReaction( OneMoreRoundWeapon weapon )
	{
		ReleaseBotWeaponIntent( weapon );
		OrientTowardThreat();

		float side = _strafeDirection >= 0f ? 1f : -1f;
		float lateral = MathX.Clamp( UnderFireEvadeStrength, 0.2f, 1f ) * side;
		Vector3 moveInput = new Vector3( -0.10f, lateral, 0f ).ClampLength( 1f );

		_movementInput?.SetBotInput(
			moveInput,
			sprintDown: false,
			crouchDown: GetBotCrouchButtonDown(),
			jumpPressed: false
		);

		SetMovementDiagnostics( side > 0f ? "UNDER FIRE / EVADE RIGHT" : "UNDER FIRE / EVADE LEFT" );
		TacticalStatus = "UNDER FIRE / LOCATE + EVADE";
		CoverStatus = "ASSESSING";
		CombatStatus = "LOCATING ATTACK SECTOR";
		CurrentIntent = "TACTICAL / REACT TO FIRE";
	}

	private bool TryHandleLegacyTacticalPriority( OneMoreRoundWeapon weapon )
	{
		if ( !UsesTacticalBehavior() )
			return false;

		bool recentThreat = HasRecentThreat();
		bool hasVisual = _hasConfirmedSight && _perceptionTarget?.IsAlive == true;
		bool hasMemory = HasFreshMemory();
		bool needsReload =
			weapon?.IsValid == true &&
			(
				weapon.IsReloading ||
				weapon.Clip1 == 0 ||
				(
					ActiveModifierIs( RoundModifier.LargeCaliber ) &&
					weapon.UsesPrimaryClip &&
					weapon.PrimaryClipSize > 0 &&
					weapon.Ammo1 > 0 &&
					weapon.Clip1 <= Math.Max( 1, (int)MathF.Floor( weapon.PrimaryClipSize * 0.24f ) )
				)
			);

		if ( hasVisual && _searchPoints.Count > 0 )
			ClearSearchPlan( "CONTACT" );

		if (
			recentThreat &&
			!hasVisual &&
			Time.Now < _threatOrientUntil
		)
		{
			UpdateUnderFireReaction( weapon );
			return true;
		}

		if ( _hasCoverTarget )
		{
			if ( ShouldInterruptCoverForEngage( weapon ) )
			{
				ClearCoverPlan( "INTERRUPTED / ENGAGE" );
				TacticalStatus = "ENGAGE / COVER INTERRUPTED";
				return false;
			}

			if ( UpdateActiveCoverPlan( weapon ) )
				return true;
		}

		if ( _flankActive && TryHandleFlankPlan( weapon ) )
			return true;

		// A short burst at the *last actually observed* position gives automatic
		// weapons a believable suppressive behavior without granting wall vision.
		// Physical ballistics still decide whether those rounds hit cover or an
		// opponent who happens to re-peek.
		if ( !hasVisual && TryHandleSuppressiveFire( weapon ) )
			return true;

		if ( hasVisual && TryStartFlank( weapon ) )
			return true;

		float healthFraction = GetOwnHealthFraction();
		bool lowHealth =
			healthFraction <= MathX.Clamp( LowHealthCoverFraction, 0.15f, 0.75f ) &&
			Time.Now >= _nextLowHealthCoverAt;

		EvaluateTacticalActionScores(
			weapon,
			hasVisual,
			recentThreat,
			lowHealth,
			needsReload,
			out float engageScore,
			out float coverScore
		);

		string reason = null;

		if ( needsReload && ( hasVisual || hasMemory || recentThreat || HasFreshHearing() ) )
		{
			reason = "RELOAD";
		}
		else if ( recentThreat && !hasVisual )
		{
			// Getting hit while blind is evidence, not an unconditional retreat
			// order. Healthy/aggressive bots first turn toward and investigate the
			// threat sector; damaged/cautious bots still prefer hard cover.
			bool defensiveReaction =
				healthFraction <= 0.58f ||
				TacticalAggression <= 0.43f ||
				( healthFraction <= 0.78f && TacticalAggression < 0.60f );

			if ( defensiveReaction )
				reason = "UNDER FIRE";
			else
			{
				TacticalStatus = "INVESTIGATE FIRE DIRECTION";
				CoverStatus = "NONE";
				if ( TryHandleIntelligentSearch( weapon ) )
					return true;
			}
		}
		else if (
			( recentThreat || ( lowHealth && hasVisual ) ) &&
			coverScore > engageScore + MathF.Max( 0f, CoverEngageInterruptMargin )
		)
		{
			reason = recentThreat ? "UNDER FIRE" : "LOW HEALTH";
		}

		if ( reason is not null && Time.Now >= _nextCoverDecisionAt )
		{
			if ( !TryResolveThreatReference( out Vector3 threatReference, out Vector3 threatDirection ) )
			{
				TacticalStatus = $"{reason} / NO THREAT VECTOR";
				CoverStatus = "NO REFERENCE";
				_nextCoverDecisionAt = Time.Now + 0.5f;
			}
			else if ( !TryChooseCoverPosition( weapon, threatReference, threatDirection, out OMRCoverChoice cover ) )
			{
				TacticalStatus = $"{reason} / NO COVER";
				CoverStatus = "NO CANDIDATE";
				_nextCoverDecisionAt = Time.Now + MathF.Max( 0.5f, CoverDecisionCooldown );
			}
			else
			{
				_hasCoverTarget = true;
				_coverTarget = cover.Anchor;
				_coverReason = reason;
				_coverHoldUntil = -1f;
				_coverPosture = cover.Posture;
				_coverLeftPeek = cover.LeftPeek;
				_coverRightPeek = cover.RightPeek;
				_coverHasLeftPeek = cover.HasLeftPeek;
				_coverHasRightPeek = cover.HasRightPeek;
				_coverPeekActive = false;
				_coverPeekReturning = false;
				_coverPeekUntil = -1f;
				_nextCoverPeekAt = Time.Now + 0.12f;
				_nextCoverDecisionAt = Time.Now + MathF.Max( 0.5f, CoverDecisionCooldown );

				if ( reason == "LOW HEALTH" )
					_nextLowHealthCoverAt = Time.Now + MathF.Max( 2f, LowHealthDecisionCooldown );

				TacticalStatus = $"SEEK COVER / {reason}";
				CoverStatus = $"SEEKING {reason} · {_coverPosture.ToString().ToUpperInvariant()}";
				ClearSearchPlan( "COVER" );
				CancelFlank( "COVER PRIORITY" );
				return UpdateActiveCoverPlan( weapon );
			}
		}

		if ( !hasVisual )
		{
			CoverStatus = "NONE";
			if ( TryHandleIntelligentSearch( weapon ) )
				return true;
		}

		TacticalStatus = hasVisual
			? $"ENGAGE · E{engageScore:0} C{coverScore:0}"
			: hasMemory || HasFreshHearing()
				? "SEARCH"
				: "PATROL";

		if ( !_hasCoverTarget )
			CoverStatus = "NONE";
		return false;
	}

	private bool UpdateActiveCoverPlan( OneMoreRoundWeapon weapon )
	{
		if ( !_hasCoverTarget )
			return false;

		if ( _coverPeekActive )
			return UpdateActiveCoverPeek( weapon );

		Vector3 delta = ( _coverTarget - WorldPosition ).WithZ( 0f );
		float distance = delta.Length;
		bool arrived = distance <= MathF.Max( 28f, CoverArrivalDistance );

		if ( !arrived )
			return UpdateCoverTravel( weapon, distance );

		_coverTravelStartedAt = -1f;

		_pathPoints.Clear();
		_pathPointIndex = 0;
		NavigationStatus = "IN COVER";
		NavigationTargetName = "TACTICAL COVER";
		NavigationTargetDistance = MathF.Round( distance );
		CurrentIntent = $"TACTICAL COVER / {_coverReason}";
		TacticalStatus = $"IN COVER / {_coverReason}";

		if ( _coverReason == "RELOAD" )
		{
			EnsureBotCrouchState( _coverPosture != OMRCoverPosture.Firing );
			StopMovementOnly();
			ReleaseBotWeaponIntent( weapon );
			CombatWantsAim = false;
			CoverStatus = $"HOLDING RELOAD · {_coverPosture.ToString().ToUpperInvariant()}";

			if ( weapon?.IsValid == true && !weapon.IsReloading )
			{
				bool shouldReload =
					weapon.Clip1 == 0 ||
					(
						ActiveModifierIs( RoundModifier.LargeCaliber ) &&
						weapon.UsesPrimaryClip &&
						weapon.PrimaryClipSize > 0 &&
						weapon.Ammo1 > 0 &&
						weapon.Clip1 <= Math.Max( 1, (int)MathF.Floor( weapon.PrimaryClipSize * 0.28f ) )
					);

				if ( shouldReload )
				{
					weapon.BotTryReload();
					UpdateCombatAmmoDiagnostics( weapon );
				}
			}

			if ( weapon?.IsValid == true && weapon.IsReloading )
			{
				CombatStatus = "RELOADING IN COVER";
				return true;
			}
		}

		bool hasVisual = _hasConfirmedSight && _perceptionTarget?.IsAlive == true;
		bool hasMemory = HasFreshMemory();

		if ( TryHoldPrecisionResetInCover( weapon ) )
			return true;

		if ( _coverReason != "RELOAD" && ( hasVisual || hasMemory ) )
		{
			if ( _coverPosture == OMRCoverPosture.Firing && hasVisual )
			{
				EnsureBotCrouchState( false );
				StopMovementOnly();
				CoverStatus = "FIRING COVER / OVER TOP";
				TacticalStatus = "ENGAGE FROM COVER";
				UpdateCoverFire( weapon );
				_coverHoldUntil = Time.Now + MathF.Max( 0.35f, CoverHoldDuration );
				return true;
			}

			if ( _coverPosture == OMRCoverPosture.Crouch )
			{
				if ( Time.Now >= _nextCoverPeekAt )
				{
					EnsureBotCrouchState( false );
					StopMovementOnly();
					CoverStatus = "CROUCH COVER / STAND PEEK";
					TacticalStatus = "PEEK FROM LOW COVER";
					_coverPeekUntil = Time.Now + MathF.Max( 0.25f, CoverPeekDuration );
					_nextCoverPeekAt = _coverPeekUntil + MathF.Max( 0.25f, CoverPeekCooldown );
				}

				if ( Time.Now < _coverPeekUntil )
				{
					if ( hasVisual )
						UpdateCoverFire( weapon );
					else
						CombatStatus = "LOW COVER / ACQUIRING";
					return true;
				}

				EnsureBotCrouchState( true );
				StopMovementOnly();
				CoverStatus = "CROUCH COVER / HIDDEN";
			}
			else if (
				_coverPosture == OMRCoverPosture.Full &&
				Time.Now >= _nextCoverPeekAt &&
				( _coverHasLeftPeek || _coverHasRightPeek )
			)
			{
				StartCoverSidePeek();
				return UpdateActiveCoverPeek( weapon );
			}
			else
			{
				EnsureBotCrouchState( false );
				StopMovementOnly();
				CoverStatus = $"HOLDING {_coverPosture.ToString().ToUpperInvariant()}";
			}
		}
		else
		{
			EnsureBotCrouchState( _coverPosture == OMRCoverPosture.Crouch );
			StopMovementOnly();
			CoverStatus = $"HOLDING {_coverPosture.ToString().ToUpperInvariant()}";
		}

		if ( _coverHoldUntil < 0f )
		{
			float tacticalHold =
				MathX.Lerp(
					CoverHoldDuration * 1.20f,
					CoverHoldDuration * 0.55f,
					MathX.Clamp( TacticalAggression, 0f, 1f )
				);

			tacticalHold *=
				MathX.Clamp( 1f + _dynamicCoverBias * 0.75f, 0.72f, 1.30f );

			if ( ActiveModifierIs( RoundModifier.Blitz ) )
				tacticalHold *= 0.62f;
			else if ( ActiveModifierIs( RoundModifier.LargeCaliber ) )
				tacticalHold *= 1.10f;

			_coverHoldUntil = Time.Now + MathF.Max( 0.18f, tacticalHold );
		}

		if ( Time.Now < _coverHoldUntil )
		{
			CombatStatus = _coverReason == "LOW HEALTH"
				? "RECOVERING POSITION"
				: "HOLDING COVER";
			return true;
		}

		ClearCoverPlan( "COMPLETE" );
		return false;
	}

	private void EnsureBotCrouchState( bool wantsCrouch )
	{
		if ( _crouch?.IsValid != true || _slide?.IsSliding == true )
			return;

		if ( _crouch.WantsCrouch == wantsCrouch )
			return;

		if ( Time.Now < _crouchButtonHeldUntil )
			return;

		PulseCrouchButton();
	}

	private void StartCoverSidePeek()
	{
		bool chooseLeft;

		if ( _coverHasLeftPeek && _coverHasRightPeek )
		{
			chooseLeft = _coverPeekSide < 0;
			_coverPeekSide *= -1;
		}
		else
		{
			chooseLeft = _coverHasLeftPeek;
		}

		_coverPeekTarget = chooseLeft ? _coverLeftPeek : _coverRightPeek;
		_coverPeekActive = true;
		_coverPeekReturning = false;
		_coverPeekUntil = -1f;
		EnsureBotCrouchState( false );
	}

	private bool UpdateActiveCoverPeek( OneMoreRoundWeapon weapon )
	{
		if ( _hasConfirmedSight ) UpdateCombatAim( _observedTargetAimPoint );
		else if ( HasFreshMemory() ) LookTowardWorldPoint( _observedTargetAimPoint, 7f );
		Vector3 target = _coverPeekReturning ? _coverTarget : _coverPeekTarget;
		float distance = ( target - WorldPosition ).WithZ( 0f ).Length;
		float arrival = MathF.Max( 18f, CoverPeekArrivalDistance );

		if ( distance > arrival )
		{
			NavigateToWorldPosition(
				target,
				_coverPeekReturning ? "COVER ANCHOR" : "COVER PEEK",
				arrival,
				_coverPeekReturning ? "RETURN TO COVER" : "MOVE TO COVER PEEK",
				allowSprint: false,
				faceMovement: false,
				advancedMovement: true,
				movementWeapon: weapon,
				visibleCombatTarget: _hasConfirmedSight
			);
			CoverStatus = _coverPeekReturning ? "RETURNING TO ANCHOR" : "MOVING TO PEEK";
			TacticalStatus = _coverPeekReturning ? "COVER RESET" : "SIDE PEEK";
			return true;
		}

		StopMovementOnly();

		if ( _coverPeekReturning )
		{
			_coverPeekActive = false;
			_coverPeekReturning = false;
			_coverPeekUntil = -1f;
			_nextCoverPeekAt = Time.Now + MathF.Max( 0.25f, CoverPeekCooldown );
			CoverStatus = "BACK AT ANCHOR";
			return true;
		}

		if ( _coverPeekUntil < 0f )
			_coverPeekUntil = Time.Now + MathF.Max( 0.25f, CoverPeekDuration );

		CoverStatus = "SIDE PEEK / FIRING POSITION";
		TacticalStatus = "ENGAGE FROM SIDE PEEK";

		if ( _hasConfirmedSight && _perceptionTarget?.IsAlive == true )
			UpdateCoverFire( weapon );
		else
			CombatStatus = "PEEK / ACQUIRING";

		if ( Time.Now >= _coverPeekUntil || ( HasRecentThreat() && ThreatAgeSeconds <= 0.25f ) )
		{
			_coverPeekReturning = true;
			_coverPeekUntil = -1f;
		}

		return true;
	}

	private void UpdateCoverFire( OneMoreRoundWeapon weapon )
	{
		if (
			weapon?.IsValid != true ||
			!_hasConfirmedSight ||
			_perceptionTarget?.IsAlive != true
		)
			return;

		float distance =
			( _observedTargetPosition - WorldPosition ).WithZ( 0f ).Length;

		UpdateCombatAim( _observedTargetAimPoint );
		bool wantsAds = ShouldUseAds( weapon, distance );
		CombatWantsAim = wantsAds;
		weapon.SetBotAimIntent( wantsAds );
		UpdateVisibleWeaponAttack( weapon, distance, wantsAds );
	}

	private bool TryResolveThreatReference(
		out Vector3 threatReference,
		out Vector3 threatDirection
	)
	{
		if ( _hasConfirmedSight && _perceptionTarget?.IsAlive == true )
		{
			threatReference = _observedTargetPosition + Vector3.Up * 34f;
			threatDirection =
				( _observedTargetPosition - WorldPosition )
					.WithZ( 0f );
			if ( !threatDirection.IsNearlyZero( 0.01f ) )
				threatDirection = threatDirection.Normal;
			return !threatDirection.IsNearlyZero( 0.01f );
		}

		if ( HasRecentThreat() )
		{
			threatDirection = _lastThreatDirection;
			threatReference =
				WorldPosition +
				threatDirection * MathF.Max( 500f, ThreatProbeDistance ) +
				Vector3.Up * 46f;
			return true;
		}

		if ( HasFreshMemory() )
		{
			threatReference = LastKnownPosition + Vector3.Up * 34f;
			threatDirection =
				( LastKnownPosition - WorldPosition )
					.WithZ( 0f );
			if ( !threatDirection.IsNearlyZero( 0.01f ) )
				threatDirection = threatDirection.Normal;
			return !threatDirection.IsNearlyZero( 0.01f );
		}

		if ( HasActionableHearing() )
		{
			threatReference = _lastHeardPosition + Vector3.Up * 34f;
			threatDirection = ( _lastHeardPosition - WorldPosition ).WithZ( 0f );
			if ( !threatDirection.IsNearlyZero( 0.01f ) )
				threatDirection = threatDirection.Normal;
			return !threatDirection.IsNearlyZero( 0.01f );
		}

		if ( TryGetBestOpponentBelief( out Vector3 beliefThreat, out float beliefConfidence ) && beliefConfidence >= 0.06f )
		{
			threatReference = beliefThreat + Vector3.Up * 34f;
			threatDirection = ( beliefThreat - WorldPosition ).WithZ( 0f );
			if ( !threatDirection.IsNearlyZero( 0.01f ) )
				threatDirection = threatDirection.Normal;
			return !threatDirection.IsNearlyZero( 0.01f );
		}

		threatReference = Vector3.Zero;
		threatDirection = Vector3.Zero;
		return false;
	}

	private bool TryChooseCoverPosition(
		OneMoreRoundWeapon weapon,
		Vector3 threatReference,
		Vector3 threatDirection,
		out OMRCoverChoice bestChoice
	)
	{
		bestChoice = default;
		if ( Scene?.NavMesh is null || !Scene.NavMesh.IsEnabled ||
			Scene.NavMesh.IsGenerating || threatDirection.IsNearlyZero( 0.01f ) ) return false;

		// First shortlist protected nearby endpoints; expensive complete-path and
		// exposure tests only run for useful cover, rather than empty arena space.
		Vector3 away = ( -threatDirection ).WithZ( 0f ).Normal;
		float minDistance = MathF.Max( 80f, CoverCandidateMinDistance );
		float maxDistance = MathF.Max( minDistance + 40f, CoverCandidateMaxDistance );
		if ( Time.Now >= _nextCoverShortlistAt ||
			( WorldPosition - _coverShortlistOrigin ).Length > 24f ||
			( threatReference - _coverShortlistThreat ).Length > 24f )
		{
			_nextCoverShortlistAt = Time.Now + 0.25f;
			_coverShortlistOrigin = WorldPosition;
			_coverShortlistThreat = threatReference;
			_coverShortlist.Clear();
			for ( int ring = 0; ring < 4; ring++ )
			{
				float distance = ring switch
				{
					0 => MathF.Min( 96f, minDistance ),
					1 => minDistance,
					2 => ( minDistance + maxDistance ) * 0.5f,
					_ => maxDistance
				};
				foreach ( float angle in CoverSearchAngles )
				{
					Vector3 direction = ( Rotation.FromYaw( angle ) * away ).WithZ( 0f ).Normal;
					Vector3 raw = WorldPosition + direction * distance;
					Vector3? projected = Scene.NavMesh.GetClosestPoint( raw, 72f );
					if ( projected is null ) continue;
					Vector3 candidate = projected.Value;
					float travel = ( candidate - WorldPosition ).WithZ( 0f ).Length;
					if ( travel < 48f || ( candidate - raw ).WithZ( 0f ).Length > 60f ) continue;
					bool duplicate = false;
					foreach ( var item in _coverShortlist )
						if ( ( item.Point - candidate ).Length < 36f ) { duplicate = true; break; }
					if ( duplicate ) continue;
					int protection = CountBlockedThreatSamples( candidate, threatReference );
					if ( protection == 0 ) continue;
					float risk = GetSpatialMemoryRiskAt( candidate );
					// Adjacent side-steps into protection win over long perimeter retreats.
					float priority = protection * 55f - travel * 0.45f - risk * 10f;
					_coverShortlist.Add( ( candidate, priority ) );
				}
			}
			_coverShortlist.Sort( ( a, b ) => b.Priority.CompareTo( a.Priority ) );
		}
		float bestScore = float.MinValue;
		OMRBotTacticalPositionEvaluation bestEvaluation = default;
		OMRBotWeaponDoctrine doctrine = GetWeaponDoctrine( weapon );
		float desiredRange = MathF.Max( 90f, doctrine.LegacyHoldDistance );
		foreach ( var item in _coverShortlist )
		{
			if ( _tacticalPathQueriesRemaining <= 0 ) break;
			if ( !TryEvaluateTacticalPosition( item.Point, OMRBotTacticalQueryPurpose.Cover,
				doctrine, threatReference, true, threatReference, desiredRange,
				out OMRBotTacticalPositionEvaluation evaluation ) ) continue;
			if ( evaluation.Route.PathLength > maxDistance * 2f || !IsCoverApproachSafe( evaluation.Route ) ) continue;
			Vector3 candidate = evaluation.Position;
			OMRCoverPosture posture = ClassifyCoverPosture( candidate, threatReference );
			if ( posture == OMRCoverPosture.None ) continue;
			EvaluateCoverOptions( candidate, threatReference, threatDirection, out int mobilityOptions,
				out Vector3 leftPeek, out Vector3 rightPeek, out bool hasLeftPeek, out bool hasRightPeek );
			int peekOptions = ( hasLeftPeek ? 1 : 0 ) + ( hasRightPeek ? 1 : 0 );
			// A blind alcove is a poor place to disengage when still trading fire.
			if ( _hasConfirmedSight && mobilityOptions == 0 ) continue;
			float postureBonus = posture switch
			{
				OMRCoverPosture.Firing => 280f,
				OMRCoverPosture.Crouch => 210f,
				_ => 155f
			};
			float earlyProtection = evaluation.Route.FirstProtectionDistance >= 0f
				? MathF.Max( 0f, 160f - evaluation.Route.FirstProtectionDistance ) * 1.1f : -120f;
			float passivePenalty = posture == OMRCoverPosture.Full && peekOptions == 0 ? 150f : 0f;
			float score = evaluation.Score + postureBonus + earlyProtection +
				mobilityOptions * 48f + peekOptions * 80f - passivePenalty -
				evaluation.Route.PathLength * 0.36f - evaluation.Route.ExposureFraction * 180f;
			if ( score <= bestScore ) continue;
			bestScore = score;
			bestEvaluation = evaluation;
			bestChoice = new OMRCoverChoice( candidate, posture, leftPeek, rightPeek, hasLeftPeek, hasRightPeek, score );
		}
		if ( bestScore == float.MinValue ) return false;
		SetTacticalQueryDiagnostic( OMRBotTacticalQueryPurpose.Cover, bestEvaluation );
		return true;
	}
	private OMRCoverPosture ClassifyCoverPosture(
		Vector3 candidate,
		Vector3 threatReference
	)
	{
		bool standingEyeBlocked =
			IsThreatRayBlocked( candidate + Vector3.Up * 64f, threatReference );
		bool standingTorsoBlocked =
			IsThreatRayBlocked( candidate + Vector3.Up * 40f, threatReference );
		bool crouchEyeBlocked =
			IsThreatRayBlocked( candidate + Vector3.Up * 42f, threatReference );
		bool crouchTorsoBlocked =
			IsThreatRayBlocked( candidate + Vector3.Up * 25f, threatReference );

		// Ideal low/medium cover: the weapon/head can see over it while the torso
		// remains protected. This is the highest-value fighting posture.
		if ( !standingEyeBlocked && standingTorsoBlocked )
			return OMRCoverPosture.Firing;

		// Tall geometry blocks both standing samples. It is safe, but needs a side
		// peek before it becomes an offensive position.
		if ( standingEyeBlocked && standingTorsoBlocked )
			return OMRCoverPosture.Full;

		// Low geometry can still be useful when ducking even if standing would
		// expose most of the body.
		if ( crouchEyeBlocked && crouchTorsoBlocked )
			return OMRCoverPosture.Crouch;

		return OMRCoverPosture.None;
	}

	private void EvaluatePathExposure(
		NavMeshPath path,
		Vector3 threatReference,
		out int exposedSamples,
		out int partialSamples,
		out int protectedSamples,
		out float firstProtectionDistance
	)
	{
		exposedSamples = 0;
		partialSamples = 0;
		protectedSamples = 0;
		firstProtectionDistance = -1f;

		Vector3 previous = WorldPosition;
		float travelled = 0f;
		float totalPathLength = CalculatePathLength( path );
		float spacing = MathF.Max( MathF.Max( 36f, CoverRouteSampleSpacing ), totalPathLength / 10f );
		float nextSampleDistance = spacing;

		foreach ( NavMeshPathPoint point in path.Points )
		{
			Vector3 delta = point.Position - previous;
			float segmentLength = delta.WithZ( 0f ).Length;

			if ( segmentLength <= 0.01f )
			{
				previous = point.Position;
				continue;
			}

			while ( nextSampleDistance <= travelled + segmentLength ||
				( travelled + segmentLength >= totalPathLength - 0.1f && nextSampleDistance - spacing < travelled + segmentLength - 0.1f ) )
			{
				float t = MathX.Clamp( ( nextSampleDistance - travelled ) / segmentLength, 0f, 1f );
				nextSampleDistance += spacing;
				Vector3 sample = Vector3.Lerp( previous, point.Position, t );
				int cover = CountBlockedThreatSamples( sample, threatReference );
				float sampleDistance = travelled + segmentLength * t;

				if ( cover >= 2 )
				{
					protectedSamples++;
					if ( firstProtectionDistance < 0f )
						firstProtectionDistance = sampleDistance;
				}
				else if ( cover == 1 )
				{
					partialSamples++;
					if ( firstProtectionDistance < 0f )
						firstProtectionDistance = sampleDistance;
				}
				else
				{
					exposedSamples++;
				}
			}

			travelled += segmentLength;
			previous = point.Position;
		}
	}

	private void EvaluateCoverOptions(
		Vector3 candidate,
		Vector3 threatReference,
		Vector3 threatDirection,
		out int mobilityOptions,
		out Vector3 leftPeek,
		out Vector3 rightPeek,
		out bool hasLeftPeek,
		out bool hasRightPeek
	)
	{
		mobilityOptions = 0;
		leftPeek = Vector3.Zero;
		rightPeek = Vector3.Zero;
		hasLeftPeek = false;
		hasRightPeek = false;

		if ( Scene?.NavMesh is null )
			return;

		Vector3 lateral =
			new Vector3( -threatDirection.y, threatDirection.x, 0f )
				.Normal;

		float sideDistance = MathF.Max( 45f, CoverSideProbeDistance );
		Vector3 away = ( -threatDirection ).WithZ( 0f ).Normal;

		Vector3[] optionDirections =
		{
			-lateral,
			lateral,
			away
		};

		for ( int i = 0; i < optionDirections.Length; i++ )
		{
			Vector3 optionDirection = optionDirections[i];
			Vector3 raw = candidate + optionDirection * sideDistance;
			Vector3? projected = Scene.NavMesh.GetClosestPoint( raw, 54f );

			if ( projected is null )
				continue;

			if ( ( projected.Value - candidate ).WithZ( 0f ).Length < sideDistance * 0.45f )
				continue;

			mobilityOptions++;

			if ( i >= 2 )
				continue;

			bool canSeeThreatFromEye =
				!IsThreatRayBlocked( projected.Value + Vector3.Up * 64f, threatReference );

			if ( !canSeeThreatFromEye )
				continue;

			if ( i == 0 )
			{
				leftPeek = projected.Value;
				hasLeftPeek = true;
			}
			else
			{
				rightPeek = projected.Value;
				hasRightPeek = true;
			}
		}
	}

	private float CalculatePathLength( NavMeshPath path )
	{
		Vector3 previous = WorldPosition;
		float length = 0f;

		foreach ( NavMeshPathPoint point in path.Points )
		{
			length += ( point.Position - previous ).WithZ( 0f ).Length;
			previous = point.Position;
		}

		return length;
	}

	private int CountBlockedThreatSamples(
		Vector3 candidate,
		Vector3 threatReference
	)
	{
		int blocked = 0;

		if ( IsThreatRayBlocked( candidate + Vector3.Up * 58f, threatReference ) )
			blocked++;

		if ( IsThreatRayBlocked( candidate + Vector3.Up * 34f, threatReference ) )
			blocked++;

		return blocked;
	}

	private bool IsThreatRayBlocked(
		Vector3 from,
		Vector3 to
	)
	{
		if ( Scene is null )
			return false;

		SceneTrace traceBuilder =
			Scene
				.Trace
				.Ray( from, to )
				.IgnoreGameObjectHierarchy( GameObject )
				.WithoutTags( "trigger" )
				.UseHitboxes( false );

		if ( _perceptionTarget?.GameObject is not null )
		{
			traceBuilder =
				traceBuilder.IgnoreGameObjectHierarchy( _perceptionTarget.GameObject );
		}

		SceneTraceResult trace = traceBuilder.Run();

		return trace.Hit;
	}

	private void ClearCoverPlan( string finalStatus )
	{
		if ( _coverReason == "UNDER FIRE" )
		{
			// Reaching valid cover consumes that particular damage reaction. A new
			// hit will immediately create a fresh threat event and force a reassess.
			_lastThreatAt = -999f;
		}

		EnsureBotCrouchState( false );
		_coverTravelStartedAt = -1f;
		_hasCoverTarget = false;
		_coverTarget = Vector3.Zero;
		_coverReason = string.Empty;
		_coverHoldUntil = -1f;
		_coverPosture = OMRCoverPosture.None;
		_coverLeftPeek = Vector3.Zero;
		_coverRightPeek = Vector3.Zero;
		_coverHasLeftPeek = false;
		_coverHasRightPeek = false;
		_coverPeekActive = false;
		_coverPeekReturning = false;
		_coverPeekTarget = Vector3.Zero;
		_coverPeekUntil = -1f;
		_nextCoverPeekAt = Time.Now + 0.25f;
		CoverStatus = finalStatus;
		_nextCoverDecisionAt =
			MathF.Max( _nextCoverDecisionAt, Time.Now + MathF.Max( 0.5f, CoverDecisionCooldown ) );
	}

	private void ResetTacticalState()
	{
		_lastProcessedDamageSequence =
			_health?.IsValid == true
				? _health.DamageFeedbackSequence
				: -1;
		_lastThreatAt = -999f;
		_lastThreatDirection = Vector3.Zero;
		_threatOrientUntil = -1f;
		_nextCoverDecisionAt = Time.Now + 0.4f;
		_nextLowHealthCoverAt = Time.Now + 1.5f;
		_hasCoverTarget = false;
		_coverTarget = Vector3.Zero;
		_coverReason = string.Empty;
		_coverHoldUntil = -1f;
		_coverPosture = OMRCoverPosture.None;
		_coverLeftPeek = Vector3.Zero;
		_coverRightPeek = Vector3.Zero;
		_coverHasLeftPeek = false;
		_coverHasRightPeek = false;
		_coverPeekActive = false;
		_coverPeekReturning = false;
		_coverPeekTarget = Vector3.Zero;
		_coverPeekUntil = -1f;
		_nextCoverPeekAt = Time.Now + 0.25f;
		_nextTraversalJumpAt = Time.Now + 0.35f;
		_traversalBypassUntil = -1f;
		_traversalBypassDirection = Vector3.Zero;
		_traversalFrameStatus = string.Empty;
		_traversalProgressStartedAt = -1f;
		_traversalBestDistance = float.MaxValue;
		_traversalProgressTarget = Vector3.Zero;
		_traversalPreferredBypassSign = 1;
		ResetTraversalOrbitWindow();
		_traversalRecoveryUntil = -1f;
		_traversalRecoveryDirection = Vector3.Zero;

		_lastSeenVelocity = Vector3.Zero;
		_lastSeenDirection = Vector3.Zero;
		_previousObservedPosition = Vector3.Zero;
		_previousObservedAt = -1f;
		_confirmedSightStartedAt = -1f;
		_sightWasConfirmedLastFrame = false;
		_lostSightAt = -999f;
		_heardOpponentWeapon = null;
		_heardOpponentWeaponEventCount = -1;
		_nextMovementHearingAt = 0f;
		_lastHeardPosition = Vector3.Zero;
		_lastHeardAt = -999f;
		_lastHeardConfidence = 0f;
		_lastHeardKind = string.Empty;
		_searchPoints.Clear();
		_searchPointIndex = 0;
		_searchPlanCreatedAt = -999f;
		_searchPauseUntil = -1f;
		_searchFacingDirection = Vector3.Zero;
		_searchEvidence = string.Empty;
		_flankActive = false;
		_flankTarget = Vector3.Zero;
		_nextFlankDecisionAt = Time.Now + 1.8f;
		_flankSide = BotSlot % 2 == 0 ? 1 : -1;
		_suppressionUntil = -1f;
		_nextSuppressionAt = Time.Now + 1.2f;
		_suppressionShotsRemaining = 0;
		_suppressionAimPoint = Vector3.Zero;
		HearingStatus = UsesTacticalBehavior() ? "NONE" : "OFF";
		HearingBearing = "NONE";
		HearingAgeSeconds = -1f;
		SearchStatus = UsesTacticalBehavior() ? "READY" : "OFF";
		FlankStatus = UsesTacticalBehavior() ? "READY" : "OFF";
		SuppressionStatus = UsesTacticalBehavior() ? "NONE" : "OFF";

		TacticalStatus = UsesTacticalBehavior() ? "READY" : "OFF";
		ThreatStatus = UsesTacticalBehavior() ? "NONE" : "OFF";
		ThreatBearing = "NONE";
		ThreatAgeSeconds = -1f;
		CoverStatus = "NONE";
		TacticalAggression = 0.50f;
		TacticalContextStatus = UsesTacticalBehavior() ? "BALANCED" : "OFF";
		ModifierStatus = UsesTacticalBehavior() ? "STANDARD · BASELINE" : "OFF";
		_nextDynamicVariationAt = 0f;
		_highNoonFireAt = -1f;
		_lastHighNoonStage = HighNoonStage.Inactive;
		UpdateAdaptationDiagnostics();
	}

	// =========================================================
	// SHARED NAVIGATION CONSUMER
	// =========================================================

	private bool CanUseNavigation()
	{
		if (
			Scene is null ||
			Scene.NavMesh is null ||
			!Scene.NavMesh.IsEnabled
		)
		{
			StopNavigation(
				"WAITING FOR NAVMESH",
				"DISABLED"
			);
			return false;
		}

		if ( Scene.NavMesh.IsGenerating ||
			( _navigationManager?.IsValid == true && !_navigationManager.NavigationReady ) )
		{
			StopNavigation(
				"WAITING FOR NAVMESH",
				"GENERATING"
			);
			return false;
		}

		if (
			_playerState?.IsValid != true ||
			_playerState.IsAlive != true ||
			_movementInput?.IsValid != true ||
			_controller?.IsValid != true
		)
		{
			StopNavigation(
				"WAITING FOR PLAYER STATE",
				"NOT READY"
			);
			return false;
		}

		return true;
	}

	private void NavigateToWorldPosition(
		Vector3 targetPosition,
		string targetName,
		float stopDistance,
		string movingIntent,
		bool allowSprint = true,
		bool faceMovement = true,
		bool advancedMovement = false,
		OneMoreRoundWeapon movementWeapon = null,
		bool visibleCombatTarget = false
	)
	{
		Vector3 toTarget =
			( targetPosition - WorldPosition )
				.WithZ( 0f );

		float targetDistance =
			toTarget.Length;

		SetLocomotionMode( ResolveLocomotionMode( movingIntent, visibleCombatTarget ) );

		UpdateNavigationDiagnostics(
			targetDistance,
			targetName
		);

		if ( targetDistance <= stopDistance )
		{
			_pathPoints.Clear();
			_pathPointIndex = 0;
			StopMovementOnly();
			CurrentIntent = movingIntent.Contains( "VISIBLE" )
				? "HOLDING VISIBLE TARGET"
				: "HOLDING NEAR TARGET";
			NavigationStatus = "ARRIVED";
			return;
		}

		if ( !TryProjectNavigationEndpoints( targetPosition ) )
		{
			_pathPoints.Clear();
			_pathPointIndex = 0;
			StopMovementOnly();
			CurrentIntent = "ENDPOINT OFF NAVMESH";
			NavigationStatus = "NO START POINT";
			return;
		}

		Vector3 previousSteeringPoint =
			_pathPointIndex >= 0 && _pathPointIndex < _pathPoints.Count
				? _pathPoints[_pathPointIndex]
				: _previousPathSteeringPoint;

		if ( Time.Now >= _nextRepathAt && Time.Now >= _nextMovementPathAt )
		{
			_nextRepathAt =
				Time.Now + MathF.Max( 0.05f, RepathInterval );

			_nextMovementPathAt = Time.Now + 0.15f;
			NavMeshPath calculatedPath = CalculateCountedBotPath( _navigationStartOnMesh, _navigationTargetOnMesh );
			List<Vector3> refreshedPoints = _refreshedPathPoints;
			refreshedPoints.Clear();

			if (
				calculatedPath.IsValid &&
				calculatedPath.Status == NavMeshPathStatus.Complete &&
				calculatedPath.Points is not null
			)
			{
				foreach ( NavMeshPathPoint point in calculatedPath.Points )
					refreshedPoints.Add( point.Position );
			}

			if ( refreshedPoints.Count > 0 )
			{
				int continuityIndex = FluidMovementEnabled
					? ChoosePathContinuityIndex( refreshedPoints, previousSteeringPoint )
					: 0;

				_pathPoints.Clear();
				_pathPoints.AddRange( refreshedPoints );
				_pathPointIndex = Math.Clamp( continuityIndex, 0, _pathPoints.Count - 1 );
				_pathStatus =
					calculatedPath.Status
						.ToString()
						.ToUpperInvariant();
				_lastSuccessfulPathAt = Time.Now;
			}
			else
			{
				// BOT 6 continuity: a single transient failed repath must not zero the
				// movement command and make ROOK look as if it stopped to think. Keep the
				// last usable route for a short grace period while requesting another.
				bool canUseGracePath =
					_pathPoints.Count > 0 &&
					Time.Now - _lastSuccessfulPathAt <= MathF.Max( 0.15f, RepathFailureGrace );

				if ( canUseGracePath )
				{
					_pathStatus = "REPATH GRACE";
					_nextRepathAt = MathF.Min( _nextRepathAt, Time.Now + 0.10f );
				}
				else
				{
					_pathPoints.Clear();
					_pathPointIndex = 0;
					_pathStatus = calculatedPath.IsValid
						? $"NO PATH / {calculatedPath.Status.ToString().ToUpperInvariant()}"
						: "NO PATH";
					_nextRepathAt = Time.Now + MathF.Max( 0.25f, FailedPathRetryDelay );
				}
			}
		}

		NavigationStatus = _pathStatus;

		if ( _pathPoints.Count == 0 )
		{
			StopMovementOnly();
			CurrentIntent = "NO NAVIGATION PATH";
			return;
		}

		AdvancePastReachedPathPoints();

		if ( _pathPointIndex >= _pathPoints.Count )
		{
			StopMovementOnly();
			CurrentIntent = "PATH COMPLETE / HOLD";
			NavigationStatus = "ARRIVED";
			return;
		}

		Vector3 steeringPoint =
			_pathPoints[_pathPointIndex];
		_previousPathSteeringPoint = steeringPoint;

		Vector3 moveDirection = FluidMovementEnabled
			? GetFluidNavigationDirection( steeringPoint )
			: ( steeringPoint - WorldPosition ).WithZ( 0f );

		if ( moveDirection.IsNearlyZero( 0.01f ) )
		{
			_pathPointIndex++;

			if ( _pathPointIndex < _pathPoints.Count )
			{
				steeringPoint = _pathPoints[_pathPointIndex];
				_previousPathSteeringPoint = steeringPoint;
				moveDirection = FluidMovementEnabled
					? GetFluidNavigationDirection( steeringPoint )
					: ( steeringPoint - WorldPosition ).WithZ( 0f );
			}
		}

		if ( moveDirection.IsNearlyZero( 0.01f ) )
		{
			StopMovementOnly();
			CurrentIntent = "PATH COMPLETE / HOLD";
			NavigationStatus = "ARRIVED";
			return;
		}

		if (
			advancedMovement &&
			UsesTacticalBehavior() &&
			DetectTraversalNoProgress( steeringPoint )
		)
		{
			_pathPoints.Clear();
			_pathPointIndex = 0;
			_nextRepathAt = 0f;
			StopMovementOnly();
			NavigationStatus = "STUCK / REPATH";
			CurrentIntent = $"{movingIntent} / STUCK REPATH";
			return;
		}

		bool sprint =
			allowSprint &&
			targetDistance >= SprintDistance;

		if ( sprint && ShouldSlowForUpcomingCorner() )
			sprint = false;

		bool crouchDown = false;
		bool jumpPressed = false;
		_traversalFrameStatus = string.Empty;

		if ( advancedMovement && UsesTacticalBehavior() )
		{
			moveDirection =
				ApplyTraversalAwareness(
					moveDirection,
					ref sprint,
					ref jumpPressed
				);

			moveDirection =
				ApplyTraversalOrbitGuard(
					steeringPoint,
					moveDirection,
					ref sprint
				);

			if ( moveDirection.IsNearlyZero( 0.01f ) )
			{
				StopMovementOnly();
				CurrentIntent = $"{movingIntent} / LOCAL BLOCKED";
				NavigationStatus = "LOCAL BLOCKED";
				return;
			}
		}

		if ( faceMovement ) FaceMovementDirection( moveDirection );
		Rotation movementBasis = Rotation.FromYaw( _controller.EyeAngles.yaw );
		Vector3 moveInput = ( movementBasis.Inverse * moveDirection.Normal ).WithZ( 0f ).ClampLength( 1f );
		if ( visibleCombatTarget || HasCombatFacingEvidence() ) sprint = false;

		if ( advancedMovement )
		{
			ApplyAdvancedTraversalActions(
				movementWeapon,
				targetDistance,
				visibleCombatTarget,
				ref sprint,
				ref crouchDown,
				ref jumpPressed
			);
		}

		if ( visibleCombatTarget || HasCombatFacingEvidence() ) sprint = false;
		_movementInput.SetBotInput(
			moveInput,
			sprintDown: sprint,
			crouchDown: crouchDown,
			jumpPressed: jumpPressed
		);

		if ( advancedMovement )
		{
			if ( !string.IsNullOrWhiteSpace( _traversalFrameStatus ) )
			{
				SetMovementDiagnostics( _traversalFrameStatus );
				CurrentIntent = $"{movingIntent} / {_traversalFrameStatus}";
			}
			else if ( _slide?.IsSliding == true )
			{
				SetMovementDiagnostics( "SLIDE" );
				CurrentIntent = $"{movingIntent} / SLIDE";
			}
			else if ( jumpPressed )
			{
				SetMovementDiagnostics( _controller.IsAirborne ? "AIR JUMP REQUEST" : "JUMP REQUEST" );
				CurrentIntent = $"{movingIntent} / JUMP";
			}
			else if ( sprint )
			{
				SetMovementDiagnostics( "SPRINT" );
				CurrentIntent = $"{movingIntent} / SPRINT";
			}
			else
			{
				SetMovementDiagnostics( "MOVE" );
				CurrentIntent = $"{movingIntent} / MOVE";
			}
		}
		else
		{
			CurrentIntent = sprint
				? $"{movingIntent} / SPRINT"
				: $"{movingIntent} / MOVE";
		}
	}

	private Vector3 ApplyTraversalAwareness(
		Vector3 desiredWorldDirection,
		ref bool sprint,
		ref bool jumpPressed
	)
	{
		if (
			_controller?.IsValid != true ||
			Scene is null ||
			desiredWorldDirection.IsNearlyZero( 0.01f )
		)
			return desiredWorldDirection;

		Vector3 forward =
			desiredWorldDirection.WithZ( 0f ).Normal;

		if (
			Time.Now < _traversalRecoveryUntil &&
			!_traversalRecoveryDirection.IsNearlyZero( 0.01f )
		)
		{
			sprint = false;
			_traversalFrameStatus = "ORBIT ESCAPE";
			return _traversalRecoveryDirection * MathF.Max( desiredWorldDirection.Length, 1f );
		}

		if (
			Time.Now < _traversalBypassUntil &&
			!_traversalBypassDirection.IsNearlyZero( 0.01f )
		)
		{
			sprint = false;
			_traversalFrameStatus = "LOCAL BYPASS";
			return _traversalBypassDirection * MathF.Max( desiredWorldDirection.Length, 1f );
		}

		if ( !_controller.IsOnGround )
			return desiredWorldDirection;

		bool lowBlocked =
			IsTraversalRayBlocked( forward, TraversalLowProbeHeight );
		bool highBlocked =
			IsTraversalRayBlocked( forward, TraversalHighProbeHeight );

		if ( !lowBlocked )
			return desiredWorldDirection;

		// A low obstacle with headroom is a legitimate jump request. The real
		// PlayerLocomotion/PlayerController pipeline still decides whether the jump
		// is physically legal, so this never grants bot-only traversal powers.
		if (
			!highBlocked &&
			Time.Now >= _nextTraversalJumpAt
		)
		{
			jumpPressed = true;
			_nextTraversalJumpAt =
				Time.Now + MathF.Max( 0.65f, TraversalJumpCooldown );
			_traversalFrameStatus = "TRAVERSAL JUMP";
			return desiredWorldDirection;
		}

		// If both low and high probes hit, this is a wall/ramp side rather than a
		// jumpable lip. Try a short local bypass and force a fresh nav query instead
		// of repeatedly jumping into the same geometry.
		Vector3 bypass =
			ChooseTraversalEscapeDirection(
				forward,
				_pathPointIndex < _pathPoints.Count
					? _pathPoints[_pathPointIndex]
					: WorldPosition + forward * 96f,
				out string side
			);

		sprint = false;

		if ( bypass.IsNearlyZero( 0.01f ) )
		{
			_nextRepathAt = 0f;
			_traversalFrameStatus = "TRAVERSAL BLOCKED";
			return Vector3.Zero;
		}

		_traversalPreferredBypassSign = side == "RIGHT" ? 1 : -1;
		_traversalBypassDirection =
			( forward * 0.18f + bypass * 0.99f )
				.WithZ( 0f )
				.Normal;
		_traversalBypassUntil =
			Time.Now + MathF.Max( 0.35f, TraversalBypassDuration );

		// Do not let the regular repath timer immediately fight the committed local
		// bypass. This was the source of the ramp-side orbit seen in 5A.1.
		_nextRepathAt = MathF.Max( _nextRepathAt, _traversalBypassUntil );
		_traversalFrameStatus = $"BYPASS {side}";

		return _traversalBypassDirection * MathF.Max( desiredWorldDirection.Length, 1f );
	}

	private Vector3 ApplyTraversalOrbitGuard(
		Vector3 steeringPoint,
		Vector3 desiredWorldDirection,
		ref bool sprint
	)
	{
		if ( desiredWorldDirection.IsNearlyZero( 0.01f ) )
			return desiredWorldDirection;

		if (
			Time.Now < _traversalRecoveryUntil &&
			!_traversalRecoveryDirection.IsNearlyZero( 0.01f )
		)
		{
			sprint = false;
			_traversalFrameStatus = "ORBIT ESCAPE";
			return _traversalRecoveryDirection * MathF.Max( desiredWorldDirection.Length, 1f );
		}

		Vector3 flatDirection = desiredWorldDirection.WithZ( 0f ).Normal;
		float distance = ( steeringPoint - WorldPosition ).WithZ( 0f ).Length;
		float targetShift = ( steeringPoint - _traversalOrbitTarget ).WithZ( 0f ).Length;

		if (
			_traversalOrbitWindowStartedAt < 0f ||
			targetShift > 48f ||
			_traversalOrbitLastPosition.IsNearlyZero( 0.01f )
		)
		{
			ResetTraversalOrbitWindow( steeringPoint, flatDirection, distance );
			return desiredWorldDirection;
		}

		float frameTravel =
			( WorldPosition - _traversalOrbitLastPosition )
				.WithZ( 0f )
				.Length;

		if ( frameTravel > 96f )
		{
			ResetTraversalOrbitWindow( steeringPoint, flatDirection, distance );
			return desiredWorldDirection;
		}

		_traversalOrbitTravelDistance += frameTravel;
		_traversalOrbitLastPosition = WorldPosition;

		if ( !_traversalOrbitPreviousDirection.IsNearlyZero( 0.01f ) )
		{
			float dot = Math.Clamp(
				Vector3.Dot( _traversalOrbitPreviousDirection, flatDirection ),
				-1f,
				1f
			);
			float crossZ =
				_traversalOrbitPreviousDirection.x * flatDirection.y -
				_traversalOrbitPreviousDirection.y * flatDirection.x;
			float turn =
				MathF.Abs( MathF.Atan2( crossZ, dot ) * ( 180f / MathF.PI ) );
			_traversalOrbitTurnDegrees += turn;
		}

		_traversalOrbitPreviousDirection = flatDirection;

		float elapsed = Time.Now - _traversalOrbitWindowStartedAt;
		float improvement = _traversalOrbitStartDistance - distance;
		float netDisplacement =
			( WorldPosition - _traversalOrbitStartPosition )
				.WithZ( 0f )
				.Length;

		if (
			elapsed >= MathF.Max( 0.40f, TraversalOrbitWindow ) &&
			_traversalOrbitTravelDistance >= MathF.Max( 48f, TraversalOrbitMinimumTravel ) &&
			improvement < MathF.Max( 18f, TraversalMinimumProgress * 1.35f ) &&
			(
				_traversalOrbitTurnDegrees >= MathF.Max( 120f, TraversalOrbitTurnThreshold ) ||
				( _traversalOrbitTravelDistance >= 125f && netDisplacement <= 58f )
			)
		)
		{
			Vector3 escape =
				ChooseTraversalEscapeDirection(
					flatDirection,
					steeringPoint,
					out string side
				);

			if ( escape.IsNearlyZero( 0.01f ) )
			{
				escape = -flatDirection;
				side = "BACK";
			}

			_traversalPreferredBypassSign *= -1;
			_traversalBypassUntil = -1f;
			_traversalBypassDirection = Vector3.Zero;
			_traversalRecoveryDirection = escape.WithZ( 0f ).Normal;
			_traversalRecoveryUntil =
				Time.Now + MathF.Max( 0.35f, TraversalRecoveryDuration );
			_nextRepathAt = MathF.Max( _nextRepathAt, _traversalRecoveryUntil );
			sprint = false;
			_traversalFrameStatus = $"ORBIT ESCAPE {side}";

			ResetTraversalOrbitWindow( steeringPoint, _traversalRecoveryDirection, distance );
			return _traversalRecoveryDirection * MathF.Max( desiredWorldDirection.Length, 1f );
		}

		if ( improvement >= MathF.Max( 24f, TraversalMinimumProgress * 1.65f ) )
		{
			ResetTraversalOrbitWindow( steeringPoint, flatDirection, distance );
		}
		else if ( elapsed >= MathF.Max( 0.80f, TraversalOrbitWindow * 1.5f ) )
		{
			ResetTraversalOrbitWindow( steeringPoint, flatDirection, distance );
		}

		return desiredWorldDirection;
	}

	private Vector3 ChooseTraversalEscapeDirection(
		Vector3 desiredDirection,
		Vector3 steeringPoint,
		out string sideLabel
	)
	{
		sideLabel = string.Empty;

		if ( desiredDirection.IsNearlyZero( 0.01f ) )
			return Vector3.Zero;

		Vector3 forward = desiredDirection.WithZ( 0f ).Normal;
		float[] angles = _traversalPreferredBypassSign >= 0
			? new[] { 48f, 74f, 102f, 132f, -48f, -74f, -102f, -132f, 180f }
			: new[] { -48f, -74f, -102f, -132f, 48f, 74f, 102f, 132f, 180f };

		float currentDistance = ( steeringPoint - WorldPosition ).WithZ( 0f ).Length;
		float bestScore = float.MinValue;
		Vector3 bestDirection = Vector3.Zero;
		string bestLabel = string.Empty;

		foreach ( float angle in angles )
		{
			Vector3 candidate =
				( Rotation.FromYaw( angle ) * forward )
					.WithZ( 0f )
					.Normal;

			if ( !IsTraversalDirectionClear( candidate ) )
				continue;

			Vector3 probePosition =
				WorldPosition + candidate * MathF.Max( 56f, TraversalProbeDistance * 1.45f );
			Vector3? navPoint = Scene.NavMesh.GetClosestPoint( probePosition, 72f );
			if ( navPoint is null )
				continue;

			Vector3 actualDirection =
				( navPoint.Value - WorldPosition )
					.WithZ( 0f );
			if ( actualDirection.IsNearlyZero( 0.01f ) )
				continue;

			actualDirection = actualDirection.Normal;
			float candidateDistance =
				( steeringPoint - navPoint.Value )
					.WithZ( 0f )
					.Length;
			float progress = currentDistance - candidateDistance;
			float alignment = Vector3.Dot( forward, actualDirection );
			float lateral = 1f - MathF.Abs( alignment );

			float score =
				progress * 2.4f +
				alignment * 28f +
				lateral * 16f;

			if ( MathF.Abs( angle ) >= 170f )
				score -= 32f;

			if ( score <= bestScore )
				continue;

			bestScore = score;
			bestDirection = actualDirection;
			bestLabel = angle > 8f ? "RIGHT" : angle < -8f ? "LEFT" : "BACK";
		}

		sideLabel = bestLabel;
		return bestDirection;
	}

	private void ResetTraversalOrbitWindow()
	{
		_traversalOrbitWindowStartedAt = -1f;
		_traversalOrbitStartPosition = Vector3.Zero;
		_traversalOrbitTarget = Vector3.Zero;
		_traversalOrbitLastPosition = Vector3.Zero;
		_traversalOrbitPreviousDirection = Vector3.Zero;
		_traversalOrbitStartDistance = float.MaxValue;
		_traversalOrbitTravelDistance = 0f;
		_traversalOrbitTurnDegrees = 0f;
	}

	private void ResetTraversalOrbitWindow(
		Vector3 steeringPoint,
		Vector3 direction,
		float distance
	)
	{
		_traversalOrbitWindowStartedAt = Time.Now;
		_traversalOrbitStartPosition = WorldPosition;
		_traversalOrbitTarget = steeringPoint;
		_traversalOrbitLastPosition = WorldPosition;
		_traversalOrbitPreviousDirection = direction.WithZ( 0f ).Normal;
		_traversalOrbitStartDistance = distance;
		_traversalOrbitTravelDistance = 0f;
		_traversalOrbitTurnDegrees = 0f;
	}

	private bool DetectTraversalNoProgress( Vector3 steeringPoint )
	{
		float distance = ( steeringPoint - WorldPosition ).WithZ( 0f ).Length;
		float targetShift = ( steeringPoint - _traversalProgressTarget ).WithZ( 0f ).Length;

		if (
			_traversalProgressStartedAt < 0f ||
			targetShift > 48f ||
			float.IsNaN( _traversalBestDistance ) || float.IsInfinity( _traversalBestDistance )
		)
		{
			_traversalProgressStartedAt = Time.Now;
			_traversalBestDistance = distance;
			_traversalProgressTarget = steeringPoint;
			return false;
		}

		float requiredProgress = MathF.Max( 4f, TraversalMinimumProgress );
		if ( distance <= _traversalBestDistance - requiredProgress )
		{
			_traversalBestDistance = distance;
			_traversalProgressStartedAt = Time.Now;
			return false;
		}

		if ( Time.Now - _traversalProgressStartedAt < MathF.Max( 0.45f, TraversalNoProgressTimeout ) )
			return false;

		// The bot has been moving without getting meaningfully closer to the current
		// path corner. Break the local orbit, alternate bypass side and request a new
		// path on the next frame.
		_traversalProgressStartedAt = Time.Now;
		_traversalBestDistance = distance;
		_traversalPreferredBypassSign *= -1;
		_traversalBypassUntil = -1f;
		_traversalBypassDirection = Vector3.Zero;
		_traversalFrameStatus = "STUCK / REPATH";
		return true;
	}

	private bool IsTraversalDirectionClear( Vector3 direction )
	{
		if ( direction.IsNearlyZero( 0.01f ) )
			return false;

		return
			!IsTraversalRayBlocked( direction, TraversalLowProbeHeight ) &&
			!IsTraversalRayBlocked( direction, TraversalHighProbeHeight );
	}

	private bool IsTraversalRayBlocked(
		Vector3 direction,
		float height
	)
	{
		if ( Scene is null || direction.IsNearlyZero( 0.01f ) )
			return false;

		Vector3 planar = direction.WithZ( 0f ).Normal;
		var probeKey = ( (int)MathF.Round( planar.x * 20f ), (int)MathF.Round( planar.y * 20f ), (int)MathF.Round( height ) );
		if ( _traversalProbeCache.TryGetValue( probeKey, out TraversalProbeSample cachedProbe ) &&
			Time.Now <= cachedProbe.ExpiresAt && ( WorldPosition - cachedProbe.Origin ).Length <= 12f &&
			planar.Dot( cachedProbe.Direction ) >= 0.999f ) return cachedProbe.Blocked;
		if ( _traversalProbeCache.Count > 64 ) _traversalProbeCache.Clear();
		Vector3 start = WorldPosition + Vector3.Up * MathF.Max( 4f, height );
		Vector3 end =
			start +
			direction.WithZ( 0f ).Normal * MathF.Max( 24f, TraversalProbeDistance );

		SceneTrace traceBuilder =
			Scene
				.Trace
				.Ray( start, end )
				.IgnoreGameObjectHierarchy( GameObject )
				.WithoutTags( "trigger" )
				.UseHitboxes( false );

		if ( _perceptionTarget?.GameObject is not null )
		{
			traceBuilder =
				traceBuilder.IgnoreGameObjectHierarchy( _perceptionTarget.GameObject );
		}

		_traversalProbes++;
		bool blocked = traceBuilder.Run().Hit;
		_traversalProbeCache[probeKey] = new TraversalProbeSample( WorldPosition, planar, blocked );
		return blocked;
	}

	private void AdvancePastReachedPathPoints()
	{
		if ( _pathPoints.Count == 0 )
			return;

		float reachDistance =
			Math.Clamp( LookAheadDistance * 0.42f, 24f, 42f );

		while ( _pathPointIndex < _pathPoints.Count )
		{
			Vector3 delta =
				( _pathPoints[_pathPointIndex] - WorldPosition )
					.WithZ( 0f );

			if ( delta.Length > reachDistance )
				break;

			_pathPointIndex++;
		}
	}

	private PlayerState ResolveHumanTarget(
		PlayerState cached
	)
	{
		if (
			cached is not null &&
			cached.IsValid &&
			!cached.IsBot &&
			cached.IsAlive
		)
		{
			return cached;
		}

		return Scene?
			.GetAllComponents<PlayerState>()
			.FirstOrDefault(
				x =>
					x is not null &&
					x.IsValid &&
					!x.IsBot &&
					x.IsAlive
			);
	}

	private void FaceMovementDirection( Vector3 moveDirection )
	{
		if ( _controller?.IsValid != true || moveDirection.IsNearlyZero( 0.001f ) ) return;
		LookTowardWorldPoint( _controller.EyePosition + moveDirection.Normal * 180f, 8f );
	}

	private void StopNavigation(
		string intent,
		string navigationStatus
	)
	{
		_pathPoints.Clear();
		_pathPointIndex = 0;
		_pathStatus = navigationStatus;
		_fluidSteeringDirection = Vector3.Zero;
		_previousPathSteeringPoint = Vector3.Zero;
		SetLocomotionMode( OMRBotLocomotionMode.Idle );
		StopMovementOnly();

		CurrentIntent = intent;
		NavigationStatus = navigationStatus;
		NavigationTargetName = "NONE";
		NavigationTargetDistance = 0f;
	}

	private void StopMovementOnly()
	{
		if ( UsesAdvancedMovement() )
			UpdateScheduledCrouchRelease();

		_movementInput?.SetBotInput(
			Vector3.Zero,
			sprintDown: false,
			crouchDown: GetBotCrouchButtonDown(),
			jumpPressed: false
		);

		if ( UsesAdvancedMovement() )
			SetMovementDiagnostics( _controller?.IsDucking == true ? "CROUCH HOLD" : "HOLD" );
	}

	private void UpdateNavigationDiagnostics(
		float distance,
		string targetName
	)
	{
		if ( Time.Now < _nextDiagnosticAt )
			return;

		_nextDiagnosticAt =
			Time.Now + 0.10f;

		NavigationTargetDistance =
			MathF.Round( distance );

		NavigationTargetName =
			string.IsNullOrWhiteSpace( targetName )
				? "PLAYER"
				: targetName;
	}

	private void ResetRuntimeBehaviorState()
	{
		_nextRepathAt = 0f;
		_pathPoints.Clear();
		_pathPointIndex = 0;
		_pathStatus =
			BehaviorMode == OMRBotBehaviorMode.Stationary
				? "OFF"
				: "NO PATH";
		ResetFluidMovementState();
		ResetCombatHumanization();
		ResetCombatContinuity();
		ResetPerformanceCaches();

		_navigationTarget = null;
		_perceptionTarget = null;
		_nextPerceptionScanAt = 0f;
		_rawVisibleSince = -1f;
		_lastConfirmedSeenAt = -999f;
		_hasConfirmedSight = false;
		_observedTargetPosition = Vector3.Zero;
		_observedTargetAimPoint = Vector3.Zero;
		HasLastKnownPosition = false;
		LastKnownPosition = Vector3.Zero;
		_nextSearchTurnAt = 0f;
		_searchTurnDirection = 1f;
		_nextBotTriggerAt = 0f;
		_nextStrafeSwitchAt = Time.Now + 0.65f;
		_strafeDirection = BotSlot % 2 == 0 ? 1f : -1f;
		_nextSlideAt = Time.Now + 1.35f;
		_nextJumpAt = Time.Now + 2.1f;
		_airJumpAttemptPending = false;
		_airJumpAttemptAt = 0f;
		_nextCrouchDodgeAt = Time.Now + 1.6f;
		_crouchDodgeEndAt = -1f;
		_crouchButtonHeldUntil = -1f;
		_wasSliding = false;
		MovementStatus =
			UsesAdvancedMovement()
				? "READY"
				: "OFF";
		MovementSpeed = 0f;
		SafeReleaseLastCombatWeapon();
		ResetCombatDiagnostics(
			BehaviorMode == OMRBotBehaviorMode.Combat ||
			UsesAdvancedMovement()
				? "NO CONTACT"
				: "OFF"
		);
		ResetPerceptionDiagnostics(
			BehaviorMode == OMRBotBehaviorMode.PerceptionSearch ||
			BehaviorMode == OMRBotBehaviorMode.Combat ||
			UsesAdvancedMovement()
				? "NO CONTACT"
				: "OFF"
		);

		ResetTacticalState();
		ResetBrainArchitecture();
		ResetTacticalMapState();
		ResetUtilityBrainState();
		ResetOpponentBelief();
		ResetPlayerPrediction( clearStyle: true );
	}

	private void ResetPerceptionDiagnostics(
		string status
	)
	{
		PerceptionStatus = status;
		PerceptionTargetName = "NONE";
		PerceptionTargetDistance = 0f;
		PerceptionLastSeenSeconds = -1f;
		PerceptionReactionRemaining = 0f;
	}

	private void SuppressHumanControl()
	{
		if ( _controller?.IsValid == true )
		{
			_controller.UseInputControls = false;
			_controller.UseLookControls = false;
			_controller.UseCameraControls = false;
		}

		if ( _movementInput?.IsValid == true )
		{
			_movementInput.SetBotDriven( true );
		}
	}
}