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() { Debug.Log("๐Ÿš€ BattleActionIntegration starting..."); // 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); Debug.Log("๐ŸŽฎ PlayerDecisionController enabled for drag functionality"); } // 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; Debug.Log("๐ŸŽฎ Found existing SimpleActionWheel"); 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; Debug.Log("๐ŸŽฎ Created SimpleActionWheel automatically"); } 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(); } Debug.Log($"โœ… BattleActionIntegration initialized - useNewActionSystem: {useNewActionSystem}"); } 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 Debug.Log($"โŒจ๏ธ {wheelKey} pressed, showing wheel for {characterForWheel.CharacterName}"); ShowActionWheelForCharacter(characterForWheel); } else { Debug.Log($"โŒจ๏ธ {wheelKey} pressed but no character selected"); } } 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; Debug.Log($"๐Ÿ–ฑ๏ธ Character selected for action wheel: {currentlySelected.CharacterName}"); // 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) { Debug.Log($"๐Ÿ–ฑ๏ธ Clicked on character: {selectedCharacter.CharacterName} - Tag: {selectedCharacter.tag}"); if (selectedCharacter.CompareTag("Player")) { Debug.Log($"โœ… Confirmed player character: {selectedCharacter.CharacterName}"); SelectCharacterForAction(selectedCharacter); } else { Debug.Log($"โŒ Not a player character: {selectedCharacter.CharacterName} (Tag: {selectedCharacter.tag})"); // Try to force selection anyway for testing Debug.Log($"๐Ÿงช Trying to select anyway for testing..."); SelectCharacterForAction(selectedCharacter); } } else { Debug.Log("๐Ÿ–ฑ๏ธ Clicked but no character found"); } } } 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(); Debug.Log($"๐ŸŽฏ Selected character for action: {character.CharacterName}"); // Don't auto-show wheel - let user press Q manually // if (useNewActionSystem) // { // ShowActionWheelForCharacter(character); // } } /// /// 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) { Debug.Log($"๐ŸŽฏ ShowActionWheelForCharacter called for: {character.CharacterName}"); // 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) { Debug.Log($"๐Ÿ”„ Resetting existing action for {character.CharacterName}: {existingActionData.GetActionDescription()}"); existingActionData.Reset(); character.SetVisualState(ActionDecisionState.NoAction); } // Try simple wheel first if (simpleWheelComponent != null) { Debug.Log($"๐ŸŽฎ Found SimpleActionWheel component: {simpleWheelComponent.GetType().Name}"); // Use reflection to call ShowWheelForCharacter var method = simpleWheelComponent.GetType().GetMethod("ShowWheelForCharacter"); if (method != null) { Debug.Log("๐Ÿ”ง Calling ShowWheelForCharacter via reflection..."); method.Invoke(simpleWheelComponent, new object[] { character }); return; } else { Debug.LogError("โŒ ShowWheelForCharacter method not found on SimpleActionWheel!"); } } else { Debug.LogError("โŒ simpleWheelComponent is null!"); } // Fallback to battle action system if (battleActionSystem != null) { Debug.Log("๐Ÿ”„ Falling back to BattleActionSystem..."); battleActionSystem.ShowActionWheel(character); } else { Debug.LogError("BattleActionIntegration: No action wheel system found!"); } } private void ConnectSimpleWheelEvents() { if (simpleWheelComponent == null) { Debug.LogError("โŒ simpleWheelComponent is null in ConnectSimpleWheelEvents"); return; } Debug.Log($"๐Ÿ”ง Connecting events for SimpleActionWheel component: {simpleWheelComponent.GetType().Name}"); // Use reflection to connect to OnActionSelected event var eventInfo = simpleWheelComponent.GetType().GetEvent("OnActionSelected"); if (eventInfo != null) { Debug.Log($"โœ… Found OnActionSelected event: {eventInfo.EventHandlerType}"); // 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) { Debug.Log($"โœ… Found OnActionSelected method: {methodInfo.Name}"); var handler = System.Delegate.CreateDelegate(delegateType, this, methodInfo); eventInfo.AddEventHandler(simpleWheelComponent, handler); Debug.Log("โœ… Successfully connected SimpleActionWheel.OnActionSelected event"); } else { Debug.LogError("โŒ Could not find OnActionSelected method in BattleActionIntegration"); } } else { Debug.LogError("โŒ Could not find OnActionSelected event in SimpleActionWheel"); } } private void OnActionSelected(BattleActionType actionType) { Debug.Log($"๐Ÿ”ฅ OnActionSelected called with: {actionType}"); if (lastSelectedCharacter == null) { Debug.LogWarning("โŒ Action selected but no character selected!"); return; } Debug.Log($"๐ŸŽฏ {lastSelectedCharacter.CharacterName} selected action: {actionType}"); // Set action data for the character var actionData = lastSelectedCharacter.GetEnhancedActionData(); if (actionData == null) { actionData = new EnhancedCharacterActionData(); lastSelectedCharacter.SetEnhancedActionData(actionData); Debug.Log($"๐Ÿ“ Created new EnhancedCharacterActionData for {lastSelectedCharacter.CharacterName}"); } // Configure action based on type and enable targeting mode switch (actionType) { case BattleActionType.Attack: actionData.actionType = actionType; Debug.Log("๐Ÿ—ก๏ธ Attack selected - Now drag from character to target enemy!"); ShowInstructionMessage("ATTACK: Drag from character to enemy"); StartTargetingMode(lastSelectedCharacter, actionType); break; case BattleActionType.Move: actionData.actionType = actionType; Debug.Log("๐Ÿ‘Ÿ Move selected - Now drag from character to target position!"); ShowInstructionMessage("MOVE: Drag from character to target position"); StartTargetingMode(lastSelectedCharacter, actionType); break; case BattleActionType.UseItem: actionData.actionType = actionType; Debug.Log("๐Ÿงช Use Item selected - showing item selection UI"); ShowInstructionMessage("USE ITEM: Select item from list"); ShowItemSelection(lastSelectedCharacter); break; case BattleActionType.CastSpell: actionData.actionType = actionType; actionData.state = ActionDecisionState.ActionSelected; lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected); Debug.Log("โœจ Cast Spell selected - implement spell selection UI"); break; case BattleActionType.Defend: actionData.actionType = actionType; actionData.state = ActionDecisionState.ActionSelected; lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected); Debug.Log("๐Ÿ›ก๏ธ Defend action set - character will defend this turn"); break; case BattleActionType.RunAway: actionData.actionType = actionType; actionData.state = ActionDecisionState.ActionSelected; lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected); Debug.Log("๐Ÿ’จ Run Away action set - character will attempt to flee"); break; } Debug.Log($"โœ… Action {actionType} configured for {lastSelectedCharacter.CharacterName}"); // Update all character visual states to show proper action status UpdateAllCharacterVisualStates(); } private void StartTargetingMode(Character character, BattleActionType actionType) { Debug.Log($"๐ŸŽฏ Starting targeting mode for {character.CharacterName} with action {actionType}"); // Enable the PlayerDecisionController to handle targeting if (playerDecisionController != null) { // Use the new public method to start targeting playerDecisionController.StartTargetingForCharacter(character, actionType); Debug.Log($"โœ… PlayerDecisionController targeting started for {actionType}"); } else { Debug.LogError("โŒ PlayerDecisionController not found - cannot start targeting mode"); } } private void ShowItemSelection(Character character) { Debug.Log($"๐Ÿงช Showing item selection for {character.CharacterName}"); 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) { Debug.Log($"๐Ÿ“ฆ Item selected: {itemName} (index: {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); Debug.Log($"โœ… {lastSelectedCharacter.CharacterName} will use {itemName}"); // Show the updated action status ShowCharacterActionStatus(lastSelectedCharacter); } else { Debug.Log($"๐ŸŽฏ {itemName} requires targeting - start targeting mode"); 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() { Debug.Log("โŒ Item selection cancelled"); if (lastSelectedCharacter != null) { var actionData = lastSelectedCharacter.GetEnhancedActionData(); if (actionData != null) { actionData.Reset(); lastSelectedCharacter.SetVisualState(ActionDecisionState.NoAction); } } } private void OnCharacterActionCompleted(Character character) { Debug.Log($"โœ… Action completed for {character.CharacterName}"); // 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; Debug.Log($"๐ŸŽฏ Action system switched to: {(useNewActionSystem ? "New Action Wheel (Q to open wheel)" : "Old Click-Drag (direct drag to move/attack)")}"); } /// /// 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; Debug.Log("๐Ÿ”„ All player actions reset"); } /// /// 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) { Debug.Log($"โŒ Canceling action for {character.CharacterName}: {actionData.GetActionDescription()}"); actionData.Reset(); character.SetVisualState(ActionDecisionState.NoAction); ShowInstructionMessage($"Action canceled for {character.CharacterName}"); } else { Debug.Log($"No action to cancel for {character.CharacterName}"); } } private void ShowInstructionMessage(string message) { currentInstruction = message; instructionTimer = instructionDuration; Debug.Log($"๐Ÿ“ข Instruction: {message}"); } /// /// 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; Debug.Log($"๐Ÿ“ข No action set for {character.CharacterName} - instructions cleared"); } } /// /// Called by PlayerDecisionController when targeting is complete /// public void OnTargetingComplete(Character character) { Debug.Log($"โœ… Targeting complete for {character.CharacterName}"); // 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()}"); } } }