| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672 |
- using UnityEngine;
- using System.Collections.Generic;
- using System.Collections;
- /// <summary>
- /// Manages the execution of battle actions and coordinates with existing systems
- /// </summary>
- 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<Character> OnActionCompleted;
- public event System.Action<Character, BattleActionType> OnActionStarted;
- void Awake()
- {
- mainCamera = Camera.main;
- // Find or create action wheel
- if (actionWheel == null)
- actionWheel = FindFirstObjectByType<BattleActionWheel>();
- }
- 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();
- }
- }
- /// <summary>
- /// Shows the action wheel for a character
- /// </summary>
- 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!");
- }
- }
- /// <summary>
- /// Hides the action wheel
- /// </summary>
- public void HideActionWheel()
- {
- if (actionWheel != null)
- {
- actionWheel.HideWheel();
- }
- }
- /// <summary>
- /// Executes the character's selected action
- /// </summary>
- public void ExecuteCharacterAction(Character character)
- {
- if (character == null)
- {
- Debug.LogWarning("BattleActionSystem: Invalid character");
- return;
- }
- var actionData = character.GetEnhancedActionData<EnhancedCharacterActionData>();
- 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;
- }
- 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)
- {
- // 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;
- }
- // Use existing attack system
- Character targetCharacter = actionData.targetEnemy.GetComponent<Character>();
- if (targetCharacter != null)
- {
- character.AttackTarget(targetCharacter);
- }
- yield return new WaitForSeconds(1f); // Attack animation time
- }
- private IEnumerator ExecuteItemAction(Character character, EnhancedCharacterActionData actionData)
- {
- // 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)
- {
- // 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)
- {
- // Apply defend buff (reduce incoming damage, increase AC, etc.)
- ApplyDefendBuff(character);
- yield return new WaitForSeconds(0.3f);
- }
- private IEnumerator ExecuteWaitAction(Character character, EnhancedCharacterActionData actionData)
- {
- // Character does nothing but maintains position
- yield return new WaitForSeconds(0.1f);
- }
- private IEnumerator ExecuteRunAwayAction(Character character, EnhancedCharacterActionData actionData)
- {
- // 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;
- // Initialize enhanced action data if needed
- var actionData = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
- 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<EnhancedCharacterActionData>();
- 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<EnhancedCharacterActionData>();
- 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()
- {
- pendingAction = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
- isWaitingForTarget = true;
- // Show move cursor or indicators
- }
- private void StartTargetSelectionForAttack()
- {
- pendingAction = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
- isWaitingForTarget = true;
- // Show attack cursor or highlight enemies
- }
- private void StartTargetSelectionForItem()
- {
- pendingAction = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
- isWaitingForTarget = true;
- }
- private void StartTargetSelectionForSpell()
- {
- pendingAction = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
- 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<Character>();
- 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<EnhancedCharacterActionData>();
- }
- }
- private void CancelActionSelection()
- {
- isWaitingForTarget = false;
- pendingAction = null;
- if (currentCharacter != null)
- {
- var actionData = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
- if (actionData != null)
- actionData.Reset();
- currentCharacter.SetVisualState(ActionDecisionState.NoAction);
- }
- 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)
- {
- // Try to find and use the actual item from inventory
- bool itemConsumed = false;
- var inventory = user.GetComponent<Inventory>();
- if (inventory != null)
- {
- // Try to find the item in the inventory
- var miscItems = inventory.Miscellaneous;
- foreach (var slot in miscItems)
- {
- if (slot.item != null && slot.item.itemName == itemName && slot.quantity > 0)
- {
- if (slot.item is MiscellaneousItem miscItem && miscItem.isConsumable)
- {
- // Use the item effect
- Character effectTarget = target ?? user;
- miscItem.UseItem(effectTarget);
- // Remove one from inventory
- inventory.RemoveItem(slot.item, 1);
- itemConsumed = true;
- break;
- }
- }
- }
- }
- // If no ScriptableObject item found, try CombatDataTransfer session data
- if (!itemConsumed && CombatDataTransfer.HasValidSession())
- {
- var session = CombatDataTransfer.GetCurrentSession();
- var playerData = session.playerTeam.Find(p =>
- p.characterName == user.CharacterName ||
- user.CharacterName.StartsWith(p.characterName));
- if (playerData != null && playerData.miscItems != null)
- {
- // Remove item from session data
- for (int i = 0; i < playerData.miscItems.Count; i++)
- {
- if (playerData.miscItems[i] == itemName)
- {
- playerData.miscItems.RemoveAt(i);
- itemConsumed = true;
- // Apply basic effects based on item name
- Character effectTarget = target ?? user;
- ApplyItemEffectByName(itemName, effectTarget);
- break;
- }
- }
- }
- }
- // Fallback - basic effects without consumption
- if (!itemConsumed)
- {
- Debug.LogWarning($"📦 Could not find consumable item {itemName} in {user.CharacterName}'s inventory - applying basic effect");
- Character effectTarget = target ?? user;
- ApplyItemEffectByName(itemName, effectTarget);
- }
- yield return null;
- }
- /// <summary>
- /// Apply item effects based on item name (fallback method)
- /// </summary>
- private void ApplyItemEffectByName(string itemName, Character target)
- {
- string lowerName = itemName.ToLower();
- if (lowerName.Contains("heal") || lowerName.Contains("potion"))
- {
- target.Heal(20); // Standard healing amount
- }
- else if (lowerName.Contains("antidote"))
- {
- // Could add poison removal here if implemented
- target.Heal(5); // Minor healing from antidote
- }
- else if (lowerName.Contains("bread") || lowerName.Contains("food"))
- {
- target.Heal(10); // Minor healing from food
- }
- else
- {
- // Generic beneficial effect
- target.Heal(15);
- }
- }
- private IEnumerator CastSpell(Character caster, string spellName, Character target, Vector3 targetPosition)
- {
- // Placeholder spell effects
- switch (spellName.ToLower())
- {
- case "magic missile":
- if (target != null)
- {
- target.TakeDamage(15);
- }
- break;
- case "heal":
- if (target != null)
- {
- target.Heal(25);
- }
- break;
- case "fireball":
- // AoE damage around target position
- break;
- }
- yield return null;
- }
- private void ApplyDefendBuff(Character character)
- {
- // Placeholder: apply defensive buff
- // 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;
- yield return null;
- }
- #endregion
- }
|