185 lines
5.1 KiB
C#
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));
|
|
}
|
|
}
|
|
} |