Files
beyond/Assets/AI/_Archer/DEC_PlayerInShootRange.cs
2025-11-20 14:34:59 +01:00

112 lines
3.1 KiB
C#

using Invector.vCharacterController.AI.FSMBehaviour;
using UnityEngine;
namespace ArcherEnemy
{
/// <summary>
/// Decision checking if player is in optimal shooting range
/// Returns true when player is far enough but not too far
/// </summary>
[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
}
}