112 lines
3.1 KiB
C#
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
|
|
}
|
|
} |