Files
beyond/Assets/AI/Demon/SA_CastShield.cs
2025-08-25 11:36:50 +02:00

187 lines
5.2 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/Actions/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("Shield duration in seconds")]
public float shieldDuration = 5f;
[Tooltip("Animator bool parameter name for blocking state")]
public string animatorBlockingBool = "IsBlocking";
[Header("Debug")]
[Tooltip("Enable debug logging")]
public bool enableDebug = false;
private GameObject spawnedShield;
private Animator npcAnimator;
private Transform npcTransform;
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");
// Store NPC references
npcTransform = fsmBehaviour.transform;
npcAnimator = npcTransform.GetComponent<Animator>();
var aiController = fsmBehaviour as Invector.vCharacterController.AI.vIControlAI;
if (aiController != null)
{
aiController.Stop();
if (enableDebug) Debug.Log("[SA_CastShield] AI stopped");
}
if (npcAnimator != null && !string.IsNullOrEmpty(animatorBlockingBool))
{
npcAnimator.SetBool(animatorBlockingBool, true);
if (enableDebug) Debug.Log($"[SA_CastShield] Set bool: {animatorBlockingBool} = true");
}
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 (npcAnimator != null && !string.IsNullOrEmpty(animatorBlockingBool))
{
npcAnimator.SetBool(animatorBlockingBool, false);
if (enableDebug) Debug.Log($"[SA_CastShield] Set bool: {animatorBlockingBool} = false");
}
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;
}
// Spawn shield at NPC's position and rotation
Vector3 spawnPosition = npcTransform.position;
Quaternion spawnRotation = npcTransform.rotation;
spawnedShield = LeanPool.Spawn(shieldFXPrefab, spawnPosition, spawnRotation);
if (enableDebug) Debug.Log($"[SA_CastShield] Shield spawned at NPC position: {spawnPosition}");
}
/// <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));
}
}
}