using UnityEngine; using System.Collections.Generic; using System.Collections; /// /// Manages the execution of battle actions and coordinates with existing systems /// public class BattleActionSystem : MonoBehaviour { [Header("References")] public BattleActionWheel actionWheel; [Header("Item System")] public BattleItemSelector itemSelectionUI; [Header("Spell System")] public SpellSelectionUI spellSelectionUI; [Header("Settings")] public LayerMask enemyLayerMask = 1 << 10; public LayerMask playerLayerMask = 1 << 9; public LayerMask groundLayerMask = 1 << 0; private Character currentCharacter; private EnhancedCharacterActionData pendingAction; private bool isWaitingForTarget = false; private Camera mainCamera; // Events public event System.Action OnActionCompleted; public event System.Action OnActionStarted; void Awake() { mainCamera = Camera.main; // Find or create action wheel if (actionWheel == null) actionWheel = FindFirstObjectByType(); } void Start() { // Subscribe to action wheel events if (actionWheel != null) { actionWheel.OnActionSelected += OnActionTypeSelected; actionWheel.OnWheelClosed += OnActionWheelClosed; } // Subscribe to item/spell selection events if (itemSelectionUI != null) { itemSelectionUI.OnItemSelected += OnItemSelected; itemSelectionUI.OnSelectionCancelled += OnItemSelectionCancelled; } if (spellSelectionUI != null) { spellSelectionUI.OnSpellSelected += OnSpellSelected; spellSelectionUI.OnSelectionCancelled += OnSpellSelectionCancelled; } } void Update() { if (isWaitingForTarget) { HandleTargetSelection(); } } /// /// Shows the action wheel for a character /// public void ShowActionWheel(Character character) { currentCharacter = character; if (actionWheel != null) { Vector3 wheelPosition = character.transform.position + Vector3.up * 2f; actionWheel.ShowWheel(character, wheelPosition); } else { Debug.LogError("BattleActionSystem: No action wheel assigned!"); } } /// /// Hides the action wheel /// public void HideActionWheel() { if (actionWheel != null) { actionWheel.HideWheel(); } } /// /// Executes the character's selected action /// public void ExecuteCharacterAction(Character character) { if (character == null) { Debug.LogWarning("BattleActionSystem: Invalid character"); return; } var actionData = character.GetEnhancedActionData(); if (actionData == null) { Debug.LogWarning($"BattleActionSystem: Character {character.CharacterName} has no enhanced action data"); return; } if (!actionData.hasValidAction) { Debug.LogWarning($"BattleActionSystem: Character {character.CharacterName} has no valid action"); return; } Debug.Log($"๐ŸŽฏ Executing {actionData.actionType} for {character.CharacterName}: {actionData.GetActionDescription()}"); OnActionStarted?.Invoke(character, actionData.actionType); StartCoroutine(ExecuteActionCoroutine(character, actionData)); } private IEnumerator ExecuteActionCoroutine(Character character, EnhancedCharacterActionData actionData) { switch (actionData.actionType) { case BattleActionType.Move: yield return ExecuteMoveAction(character, actionData); break; case BattleActionType.Attack: yield return ExecuteAttackAction(character, actionData); break; case BattleActionType.UseItem: yield return ExecuteItemAction(character, actionData); break; case BattleActionType.CastSpell: yield return ExecuteSpellAction(character, actionData); break; case BattleActionType.Defend: yield return ExecuteDefendAction(character, actionData); break; case BattleActionType.Wait: yield return ExecuteWaitAction(character, actionData); break; case BattleActionType.RunAway: yield return ExecuteRunAwayAction(character, actionData); break; } actionData.state = ActionDecisionState.ActionExecuted; OnActionCompleted?.Invoke(character); } #region Action Execution Methods private IEnumerator ExecuteMoveAction(Character character, EnhancedCharacterActionData actionData) { Debug.Log($"๐Ÿšถ {character.CharacterName} moving to {actionData.targetPosition}"); // Use existing movement system or implement new one character.transform.position = actionData.targetPosition; yield return new WaitForSeconds(0.5f); // Animation time } private IEnumerator ExecuteAttackAction(Character character, EnhancedCharacterActionData actionData) { if (actionData.targetEnemy == null) { Debug.LogWarning($"Attack action for {character.CharacterName} has no target!"); yield break; } Debug.Log($"โš”๏ธ {character.CharacterName} attacking {actionData.targetEnemy.name}"); // Use existing attack system Character targetCharacter = actionData.targetEnemy.GetComponent(); if (targetCharacter != null) { character.AttackTarget(targetCharacter); } yield return new WaitForSeconds(1f); // Attack animation time } private IEnumerator ExecuteItemAction(Character character, EnhancedCharacterActionData actionData) { Debug.Log($"๐Ÿงช {character.CharacterName} using item: {actionData.selectedItemName}"); // Placeholder item usage logic yield return UseItem(character, actionData.selectedItemName, actionData.selectedItemIndex, actionData.targetCharacter); yield return new WaitForSeconds(0.8f); } private IEnumerator ExecuteSpellAction(Character character, EnhancedCharacterActionData actionData) { Debug.Log($"โœจ {character.CharacterName} casting spell: {actionData.selectedSpellName}"); // Placeholder spell casting logic yield return CastSpell(character, actionData.selectedSpellName, actionData.targetCharacter, actionData.targetPosition); yield return new WaitForSeconds(1.2f); } private IEnumerator ExecuteDefendAction(Character character, EnhancedCharacterActionData actionData) { Debug.Log($"๐Ÿ›ก๏ธ {character.CharacterName} defending"); // Apply defend buff (reduce incoming damage, increase AC, etc.) ApplyDefendBuff(character); yield return new WaitForSeconds(0.3f); } private IEnumerator ExecuteWaitAction(Character character, EnhancedCharacterActionData actionData) { Debug.Log($"โณ {character.CharacterName} waiting"); // Character does nothing but maintains position yield return new WaitForSeconds(0.1f); } private IEnumerator ExecuteRunAwayAction(Character character, EnhancedCharacterActionData actionData) { Debug.Log($"๐Ÿƒ {character.CharacterName} running away"); // Move character away from enemies or off battlefield yield return HandleRunAway(character); yield return new WaitForSeconds(1f); } #endregion #region Event Handlers private void OnActionTypeSelected(BattleActionType actionType) { if (currentCharacter == null) return; Debug.Log($"๐ŸŽฏ Action type selected: {actionType} for {currentCharacter.CharacterName}"); // Initialize enhanced action data if needed var actionData = currentCharacter.GetEnhancedActionData(); if (actionData == null) { actionData = new EnhancedCharacterActionData(); currentCharacter.SetEnhancedActionData(actionData); } switch (actionType) { case BattleActionType.Move: StartTargetSelectionForMove(); break; case BattleActionType.Attack: StartTargetSelectionForAttack(); break; case BattleActionType.UseItem: ShowItemSelection(); break; case BattleActionType.CastSpell: ShowSpellSelection(); break; case BattleActionType.Defend: actionData.SetDefendAction(); CompleteActionSelection(); break; case BattleActionType.Wait: actionData.SetWaitAction(); CompleteActionSelection(); break; case BattleActionType.RunAway: actionData.SetRunAwayAction(); CompleteActionSelection(); break; } } private void OnActionWheelClosed() { if (!isWaitingForTarget) { CancelActionSelection(); } } private void OnItemSelected(string itemName, int itemIndex) { var actionData = currentCharacter?.GetEnhancedActionData(); if (actionData == null) return; // Determine if item requires targeting bool requiresTarget = DoesItemRequireTarget(itemName); actionData.SetItemAction(itemName, itemIndex, requiresTarget); if (requiresTarget) { StartTargetSelectionForItem(); } else { CompleteActionSelection(); } } private void OnItemSelectionCancelled() { CancelActionSelection(); } private void OnSpellSelected(string spellName) { var actionData = currentCharacter?.GetEnhancedActionData(); if (actionData == null) return; // Determine spell properties var spellInfo = GetSpellInfo(spellName); actionData.SetSpellAction(spellName, spellInfo.requiresTarget, spellInfo.isAoE, spellInfo.aoeRadius); if (spellInfo.requiresTarget) { StartTargetSelectionForSpell(); } else { CompleteActionSelection(); } } private void OnSpellSelectionCancelled() { CancelActionSelection(); } #endregion #region Target Selection private void StartTargetSelectionForMove() { Debug.Log("๐ŸŽฏ Select move target..."); pendingAction = currentCharacter.GetEnhancedActionData(); isWaitingForTarget = true; // Show move cursor or indicators } private void StartTargetSelectionForAttack() { Debug.Log("๐ŸŽฏ Select attack target..."); pendingAction = currentCharacter.GetEnhancedActionData(); isWaitingForTarget = true; // Show attack cursor or highlight enemies } private void StartTargetSelectionForItem() { Debug.Log("๐ŸŽฏ Select item target..."); pendingAction = currentCharacter.GetEnhancedActionData(); isWaitingForTarget = true; } private void StartTargetSelectionForSpell() { Debug.Log("๐ŸŽฏ Select spell target..."); pendingAction = currentCharacter.GetEnhancedActionData(); isWaitingForTarget = true; } private void HandleTargetSelection() { if (Input.GetMouseButtonDown(0)) { Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition); RaycastHit hit; // Check for character targets if (Physics.Raycast(ray, out hit, Mathf.Infinity, enemyLayerMask | playerLayerMask)) { Character targetCharacter = hit.collider.GetComponent(); if (targetCharacter != null) { SetCharacterTarget(targetCharacter); return; } } // Check for ground/position targets if (Physics.Raycast(ray, out hit, Mathf.Infinity, groundLayerMask)) { SetPositionTarget(hit.point); return; } } // Cancel targeting with right click or escape if (Input.GetMouseButtonDown(1) || Input.GetKeyDown(KeyCode.Escape)) { CancelTargetSelection(); } } private void SetCharacterTarget(Character target) { if (pendingAction == null) return; if (pendingAction.actionType == BattleActionType.Attack && target.CompareTag("Enemy")) { pendingAction.SetTarget(target.gameObject); CompleteActionSelection(); } else if (pendingAction.actionType == BattleActionType.UseItem || pendingAction.actionType == BattleActionType.CastSpell) { pendingAction.SetTarget(target); CompleteActionSelection(); } } private void SetPositionTarget(Vector3 position) { if (pendingAction == null) return; if (pendingAction.actionType == BattleActionType.Move) { pendingAction.SetMoveAction(position); CompleteActionSelection(); } else if (pendingAction.actionType == BattleActionType.CastSpell && pendingAction.isAreaOfEffect) { pendingAction.SetTarget(position); CompleteActionSelection(); } } private void CancelTargetSelection() { isWaitingForTarget = false; pendingAction = null; CancelActionSelection(); } #endregion #region Helper Methods private void CompleteActionSelection() { isWaitingForTarget = false; pendingAction = null; if (currentCharacter != null) { currentCharacter.SetVisualState(ActionDecisionState.ActionSelected); var actionData = currentCharacter.GetEnhancedActionData(); if (actionData != null) { Debug.Log($"โœ… Action selection complete for {currentCharacter.CharacterName}: {actionData.GetActionDescription()}"); } } } private void CancelActionSelection() { isWaitingForTarget = false; pendingAction = null; if (currentCharacter != null) { var actionData = currentCharacter.GetEnhancedActionData(); if (actionData != null) actionData.Reset(); currentCharacter.SetVisualState(ActionDecisionState.NoAction); Debug.Log($"โŒ Action selection cancelled for {currentCharacter.CharacterName}"); } currentCharacter = null; } private void ShowItemSelection() { if (itemSelectionUI != null) { itemSelectionUI.ShowItemSelection(currentCharacter); } else { Debug.LogWarning("No ItemSelectionUI found - creating placeholder item action"); // Placeholder: auto-select a health potion OnItemSelected("Health Potion", 0); } } private void ShowSpellSelection() { if (spellSelectionUI != null) { spellSelectionUI.ShowSpellSelection(currentCharacter); } else { Debug.LogWarning("No SpellSelectionUI found - creating placeholder spell action"); // Placeholder: auto-select a basic spell OnSpellSelected("Magic Missile"); } } private bool DoesItemRequireTarget(string itemName) { // Placeholder logic - determine if item needs a target return itemName.ToLower().Contains("heal") || itemName.ToLower().Contains("buff") || itemName.ToLower().Contains("restore"); } private (bool requiresTarget, bool isAoE, float aoeRadius) GetSpellInfo(string spellName) { // Placeholder spell database switch (spellName.ToLower()) { case "magic missile": return (true, false, 0f); case "heal": return (true, false, 0f); case "fireball": return (true, true, 3f); case "shield": return (false, false, 0f); default: return (true, false, 0f); } } private IEnumerator UseItem(Character user, string itemName, int itemIndex, Character target) { Debug.Log($"๐Ÿ“ฆ Using item {itemName} on {(target ? target.CharacterName : "self")}"); // Placeholder item effects if (itemName.ToLower().Contains("heal")) { Character healTarget = target ?? user; healTarget.Heal(20); // Heal for 20 HP Debug.Log($"๐Ÿ’š {healTarget.CharacterName} healed for 20 HP"); } yield return null; } private IEnumerator CastSpell(Character caster, string spellName, Character target, Vector3 targetPosition) { Debug.Log($"๐Ÿ”ฎ Casting {spellName} from {caster.CharacterName}"); // Placeholder spell effects switch (spellName.ToLower()) { case "magic missile": if (target != null) { target.TakeDamage(15); Debug.Log($"๐Ÿ’ฅ {target.CharacterName} hit by Magic Missile for 15 damage"); } break; case "heal": if (target != null) { target.Heal(25); Debug.Log($"๐Ÿ’š {target.CharacterName} healed for 25 HP"); } break; case "fireball": // AoE damage around target position Debug.Log($"๐Ÿ”ฅ Fireball explodes at {targetPosition}"); break; } yield return null; } private void ApplyDefendBuff(Character character) { // Placeholder: apply defensive buff Debug.Log($"๐Ÿ›ก๏ธ {character.CharacterName} gains defensive stance"); // TODO: Implement actual defensive bonuses } private IEnumerator HandleRunAway(Character character) { // Placeholder: move character away from combat Vector3 runDirection = -character.transform.forward; Vector3 runTarget = character.transform.position + runDirection * 5f; character.transform.position = runTarget; Debug.Log($"๐Ÿƒ {character.CharacterName} retreats to {runTarget}"); yield return null; } #endregion }