using UnityEngine; public class AoERayHitLocationSnapshotController : MonoBehaviour { public Transform aoeRayHitLocationSnapshot; public LayerMask movementMask; [Header("Gamepad Settings")] [SerializeField] private float defaultTargetDistance = 5f; [SerializeField] private float minDistance = 2f; [SerializeField] private float maxDistance = 10f; [SerializeField] private float distanceAdjustSpeed = 5f; [SerializeField] private float gamepadDeadzone = 0.2f; protected Ray ray; protected RaycastHit hit; protected Vector3 targetPoint = Vector3.zero; protected bool isCasting; protected bool isUsingGamepad; protected float currentTargetDistance; protected Vector3 lastValidAimDirection; protected virtual void Awake() { aoeRayHitLocationSnapshot.parent = null; currentTargetDistance = defaultTargetDistance; lastValidAimDirection = transform.forward; } private void OnEnable() { if (CastBarHandler.Instance != null) { CastBarHandler.Instance.OnCastingStateChanged.AddListener(UpdateIsCastingState); } } private void OnDisable() { if (CastBarHandler.Instance != null) { CastBarHandler.Instance.OnCastingStateChanged.RemoveListener(UpdateIsCastingState); } } protected virtual void Start() { } protected virtual void Update() { if (Camera.main == null) return; if (isCasting) return; DetectInputMethod(); if (isUsingGamepad) { HandleGamepadAiming(); } else { HandleMouseAiming(); } } private void DetectInputMethod() { Vector2 gamepadLook = new Vector2( Input.GetAxisRaw(GameConstants.Input.AimHorizontalAxis), Input.GetAxisRaw(GameConstants.Input.AimVerticalAxis) ); float rightTrigger = Input.GetAxisRaw("RightTrigger"); float leftTrigger = Input.GetAxisRaw("LeftTrigger"); bool triggerInput = Mathf.Abs(rightTrigger) > gamepadDeadzone || Mathf.Abs(leftTrigger) > gamepadDeadzone; if (gamepadLook.magnitude > gamepadDeadzone || triggerInput) { isUsingGamepad = true; } else if (Input.GetAxisRaw("Mouse X") != 0 || Input.GetAxisRaw("Mouse Y") != 0) { isUsingGamepad = false; } } private void HandleGamepadAiming() { // Get aim direction from right stick Vector2 aimInput = new Vector2( Input.GetAxisRaw(GameConstants.Input.AimHorizontalAxis), Input.GetAxisRaw(GameConstants.Input.AimVerticalAxis) ); // Update target distance based on both triggers float rightTrigger = Input.GetAxisRaw("RightTrigger"); float leftTrigger = Input.GetAxisRaw("LeftTrigger"); // Right trigger increases distance, left trigger decreases float distanceChange = (rightTrigger - leftTrigger) * distanceAdjustSpeed * Time.deltaTime; currentTargetDistance += distanceChange; currentTargetDistance = Mathf.Clamp(currentTargetDistance, minDistance, maxDistance); // Calculate target position Vector3 aimDirection; if (aimInput.magnitude > gamepadDeadzone) { Vector3 cameraForward = Camera.main.transform.forward; Vector3 cameraRight = Camera.main.transform.right; cameraForward.y = 0f; cameraRight.y = 0f; cameraForward.Normalize(); cameraRight.Normalize(); aimDirection = (cameraForward * aimInput.y + cameraRight * aimInput.x).normalized; lastValidAimDirection = aimDirection; } else { aimDirection = lastValidAimDirection; } // Calculate target position with ground detection Vector3 targetPosition = transform.position + aimDirection * currentTargetDistance; ray = new Ray(targetPosition + Vector3.up * 10f, Vector3.down); if (Physics.Raycast(ray, out hit, 20f, movementMask)) { aoeRayHitLocationSnapshot.position = hit.point; } else { // Fallback if no ground is hit targetPosition.y = transform.position.y; aoeRayHitLocationSnapshot.position = targetPosition; } } private void HandleMouseAiming() { ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit, 100f, movementMask)) { aoeRayHitLocationSnapshot.position = hit.point; } } private void UpdateIsCastingState(bool isCasting) { this.isCasting = isCasting; if (isCasting) { if (isUsingGamepad) { // Store the current AOE position for the cast Vector3 currentPos = aoeRayHitLocationSnapshot.position; currentPos.y = transform.position.y; targetPoint = currentPos; } else { ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit, 100f, movementMask)) { targetPoint = hit.point; } } } } private void OnDrawGizmosSelected() { if (!Application.isPlaying) return; // Draw the current target distance Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(transform.position, currentTargetDistance); // Draw the min/max range Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, minDistance); Gizmos.DrawWireSphere(transform.position, maxDistance); } }