using System.Collections; using System.Collections.Generic; using System.Linq; using Unity.BossRoom.Gameplay.GameplayObjects.Character; using Unity.Netcode; using UnityEngine; public class AbilitySystem : NetworkBehaviour { [Header("Assigned Abilities")] public List abilities = new List(); private Ability activeAbility; private bool isAbilityActive = false; private HashSet abilitiesOnCooldown = new HashSet(); [SerializeField] private GameObject currentAbilityIndicator; [SerializeField] private GameObject wallIndicator; // Separate indicator for the wall void Update() { if (isAbilityActive) { if (activeAbility.abilityKey == "VectorFence") { // Use wallIndicator for VectorFence if (!wallIndicator.activeSelf) { wallIndicator.SetActive(true); currentAbilityIndicator.SetActive(false); } if (Input.GetMouseButtonDown(0)) { // Save the spawn position for the wall Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out RaycastHit hit)) { wallIndicator.transform.position = hit.point; // wallIndicator.transform.rotation = Quaternion.identity; // Reset rotation wallIndicator.transform.localScale = new Vector3(((VectorFenceAbility) activeAbility).wallLength, ((VectorFenceAbility) activeAbility).wallHeight, ((VectorFenceAbility) activeAbility).wallWidth); } } if (Input.GetMouseButton(0)) { // Rotate the wall using Mouse X for Y-axis rotation float mouseX = Input.GetAxis("Mouse X"); wallIndicator.transform.Rotate(Vector3.up, mouseX); // Adjust rotation speed if needed } if (Input.GetMouseButtonUp(0)) { // Place the wall at the saved position and rotation UseActiveAbility(); } } else { // Use currentAbilityIndicator for all other abilities if (!currentAbilityIndicator.activeSelf) { currentAbilityIndicator.SetActive(true); wallIndicator.SetActive(false); } UpdateIndicatorPosition(); if (Input.GetMouseButtonDown(0)) { UseActiveAbility(); } } } else { // Deactivate both indicators when ability mode is inactive currentAbilityIndicator.SetActive(false); wallIndicator.SetActive(false); } } private void UpdateIndicatorForVectorFence(Vector3 center, Vector3 direction, float length) { if (wallIndicator != null) { wallIndicator.transform.position = center; wallIndicator.transform.rotation = Quaternion.LookRotation(direction); wallIndicator.transform.localScale = new Vector3(length, 1, 0.2f); // Adjust wall width & height } } public void ActivateAbilityByKey(string key) { foreach (var ability in abilities) { if (ability.abilityKey == key) { if (!abilitiesOnCooldown.Contains(ability)) { ToggleAbilityMode(ability); } else { Debug.Log($"{ability.abilityName} is on cooldown."); } return; } } Debug.LogWarning($"No ability assigned to key {key}."); } public bool IsAbilityModeActive() { return isAbilityActive; } private void ToggleAbilityMode(Ability ability) { if (isAbilityActive && activeAbility == ability) { DeactivateAbilityMode(); } else { ActivateAbilityMode(ability); } } private void ActivateAbilityMode(Ability ability) { isAbilityActive = true; activeAbility = ability; Debug.Log($"Ability {ability.abilityName} activated! Click to use."); } private void DeactivateAbilityMode() { isAbilityActive = false; activeAbility = null; Debug.Log("Ability mode deactivated."); } public void UseActiveAbility() { if (activeAbility != null) { Debug.Log($"[AbilitySystem] Using active ability {activeAbility.abilityName}."); Vector3 targetPosition; Vector3 targetRotation; if (activeAbility.abilityKey == "VectorFence") { targetPosition = wallIndicator.transform.position; targetRotation = wallIndicator.transform.eulerAngles; } else { targetPosition = currentAbilityIndicator.transform.position; targetRotation = currentAbilityIndicator.transform.eulerAngles; // Optional, depending on other abilities } RequestAbilityActivationServerRpc(activeAbility.abilityKey, targetPosition, targetRotation); StartCoroutine(StartCooldown(activeAbility)); DeactivateAbilityMode(); } else { Debug.LogWarning("[AbilitySystem] No active ability to use."); } } [ServerRpc(RequireOwnership = false)] private void RequestAbilityActivationServerRpc(string abilityKey, Vector3 targetPosition, Vector3 targetRotation, ServerRpcParams rpcParams = default) { ulong ownerClientId = rpcParams.Receive.SenderClientId; Debug.Log($"[AbilitySystem] Received activation request for ability '{abilityKey}' from client {ownerClientId} at position {targetPosition} with rotation {targetRotation}."); ExecuteAbilityOnServer(abilityKey, ownerClientId, targetPosition, targetRotation); } private void ExecuteAbilityOnServer(string abilityKey, ulong ownerClientId, Vector3 targetPosition, Vector3 targetRotation) { // Find the player's ServerCharacter var playerObject = NetworkManager.Singleton.SpawnManager.SpawnedObjectsList .FirstOrDefault(obj => obj.OwnerClientId == ownerClientId && obj.GetComponent()); if (playerObject == null || !playerObject.TryGetComponent(out ServerCharacter character)) { Debug.LogError($"[AbilitySystem] No ServerCharacter component found for player {ownerClientId}."); return; } // Find the ability var ability = abilities.Find(a => a.abilityKey == abilityKey); if (ability == null) { Debug.LogError($"[AbilitySystem] Ability {abilityKey} not found in the Ability System."); return; } // Activate the ability Debug.Log($"[AbilitySystem] Activating ability {ability.abilityName} for player {ownerClientId} at {targetPosition} with rotation {targetRotation}."); ability.Execute(character, targetPosition, targetRotation); } private IEnumerator StartCooldown(Ability ability) { abilitiesOnCooldown.Add(ability); Debug.Log($"{ability.abilityName} is now on cooldown for {ability.abilityCooldownTime} seconds."); yield return new WaitForSeconds(ability.abilityCooldownTime); abilitiesOnCooldown.Remove(ability); Debug.Log($"{ability.abilityName} is off cooldown."); } private void UpdateIndicatorPosition() { // Raycast to get the position of the cursor on the ground Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out RaycastHit hit)) { if (currentAbilityIndicator != null) { currentAbilityIndicator.transform.position = hit.point; currentAbilityIndicator.transform.localScale = Vector3.one * activeAbility.abilityRadius; } } } }