Files
beyond/Assets/AI/Demon/SA_CastShield.cs
2025-08-11 13:34:13 +02:00

185 lines
5.1 KiB
C#

using Invector.vCharacterController.AI.FSMBehaviour;
using Lean.Pool;
using UnityEngine;
namespace DemonBoss.Magic
{
/// <summary>
/// StateAction for Magic Shield spell - boss casts magical shield for 5 seconds
/// During casting boss stands still, after completion returns to Combat
/// </summary>
[CreateAssetMenu(menuName = "Invector/FSM/Decisions/DemonBoss/Cast Shield")]
public class SA_CastShield : vStateAction
{
public override string categoryName => "DemonBoss/Magic";
public override string defaultName => "Cast Shield";
[Header("Shield Configuration")]
[Tooltip("Prefab with magical shield particle effect")]
public GameObject shieldFXPrefab;
[Tooltip("Transform where shield should appear (usually boss center)")]
public Transform shieldSpawnPoint;
[Tooltip("Shield duration in seconds")]
public float shieldDuration = 5f;
[Tooltip("Animator trigger name for shield casting animation")]
public string animatorTrigger = "CastShield";
[Header("Debug")]
[Tooltip("Enable debug logging")]
public bool enableDebug = false;
private GameObject spawnedShield;
private float shieldStartTime;
private bool shieldActive = false;
/// <summary>
/// Main action execution method called by FSM
/// </summary>
public override void DoAction(vIFSMBehaviourController fsmBehaviour, vFSMComponentExecutionType executionType = vFSMComponentExecutionType.OnStateUpdate)
{
if (executionType == vFSMComponentExecutionType.OnStateEnter)
{
OnStateEnter(fsmBehaviour);
}
else if (executionType == vFSMComponentExecutionType.OnStateUpdate)
{
OnStateUpdate(fsmBehaviour);
}
else if (executionType == vFSMComponentExecutionType.OnStateExit)
{
OnStateExit(fsmBehaviour);
}
}
/// <summary>
/// Called when entering state - starts shield casting
/// </summary>
private void OnStateEnter(vIFSMBehaviourController fsmBehaviour)
{
if (enableDebug) Debug.Log("[SA_CastShield] Entering shield casting state");
var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI;
if (aiController != null)
{
aiController.Stop();
if (enableDebug) Debug.Log("[SA_CastShield] AI stopped");
}
var animator = fsmBehaviour.transform.GetComponent<Animator>();
if (animator != null && !string.IsNullOrEmpty(animatorTrigger))
{
animator.SetTrigger(animatorTrigger);
if (enableDebug) Debug.Log($"[SA_CastShield] Set trigger: {animatorTrigger}");
}
SpawnShieldEffect(fsmBehaviour);
shieldStartTime = Time.time;
shieldActive = true;
}
/// <summary>
/// Called every frame during state duration
/// </summary>
private void OnStateUpdate(vIFSMBehaviourController fsmBehaviour)
{
if (shieldActive && Time.time - shieldStartTime >= shieldDuration)
{
if (enableDebug) Debug.Log("[SA_CastShield] Shield time passed, finishing state");
FinishShield(fsmBehaviour);
}
}
/// <summary>
/// Called when exiting state - cleanup
/// </summary>
private void OnStateExit(vIFSMBehaviourController fsmBehaviour)
{
if (enableDebug) Debug.Log("[SA_CastShield] Exiting shield state");
if (shieldActive)
{
CleanupShield();
}
var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI;
if (aiController != null)
{
if (enableDebug) Debug.Log("[SA_CastShield] AI resumed");
}
}
/// <summary>
/// Spawns magical shield particle effect
/// </summary>
private void SpawnShieldEffect(vIFSMBehaviourController fsmBehaviour)
{
if (shieldFXPrefab == null)
{
Debug.LogWarning("[SA_CastShield] Missing shieldFXPrefab!");
return;
}
Vector3 spawnPosition = shieldSpawnPoint != null ?
shieldSpawnPoint.position : fsmBehaviour.transform.position;
spawnedShield = LeanPool.Spawn(shieldFXPrefab, spawnPosition,
shieldSpawnPoint != null ? shieldSpawnPoint.rotation : fsmBehaviour.transform.rotation);
if (enableDebug) Debug.Log($"[SA_CastShield] Shield spawned at position: {spawnPosition}");
if (spawnedShield != null && shieldSpawnPoint != null)
{
spawnedShield.transform.SetParent(shieldSpawnPoint);
}
}
/// <summary>
/// Finishes shield operation and transitions to next state
/// </summary>
private void FinishShield(vIFSMBehaviourController fsmBehaviour)
{
shieldActive = false;
CleanupShield();
DEC_CheckCooldown.SetCooldownStatic(fsmBehaviour, "Shield", 15f);
// End state - FSM will transition to next state
// FYI: In Invector FSM, state completion is handled automatically
}
/// <summary>
/// Cleans up spawned shield
/// </summary>
private void CleanupShield()
{
if (spawnedShield != null)
{
LeanPool.Despawn(spawnedShield);
spawnedShield = null;
if (enableDebug) Debug.Log("[SA_CastShield] Shield despawned");
}
}
/// <summary>
/// Checks if shield is currently active
/// </summary>
public bool IsShieldActive()
{
return shieldActive;
}
/// <summary>
/// Returns remaining shield time
/// </summary>
public float GetRemainingShieldTime()
{
if (!shieldActive) return 0f;
return Mathf.Max(0f, shieldDuration - (Time.time - shieldStartTime));
}
}
}