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 < Ability > abilities = new List < Ability > ( ) ;
private Ability activeAbility ;
private bool isAbilityActive = false ;
private HashSet < Ability > abilitiesOnCooldown = new HashSet < Ability > ( ) ;
[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 < ServerCharacter > ( ) ) ;
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 ;
}
}
}
}