|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using Unity.Netcode;
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
public class AbilitySystem : NetworkBehaviour
|
|
|
|
{
|
|
|
|
[Header("Assigned Abilities")]
|
|
|
|
public List<Ability> abilities = new List<Ability>();
|
|
|
|
|
|
|
|
private Ability activeAbility; // Tracks the currently active ability in "spawn mode"
|
|
|
|
private bool isAbilityActive = false;
|
|
|
|
|
|
|
|
private HashSet<Ability> abilitiesOnCooldown = new HashSet<Ability>();
|
|
|
|
[SerializeField] private GameObject currentAbilityIndicator;
|
|
|
|
|
|
|
|
void Update()
|
|
|
|
{
|
|
|
|
if (isAbilityActive)
|
|
|
|
{
|
|
|
|
UpdateIndicatorPosition();
|
|
|
|
|
|
|
|
if (Input.GetMouseButtonDown(0))
|
|
|
|
{
|
|
|
|
UseActiveAbility();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Activates an ability by its keybind.
|
|
|
|
/// </summary>
|
|
|
|
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; // Returns true if an ability mode is currently active
|
|
|
|
}
|
|
|
|
|
|
|
|
private void ToggleAbilityMode(Ability ability)
|
|
|
|
{
|
|
|
|
if (isAbilityActive && activeAbility == ability)
|
|
|
|
{
|
|
|
|
DeactivateAbilityMode();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ActivateAbilityMode(ability);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void ActivateAbilityMode(Ability ability)
|
|
|
|
{
|
|
|
|
isAbilityActive = true;
|
|
|
|
activeAbility = ability;
|
|
|
|
currentAbilityIndicator.SetActive(true);
|
|
|
|
Debug.Log($"Ability {ability.abilityName} activated! Click to use.");
|
|
|
|
}
|
|
|
|
|
|
|
|
private void DeactivateAbilityMode()
|
|
|
|
{
|
|
|
|
isAbilityActive = false;
|
|
|
|
activeAbility = null;
|
|
|
|
currentAbilityIndicator.SetActive(false);
|
|
|
|
Debug.Log("Ability mode deactivated.");
|
|
|
|
}
|
|
|
|
|
|
|
|
private void UseActiveAbility()
|
|
|
|
{
|
|
|
|
if (activeAbility != null)
|
|
|
|
{
|
|
|
|
var spawnPosition = currentAbilityIndicator.transform.position;
|
|
|
|
SpawnAbilityServerRpc(activeAbility.abilityKey, spawnPosition);
|
|
|
|
StartCoroutine(StartCooldown(activeAbility));
|
|
|
|
DeactivateAbilityMode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Starts the cooldown coroutine for the ability.
|
|
|
|
/// </summary>
|
|
|
|
private IEnumerator StartCooldown(Ability ability)
|
|
|
|
{
|
|
|
|
abilitiesOnCooldown.Add(ability);
|
|
|
|
Debug.Log($"{ability.abilityName} is now on cooldown for {ability.cooldownTime} seconds.");
|
|
|
|
|
|
|
|
yield return new WaitForSeconds(ability.cooldownTime);
|
|
|
|
|
|
|
|
abilitiesOnCooldown.Remove(ability);
|
|
|
|
Debug.Log($"{ability.abilityName} is off cooldown.");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Spawns the requested ability on the server.
|
|
|
|
/// </summary>
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
|
|
private void SpawnAbilityServerRpc(string abilityKey, Vector3 position, ServerRpcParams rpcParams = default)
|
|
|
|
{
|
|
|
|
var ability = abilities.Find(a => a.abilityKey == abilityKey);
|
|
|
|
if (ability == null)
|
|
|
|
{
|
|
|
|
Debug.LogError($"Ability {abilityKey} not found in the Ability System!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var prefab = ability.GetPrefab(); // Ensure your Ability class has a method to get the prefab
|
|
|
|
if (prefab == null)
|
|
|
|
{
|
|
|
|
Debug.LogError($"Prefab for Ability {abilityKey} is not assigned!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
GameObject abilityInstance = Instantiate(prefab, position, Quaternion.identity);
|
|
|
|
var networkObject = abilityInstance.GetComponent<NetworkObject>();
|
|
|
|
|
|
|
|
if (networkObject != null)
|
|
|
|
{
|
|
|
|
networkObject.Spawn();
|
|
|
|
Debug.Log($"Spawned {abilityKey} at {position}.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Debug.LogError($"Ability prefab {abilityKey} must have a NetworkObject component.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
currentAbilityIndicator.transform.position = hit.point;
|
|
|
|
currentAbilityIndicator.transform.localScale = Vector3.one * activeAbility.abilityRadius;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|