# Hostile NPC Behavior ## Authority and update order Hostile NPC behavior is simulated by `LocationGameState` and `CharacterState`. Rendering objects do not select targets and do not change NPC combat state. During each authoritative simulation tick: 1. The location gathers the enabled players and NPCs visible to the simulation. 2. Each hostile NPC selects or retains a player target. 3. Every character advances using the same tick-start observations. 4. Movement reservations and attack damage are resolved deterministically. 5. Navigation recovery events are applied by `InternalGameServer`. The resulting state and recovery decisions are replicated through the existing WebSocket lockstep stream. NPC target changes are simulation consequences, not client commands. ## Eligible players and nearest selection An eligible target must: - exist in the campaign player map; - be enabled; - have positive health; and - be within the NPC's `visibleRange` when a new target is selected. Distance is measured in the X/Z plane. If two players are equally close, their stable player IDs are compared lexicographically. This gives every lockstep replica the same result regardless of hash-map iteration order. ## Ordinary target locking Once a hostile NPC has a valid target, it keeps that target during ordinary ticks. The target remains locked even if it moves outside `visibleRange`. The lock ends when the player dies or becomes disabled. When a lock ends, the NPC selects the nearest eligible player in range. If no player qualifies, it clears the attack target, leaves combat state, and requests a route to its `homePosition`. ## Movement blockage and target reconsideration NPC movement uses a retry schedule after a character blocks its path. The blocked NPC first stops and waits for its deterministic navigation retry cooldown. When the retry event emits `forceNavigationReplan`, the authoritative location state performs a fresh target selection across all eligible players. This blocked-replan selection differs from ordinary target locking: - the current target is not privileged; - the nearest eligible player may remain the target; - a nearer eligible player replaces the current target; - the route is rebuilt from the NPC's current position toward the selected player's current position. If no eligible player is in range during blocked recovery, the NPC clears its stale chase target and returns toward its home position instead. The blocker is still passed to path planning so the immediate replan does not route through the character that caused the recovery event. ## Death, disconnect, and attack safety Dead or disabled players are excluded from target acquisition. A target that dies or disconnects is therefore invalidated on the next authoritative selection pass, and the NPC either switches to another player or returns home. Attack impacts are also validated at application time. Damage is ignored if the recorded target no longer exists, is disabled, or has already reached zero health. This prevents a queued animation impact from damaging a stale target. ## Regression expectations The state and pathfinding tests should preserve these guarantees: - nearest in-range player selection is deterministic; - a valid ordinary lock is retained; - blocked NPC recovery can replace the target and rebuild the chase route; - no-target blocked recovery clears combat and routes home; - dead and disabled players cannot be selected or damaged; - retry cooldowns and blocker identity remain deterministic.