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()}");
}
}
}