using Invector.vCharacterController.AI.FSMBehaviour; using UnityEngine; namespace ArcherEnemy { /// /// Decision checking if player is in optimal shooting range /// Returns true when player is far enough but not too far /// [CreateAssetMenu(menuName = "Invector/FSM/Decisions/Archer/Player In Shoot Range")] public class DEC_PlayerInShootRange : vStateDecision { public override string categoryName => "Archer/Combat"; public override string defaultName => "Player In Shoot Range"; [Header("Range Configuration")] [Tooltip("Minimum safe distance to start shooting")] public float minShootDistance = 8f; [Tooltip("Maximum effective shooting distance")] public float maxShootDistance = 25f; [Tooltip("Also check if we have clear line of sight")] public bool checkLineOfSight = true; [Tooltip("Layers that block line of sight")] public LayerMask obstacleMask = -1; [Header("Debug")] [Tooltip("Enable debug logging")] public bool enableDebug = false; [Tooltip("Show range gizmos")] public bool showGizmos = true; public override bool Decide(vIFSMBehaviourController fsmBehaviour) { Transform target = GetTarget(fsmBehaviour); if (target == null) { if (enableDebug) Debug.Log("[DEC_PlayerInShootRange] No target found"); return false; } Vector3 archerPos = fsmBehaviour.transform.position; Vector3 targetPos = target.position; float distance = Vector3.Distance(archerPos, targetPos); // Check distance range bool inRange = distance >= minShootDistance && distance <= maxShootDistance; if (!inRange) { if (enableDebug) { if (distance < minShootDistance) Debug.Log($"[DEC_PlayerInShootRange] Player too close: {distance:F1}m (min: {minShootDistance})"); else Debug.Log($"[DEC_PlayerInShootRange] Player too far: {distance:F1}m (max: {maxShootDistance})"); } return false; } // Check line of sight if enabled if (checkLineOfSight) { Vector3 shootPoint = archerPos + Vector3.up * 1.5f; // Approximate chest height Vector3 targetPoint = targetPos + Vector3.up * 1f; Vector3 direction = targetPoint - shootPoint; if (Physics.Raycast(shootPoint, direction.normalized, distance, obstacleMask, QueryTriggerInteraction.Ignore)) { if (enableDebug) Debug.Log("[DEC_PlayerInShootRange] Line of sight blocked"); return false; } } if (enableDebug) { Debug.Log($"[DEC_PlayerInShootRange] IN RANGE: {distance:F1}m"); } return true; } private Transform GetTarget(vIFSMBehaviourController fsmBehaviour) { // Try through AI controller var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI; if (aiController != null && aiController.currentTarget != null) return aiController.currentTarget.transform; // Fallback - find player GameObject player = GameObject.FindGameObjectWithTag("Player"); return player?.transform; } #if UNITY_EDITOR private void OnDrawGizmosSelected() { if (!showGizmos) return; // This would need to be drawn from the archer's position in-game // For now, just a visual reference } #endif } }