using UnityEngine; using UnityEngine.UIElements; /// /// Integration script that connects the new battle action system with existing character selection /// This allows switching between the old click-drag system and the new action wheel system /// public class BattleActionIntegration : MonoBehaviour { [Header("System References")] public PlayerDecisionController playerDecisionController; public BattleActionSystem battleActionSystem; public BattleActionWheel actionWheel; // Legacy Canvas-based wheel public EnemySelectionUI enemySelectionUI; // TODO: Add after compilation public BattleItemSelector itemSelectionUI; [Header("Settings")] [Tooltip("Enable new action wheel system (false = use old click-drag system)")] public bool useNewActionSystem = false; // Changed to false by default for simpler testing [Space] [Tooltip("Press this key to toggle between action systems")] public KeyCode toggleSystemKey = KeyCode.T; private Character lastSelectedCharacter; private MonoBehaviour simpleWheelComponent; private string currentInstruction = ""; private float instructionTimer = 0f; private float instructionDuration = 5f; void Start() { // FORCE useNewActionSystem to false to preserve drag functionality useNewActionSystem = false; // Find components if not assigned if (playerDecisionController == null) playerDecisionController = FindFirstObjectByType(); if (battleActionSystem == null) battleActionSystem = FindFirstObjectByType(); if (actionWheel == null) actionWheel = FindFirstObjectByType(); if (enemySelectionUI == null) enemySelectionUI = FindFirstObjectByType(); if (itemSelectionUI == null) itemSelectionUI = FindFirstObjectByType(); // Ensure PlayerDecisionController is always enabled for drag functionality if (playerDecisionController != null) { playerDecisionController.enabled = true; playerDecisionController.SetEnabled(true); } // Try to find or create a simple wheel component var existingWheels = FindObjectsByType(FindObjectsSortMode.None); foreach (var comp in existingWheels) { if (comp.GetType().Name == "SimpleActionWheel") { simpleWheelComponent = comp; break; } } if (simpleWheelComponent == null) { // Create simple wheel if it doesn't exist GameObject wheelObj = new GameObject("SimpleActionWheel"); // Use reflection to add the component var componentType = System.Type.GetType("SimpleActionWheel"); if (componentType != null) { simpleWheelComponent = wheelObj.AddComponent(componentType) as MonoBehaviour; } else { Debug.LogError("❌ Could not find SimpleActionWheel type"); } } // Subscribe to events if (battleActionSystem != null) { battleActionSystem.OnActionCompleted += OnCharacterActionCompleted; } // Connect SimpleActionWheel events using reflection if (simpleWheelComponent != null) { ConnectSimpleWheelEvents(); } } void Update() { // Allow toggling between systems if (Input.GetKeyDown(toggleSystemKey)) { ToggleActionSystem(); } // Handle action wheel key from SimpleActionWheel // Get the key from SimpleActionWheel component if available KeyCode wheelKey = KeyCode.Q; // Default fallback if (simpleWheelComponent != null) { var toggleKeyField = simpleWheelComponent.GetType().GetField("toggleKey"); if (toggleKeyField != null) { wheelKey = (KeyCode)toggleKeyField.GetValue(simpleWheelComponent); } } if (Input.GetKeyDown(wheelKey)) { // Clear any existing instruction when opening wheel currentInstruction = ""; instructionTimer = 0f; // When using old system, get the selected character from PlayerDecisionController Character characterForWheel = lastSelectedCharacter; if (!useNewActionSystem && playerDecisionController != null) { Character currentlySelected = playerDecisionController.GetSelectedCharacter(); if (currentlySelected != null) { characterForWheel = currentlySelected; lastSelectedCharacter = currentlySelected; // Update for consistency } } if (characterForWheel != null) { // Allow reopening the action wheel even if an action is already selected // This enables canceling/changing the selected action ShowActionWheelForCharacter(characterForWheel); } } if (useNewActionSystem) { HandleNewActionSystemInput(); } else { // When using old system, track character selection for action wheel // Monitor PlayerDecisionController's targeting state to update lastSelectedCharacter if (playerDecisionController != null && playerDecisionController.IsInTargetingMode) { Character currentlySelected = playerDecisionController.GetSelectedCharacter(); if (currentlySelected != null && currentlySelected != lastSelectedCharacter) { lastSelectedCharacter = currentlySelected; // Clear any old instructions and show current action status ShowCharacterActionStatus(currentlySelected); } } } // Note: When useNewActionSystem is false, the old PlayerDecisionController.Update() // will handle input automatically - no need to interfere // Update instruction timer if (instructionTimer > 0f) { instructionTimer -= Time.deltaTime; if (instructionTimer <= 0f) { currentInstruction = ""; } } } /// /// Get the action wheel key from SimpleActionWheel component /// private KeyCode GetActionWheelKey() { if (simpleWheelComponent != null) { var toggleKeyField = simpleWheelComponent.GetType().GetField("toggleKey"); if (toggleKeyField != null) { return (KeyCode)toggleKeyField.GetValue(simpleWheelComponent); } } return KeyCode.Q; // Default fallback } void OnGUI() { // Show instruction message if active if (!string.IsNullOrEmpty(currentInstruction)) { GUIStyle instructionStyle = new GUIStyle(GUI.skin.label); instructionStyle.fontSize = 18; instructionStyle.fontStyle = FontStyle.Bold; instructionStyle.alignment = TextAnchor.MiddleCenter; instructionStyle.normal.textColor = Color.yellow; Rect instructionRect = new Rect(0, 50, Screen.width, 30); // Background GUI.color = new Color(0, 0, 0, 0.7f); GUI.Box(instructionRect, ""); // Text GUI.color = Color.white; GUI.Label(instructionRect, currentInstruction, instructionStyle); } // Simple UI for testing - show regardless of system mode GUILayout.BeginArea(new Rect(10, 10, 300, 250)); GUILayout.Label($"Battle Action System (Mode: {(useNewActionSystem ? "New" : "Old")})"); GUILayout.Label($"Action Key: {GetActionWheelKey()}"); GUILayout.Label($"Simple Wheel: {(simpleWheelComponent != null ? "✅" : "❌")}"); if (lastSelectedCharacter != null) { GUILayout.Label($"Selected: {lastSelectedCharacter.CharacterName}"); var actionData = lastSelectedCharacter.GetEnhancedActionData(); if (actionData != null && actionData.hasValidAction) { GUILayout.Label($"Action: {actionData.GetActionDescription()}"); GUILayout.Label($"Press {GetActionWheelKey()} again to change action", GUI.skin.box); } else { GUILayout.Label($"Press {GetActionWheelKey()} to choose action"); } } else { GUILayout.Label("No character selected"); GUILayout.Label("Click a player character to select"); } GUILayout.Label($"Press {GetActionWheelKey()} to show action wheel"); if (GUILayout.Button("Test Action Wheel")) { var testCharacter = FindFirstObjectByType(); if (testCharacter != null) { ShowActionWheelForCharacter(testCharacter); } } if (GUILayout.Button("Reset PlayerDecisionController")) { if (playerDecisionController != null) { playerDecisionController.ResetState(); } } GUILayout.EndArea(); } private void HandleNewActionSystemInput() { // Don't interfere with mouse input if PlayerDecisionController is in targeting mode if (playerDecisionController != null && playerDecisionController.IsInTargetingMode) { // Let PlayerDecisionController handle the input for targeting return; } // Check for character selection if (Input.GetMouseButtonDown(0)) { Character selectedCharacter = GetCharacterAtMousePosition(); if (selectedCharacter != null) { if (selectedCharacter.CompareTag("Player")) { SelectCharacterForAction(selectedCharacter); } else { SelectCharacterForAction(selectedCharacter); } } } } private Character GetCharacterAtMousePosition() { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { return hit.collider.GetComponent(); } return null; } private void SelectCharacterForAction(Character character) { // Only clear visual state of previous selection if they don't have an action if (lastSelectedCharacter != null) { var prevActionData = lastSelectedCharacter.GetEnhancedActionData(); if (prevActionData == null || !prevActionData.hasValidAction) { // Only reset to NoAction if they don't have a valid action lastSelectedCharacter.SetVisualState(ActionDecisionState.NoAction); } else { // Preserve their action state lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected); } } lastSelectedCharacter = character; // Initialize enhanced action data if needed var actionData = character.GetEnhancedActionData(); if (actionData == null) { // Create instance at runtime to avoid compilation issues actionData = new EnhancedCharacterActionData(); character.SetEnhancedActionData(actionData); } // Highlight selected character (use a different state for "currently selected") character.SetVisualState(ActionDecisionState.NoAction); // Update all character visual states to maintain proper color coding UpdateAllCharacterVisualStates(); } /// /// Update visual states for all characters to properly show action status /// private void UpdateAllCharacterVisualStates() { Character[] allCharacters = FindObjectsByType(FindObjectsSortMode.None); foreach (Character character in allCharacters) { if (character.CompareTag("Player")) { var actionData = character.GetEnhancedActionData(); if (character == lastSelectedCharacter) { // Currently selected character - show selection highlight character.SetVisualState(ActionDecisionState.NoAction); // Pink for selection } else if (actionData != null && actionData.hasValidAction) { // Has valid action selected - show action confirmed state character.SetVisualState(ActionDecisionState.ActionSelected); // Green for confirmed action } else { // No action selected character.SetVisualState(ActionDecisionState.NoAction); // Pink for no action } } } } private void ShowActionWheelForCharacter(Character character) { // Clear any existing instruction when showing the wheel currentInstruction = ""; instructionTimer = 0f; // Reset PlayerDecisionController state to ensure clean state if (playerDecisionController != null) { playerDecisionController.ResetState(); } // Reset any existing action for this character to allow changing selection var existingActionData = character.GetEnhancedActionData(); if (existingActionData != null && existingActionData.hasValidAction) { existingActionData.Reset(); character.SetVisualState(ActionDecisionState.NoAction); } // Try simple wheel first if (simpleWheelComponent != null) { // Use reflection to call ShowWheelForCharacter var method = simpleWheelComponent.GetType().GetMethod("ShowWheelForCharacter"); if (method != null) { method.Invoke(simpleWheelComponent, new object[] { character }); return; } } // Fallback to battle action system if (battleActionSystem != null) { battleActionSystem.ShowActionWheel(character); } } private void ConnectSimpleWheelEvents() { if (simpleWheelComponent == null) { Debug.LogError("❌ simpleWheelComponent is null in ConnectSimpleWheelEvents"); return; } // Use reflection to connect to OnActionSelected event var eventInfo = simpleWheelComponent.GetType().GetEvent("OnActionSelected"); if (eventInfo != null) { // Create delegate that matches the event signature: Action var delegateType = eventInfo.EventHandlerType; var methodInfo = this.GetType().GetMethod("OnActionSelected", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (methodInfo != null) { var handler = System.Delegate.CreateDelegate(delegateType, this, methodInfo); eventInfo.AddEventHandler(simpleWheelComponent, handler); } } else { Debug.LogError("❌ Could not find OnActionSelected event in SimpleActionWheel"); } } private void OnActionSelected(BattleActionType actionType) { if (lastSelectedCharacter == null) { Debug.LogWarning("❌ Action selected but no character selected!"); return; } // Set action data for the character var actionData = lastSelectedCharacter.GetEnhancedActionData(); if (actionData == null) { actionData = new EnhancedCharacterActionData(); lastSelectedCharacter.SetEnhancedActionData(actionData); } // Configure action based on type and enable targeting mode switch (actionType) { case BattleActionType.Attack: actionData.actionType = actionType; ShowInstructionMessage("ATTACK: Drag from character to enemy"); StartTargetingMode(lastSelectedCharacter, actionType); break; case BattleActionType.Move: actionData.actionType = actionType; ShowInstructionMessage("MOVE: Drag from character to target position"); StartTargetingMode(lastSelectedCharacter, actionType); break; case BattleActionType.UseItem: actionData.actionType = actionType; ShowInstructionMessage("USE ITEM: Select item from list"); ShowItemSelection(lastSelectedCharacter); break; case BattleActionType.CastSpell: actionData.actionType = actionType; actionData.state = ActionDecisionState.ActionSelected; lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected); break; case BattleActionType.Defend: actionData.actionType = actionType; actionData.state = ActionDecisionState.ActionSelected; lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected); break; case BattleActionType.RunAway: actionData.actionType = actionType; actionData.state = ActionDecisionState.ActionSelected; lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected); break; } // Update all character visual states to show proper action status UpdateAllCharacterVisualStates(); } private void StartTargetingMode(Character character, BattleActionType actionType) { // Enable the PlayerDecisionController to handle targeting if (playerDecisionController != null) { // Use the new public method to start targeting playerDecisionController.StartTargetingForCharacter(character, actionType); } else { Debug.LogError("❌ PlayerDecisionController not found - cannot start targeting mode"); } } private void ShowItemSelection(Character character) { if (itemSelectionUI != null) { // Subscribe to item selection events itemSelectionUI.OnItemSelected -= OnItemSelected; itemSelectionUI.OnSelectionCancelled -= OnItemSelectionCancelled; itemSelectionUI.OnItemSelected += OnItemSelected; itemSelectionUI.OnSelectionCancelled += OnItemSelectionCancelled; itemSelectionUI.ShowItemSelection(character); } else { Debug.LogError("❌ BattleItemSelector not found!"); // Fallback: Complete action immediately var actionData = character.GetEnhancedActionData(); if (actionData != null) { actionData.state = ActionDecisionState.ActionSelected; character.SetVisualState(ActionDecisionState.ActionSelected); } } } private void OnItemSelected(string itemName, int itemIndex) { if (lastSelectedCharacter != null) { var actionData = lastSelectedCharacter.GetEnhancedActionData(); if (actionData != null) { // Check if item requires targeting (healing potions, etc. might target allies) bool requiresTargeting = IsItemRequiringTargeting(itemName); // Properly set the item action using the SetItemAction method actionData.SetItemAction(itemName, itemIndex, requiresTargeting); if (!requiresTargeting) { lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected); // Show the updated action status ShowCharacterActionStatus(lastSelectedCharacter); } else { ShowInstructionMessage($"TARGET: Select target for {itemName}"); StartTargetingMode(lastSelectedCharacter, BattleActionType.UseItem); } } } } /// /// Check if an item requires targeting (healing items, targeted attacks, etc.) /// private bool IsItemRequiringTargeting(string itemName) { // Add logic here to determine if item needs targeting // For now, assume most items are self-use (like health potions) // Healing items that can target others would return true if (itemName.ToLower().Contains("heal") && itemName.ToLower().Contains("other")) return true; if (itemName.ToLower().Contains("revive")) return true; if (itemName.ToLower().Contains("bomb") || itemName.ToLower().Contains("throw")) return true; return false; // Most items are self-use } private void OnItemSelectionCancelled() { if (lastSelectedCharacter != null) { var actionData = lastSelectedCharacter.GetEnhancedActionData(); if (actionData != null) { actionData.Reset(); lastSelectedCharacter.SetVisualState(ActionDecisionState.NoAction); } } } private void OnCharacterActionCompleted(Character character) { // Clear selection after action is complete if (character == lastSelectedCharacter) { lastSelectedCharacter = null; } } /// /// Manually trigger action selection for a character (for use by other systems) /// public void SelectCharacter(Character character) { SelectCharacterForAction(character); } /// /// Execute all selected actions (for turn-based systems) /// public void ExecuteAllPlayerActions() { Character[] playerCharacters = FindObjectsByType(FindObjectsSortMode.None); foreach (Character character in playerCharacters) { var actionData = character.GetEnhancedActionData(); if (character.CompareTag("Player") && actionData != null && actionData.hasValidAction) { if (battleActionSystem != null) { battleActionSystem.ExecuteCharacterAction(character); } } } } /// /// Switch between old and new action systems /// public void ToggleActionSystem() { useNewActionSystem = !useNewActionSystem; // Enable/disable appropriate systems if (playerDecisionController != null) { // Keep PlayerDecisionController enabled for targeting support // Just control its input handling behavior playerDecisionController.enabled = true; playerDecisionController.SetEnabled(true); } // Clear any instruction messages when switching currentInstruction = ""; instructionTimer = 0f; } /// /// Check if all players have selected actions /// public bool AllPlayersHaveActions() { Character[] playerCharacters = FindObjectsByType(FindObjectsSortMode.None); foreach (Character character in playerCharacters) { if (character.CompareTag("Player")) { var actionData = character.GetEnhancedActionData(); if (actionData == null || !actionData.hasValidAction) { return false; } } } return true; } /// /// Reset all player actions (useful for new turns) /// public void ResetAllPlayerActions() { Character[] playerCharacters = FindObjectsByType(FindObjectsSortMode.None); foreach (Character character in playerCharacters) { if (character.CompareTag("Player")) { var actionData = character.GetEnhancedActionData(); if (actionData != null) actionData.Reset(); character.SetVisualState(ActionDecisionState.NoAction); } } lastSelectedCharacter = null; } /// /// Cancel action for a specific character (useful for undoing individual selections) /// public void CancelCharacterAction(Character character) { if (character == null) return; var actionData = character.GetEnhancedActionData(); if (actionData != null && actionData.hasValidAction) { actionData.Reset(); character.SetVisualState(ActionDecisionState.NoAction); ShowInstructionMessage($"Action canceled for {character.CharacterName}"); } } private void ShowInstructionMessage(string message) { currentInstruction = message; instructionTimer = instructionDuration; } /// /// Show the current action status for a character or clear instructions if no action /// private void ShowCharacterActionStatus(Character character) { var actionData = character.GetEnhancedActionData(); if (actionData != null && actionData.hasValidAction) { // Show current action ShowInstructionMessage($"Current action: {actionData.GetActionDescription()}"); } else { // Clear instructions if no action set currentInstruction = ""; instructionTimer = 0f; } } /// /// Called by PlayerDecisionController when targeting is complete /// public void OnTargetingComplete(Character character) { // Update lastSelectedCharacter so action wheel knows which character was last used lastSelectedCharacter = character; // Update all character visual states to reflect the completed action UpdateAllCharacterVisualStates(); // Show instruction that action is set var actionData = character.GetEnhancedActionData(); if (actionData != null && actionData.hasValidAction) { ShowInstructionMessage($"Action set: {actionData.GetActionDescription()}"); } } }