using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; public class PlayerDecisionController : MonoBehaviour { [Header("References")] public LayerMask enemyLayerMask = 1 << 10; // Enemies are on layer 10 public LayerMask playerLayerMask = 1 << 9; // Players are on layer 9 [Header("Settings")] public float enemySnapDistance = 1f; private List playerCharacters = new List(); private Character selectedCharacter; private TargetingLine targetingLine; private Camera mainCamera; private bool isDragging = false; private Vector3 dragStartPosition; private bool isEnabled = true; private List activeActionLines = new List(); void Awake() { mainCamera = Camera.main; targetingLine = GetComponent(); if (targetingLine == null) { targetingLine = gameObject.AddComponent(); } } void Start() { InitializePlayerCharacters(); } void Update() { HandleInput(); } private void InitializePlayerCharacters() { // Get player characters from GameManager if available if (GameManager.Instance != null) { playerCharacters.Clear(); foreach (GameObject playerGO in GameManager.Instance.playerCharacters) { Character character = playerGO.GetComponent(); if (character != null) { playerCharacters.Add(character); } } } else { // Fallback: find all characters (for testing without GameManager) Character[] characters = FindObjectsByType(FindObjectsSortMode.None); playerCharacters.AddRange(characters); } foreach (Character character in playerCharacters) { character.actionData.Reset(); character.SetVisualState(ActionDecisionState.NoAction); } } private void HandleInput() { if (!isEnabled) return; if (Input.GetMouseButtonDown(0)) // Left click { HandleLeftClickDown(); } else if (Input.GetMouseButton(0) && isDragging) // Left drag { HandleLeftDrag(); } else if (Input.GetMouseButtonUp(0)) // Left release { HandleLeftClickUp(); } else if (Input.GetMouseButtonDown(1)) // Right click { HandleRightClick(); } } private void HandleLeftClickDown() { Vector3 mouseWorldPosition = GetMouseWorldPosition(); Character clickedCharacter = GetPlayerCharacterAtPosition(mouseWorldPosition); if (clickedCharacter != null) { selectedCharacter = clickedCharacter; isDragging = true; dragStartPosition = clickedCharacter.transform.position; // Clear any existing action lines before starting new targeting ClearActionLineForCharacter(clickedCharacter); targetingLine.StartTargeting(dragStartPosition); // CinemachineCameraController.Instance.FocusOnCharacter(clickedCharacter.transform); } } private void HandleLeftDrag() { if (selectedCharacter == null) return; Vector3 mouseWorldPos = GetMouseWorldPosition(); GameObject enemyAtMouse = GetEnemyAtPosition(mouseWorldPos); if (enemyAtMouse != null) { // Snap to enemy Vector3 enemyPos = enemyAtMouse.transform.position; targetingLine.UpdateTargeting(dragStartPosition, enemyPos, true); } else { // Follow mouse targetingLine.UpdateTargeting(dragStartPosition, mouseWorldPos, false); } } private void HandleLeftClickUp() { if (!isDragging || selectedCharacter == null) return; Vector3 mouseWorldPos = GetMouseWorldPosition(); GameObject enemyAtMouse = GetEnemyAtPosition(mouseWorldPos); if (enemyAtMouse != null) { // Set attack target selectedCharacter.actionData.SetAttackTarget(enemyAtMouse); // Also update enhanced action data if it exists UpdateEnhancedActionData(selectedCharacter, BattleActionType.Attack, enemyAtMouse, mouseWorldPos); } else { // Set move target selectedCharacter.actionData.SetMoveTarget(mouseWorldPos); // Also update enhanced action data if it exists UpdateEnhancedActionData(selectedCharacter, BattleActionType.Move, null, mouseWorldPos); } selectedCharacter.SetVisualState(selectedCharacter.actionData.state); // Cleanup targetingLine.StopTargeting(); selectedCharacter = null; isDragging = false; } private void HandleRightClick() { if (isDragging && selectedCharacter != null) { // Cancel current action selectedCharacter.actionData.Reset(); selectedCharacter.SetVisualState(ActionDecisionState.NoAction); targetingLine.StopTargeting(); selectedCharacter = null; isDragging = false; } else { // Right click on character to reset their action Vector3 mouseWorldPos = GetMouseWorldPosition(); Character clickedCharacter = GetPlayerCharacterAtPosition(mouseWorldPos); if (clickedCharacter != null) { clickedCharacter.actionData.Reset(); clickedCharacter.SetVisualState(ActionDecisionState.NoAction); } } } private Vector3 GetMouseWorldPosition() { Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition); RaycastHit hit; // Raycast against a ground plane or existing colliders if (Physics.Raycast(ray, out hit, 200f)) { return hit.point; } // Fallback: project onto a horizontal plane at y=0 Plane groundPlane = new Plane(Vector3.up, Vector3.zero); if (groundPlane.Raycast(ray, out float distance)) { return ray.GetPoint(distance); } return Vector3.zero; } private Character GetPlayerCharacterAtPosition(Vector3 worldPosition) { Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, 200f, playerLayerMask)) { return hit.collider.GetComponent(); } // Try raycast without layer mask to see what we're hitting if (Physics.Raycast(ray, out hit, 200f)) { } else { } return null; } private GameObject GetEnemyAtPosition(Vector3 worldPosition) { Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, 200f, enemyLayerMask)) { return hit.collider.gameObject; } return null; } public bool AllCharactersHaveActions() { foreach (var character in playerCharacters) { // Characters need actions if they have no action set if (character.actionData.state == ActionDecisionState.NoAction) return false; } return true; } public void ResetAllCharacterActions() { foreach (var character in playerCharacters) { character.actionData.Reset(); character.SetVisualState(ActionDecisionState.NoAction); } } public void UpdateVisualStates() { foreach (var character in playerCharacters) { // Update visual states based on current action status if (character.actionData.state == ActionDecisionState.NoAction) { character.SetVisualState(ActionDecisionState.NoAction); // Pink } else if (character.HasActionSelected()) { character.SetVisualState(ActionDecisionState.ActionSelected); // Green } } } public void RefreshPlayerCharacters() { InitializePlayerCharacters(); } public void SetEnabled(bool enabled) { isEnabled = enabled; if (!enabled) { if (isDragging) { // Cancel any current dragging operation targetingLine.StopTargeting(); selectedCharacter = null; isDragging = false; } // Don't automatically hide action lines when disabling - let caller decide } } public void ShowActiveActionLines() { HideActiveActionLines(); // Clear any existing lines first foreach (var character in playerCharacters) { if (character.HasActionSelected() && !character.IsActionComplete()) { GameObject lineObject = new GameObject($"ActionLine_{character.name}"); TargetingLine line = lineObject.AddComponent(); activeActionLines.Add(line); Vector3 startPos = character.transform.position + Vector3.up * 0.5f; if (character.actionData.targetEnemy != null) { Vector3 endPos = character.actionData.targetEnemy.transform.position + Vector3.up * 0.5f; line.StartTargeting(startPos); line.UpdateTargeting(startPos, endPos, true); // true for enemy target (red line) } else if (character.actionData.targetPosition != Vector3.zero) { line.StartTargeting(startPos); line.UpdateTargeting(startPos, character.actionData.targetPosition, false); // false for movement (blue line) } } } } public void HideActiveActionLines() { foreach (var line in activeActionLines) { if (line != null) { line.StopTargeting(); Destroy(line.gameObject); } } activeActionLines.Clear(); } public void ClearActionLineForCharacter(Character character) { for (int i = activeActionLines.Count - 1; i >= 0; i--) { var line = activeActionLines[i]; if (line != null && line.gameObject.name == $"ActionLine_{character.name}") { line.StopTargeting(); Destroy(line.gameObject); activeActionLines.RemoveAt(i); break; } } } private void UpdateEnhancedActionData(Character character, BattleActionType actionType, GameObject targetEnemy, Vector3 targetPosition) { // Check if character has enhanced action data var enhancedData = character.GetEnhancedActionData(); if (enhancedData != null) { Debug.Log($"🔄 Updating enhanced action data for {character.CharacterName}: {actionType}"); // Update the enhanced action data to match the targeting result enhancedData.actionType = actionType; enhancedData.state = ActionDecisionState.ActionSelected; if (actionType == BattleActionType.Attack && targetEnemy != null) { enhancedData.targetEnemy = targetEnemy; enhancedData.targetPosition = Vector3.zero; Debug.Log($"đŸ—Ąī¸ Enhanced data updated for attack on {targetEnemy.name}"); } else if (actionType == BattleActionType.Move) { enhancedData.targetPosition = targetPosition; enhancedData.targetEnemy = null; Debug.Log($"👟 Enhanced data updated for move to {targetPosition}"); } } else { Debug.Log($"â„šī¸ No enhanced action data found for {character.CharacterName}"); } } /// /// Manually start targeting mode for a specific character and action type /// Called by the action wheel system /// public void StartTargetingForCharacter(Character character, BattleActionType actionType) { Debug.Log($"đŸŽ¯ StartTargetingForCharacter called: {character.CharacterName} -> {actionType}"); selectedCharacter = character; isDragging = true; dragStartPosition = character.transform.position; // Store the action type for later reference var enhancedData = character.GetEnhancedActionData(); if (enhancedData == null) { enhancedData = new EnhancedCharacterActionData(); character.SetEnhancedActionData(enhancedData); } enhancedData.actionType = actionType; // Clear any existing action lines before starting new targeting ClearActionLineForCharacter(character); // Start the targeting line targetingLine.StartTargeting(dragStartPosition); Debug.Log($"✅ Targeting mode activated for {character.CharacterName}"); } /// /// Cancel current targeting operation /// public void CancelTargeting() { if (isDragging && selectedCharacter != null) { selectedCharacter.actionData.Reset(); selectedCharacter.SetVisualState(ActionDecisionState.NoAction); targetingLine.StopTargeting(); selectedCharacter = null; isDragging = false; Debug.Log("❌ Targeting cancelled"); } } }