146 lines
3.8 KiB
C#
146 lines
3.8 KiB
C#
using DemonBoss.AI;
|
|
using Invector.vCharacterController.AI.FSMBehaviour;
|
|
using UnityEngine;
|
|
using UnityEngine.Animations;
|
|
using UnityEngine.Playables;
|
|
|
|
namespace DemonBoss.Summoner
|
|
{
|
|
/// <summary>
|
|
/// FSM Action: cast a single fireball with optional overlay clip
|
|
/// </summary>
|
|
[CreateAssetMenu(menuName = "Invector/FSM/Actions/Summoner/Cast Fireball")]
|
|
public class SA_CastFireball : vStateAction
|
|
{
|
|
public override string categoryName => "Summoner";
|
|
public override string defaultName => "Cast Fireball";
|
|
|
|
[Header("Timing")]
|
|
[Tooltip("Optional delay before the fireball is spawned")]
|
|
public float castDelay = 0f;
|
|
|
|
[Header("One-off Overlay Clip (No Animator Params)")]
|
|
public AnimationClip overlayClip;
|
|
|
|
[Tooltip("Playback speed (1 = normal)")]
|
|
public float overlaySpeed = 1f;
|
|
|
|
[Tooltip("Blend-in seconds (instant in this minimal impl)")]
|
|
public float overlayFadeIn = 0.10f;
|
|
|
|
[Tooltip("Blend-out seconds (instant in this minimal impl)")]
|
|
public float overlayFadeOut = 0.10f;
|
|
|
|
[Header("Debug")]
|
|
public bool enableDebug = false;
|
|
|
|
private SummonerAI _summoner;
|
|
private bool _castScheduled;
|
|
|
|
// --- Playables runtime ---
|
|
private PlayableGraph _overlayGraph;
|
|
private AnimationPlayableOutput _overlayOutput;
|
|
private AnimationClipPlayable _overlayPlayable;
|
|
private bool _overlayPlaying;
|
|
private float _overlayStopAtTime;
|
|
|
|
public override void DoAction(vIFSMBehaviourController fsm, vFSMComponentExecutionType execType = vFSMComponentExecutionType.OnStateUpdate)
|
|
{
|
|
if (execType == vFSMComponentExecutionType.OnStateEnter)
|
|
{
|
|
OnEnter(fsm);
|
|
}
|
|
else if (execType == vFSMComponentExecutionType.OnStateUpdate)
|
|
{
|
|
if (_overlayPlaying && Time.time >= _overlayStopAtTime)
|
|
{
|
|
StopOverlayWithFade();
|
|
}
|
|
}
|
|
else if (execType == vFSMComponentExecutionType.OnStateExit)
|
|
{
|
|
OnExit();
|
|
}
|
|
}
|
|
|
|
private void OnEnter(vIFSMBehaviourController fsm)
|
|
{
|
|
_summoner = fsm.gameObject.GetComponent<SummonerAI>();
|
|
if (_summoner == null)
|
|
{
|
|
if (enableDebug) Debug.LogWarning("[SA_CastFireball] No SummonerAI component found!");
|
|
return;
|
|
}
|
|
|
|
_castScheduled = false;
|
|
|
|
// Play overlay clip (no Animator params)
|
|
PlayOverlayOnce(fsm.transform);
|
|
|
|
if (castDelay > 0f)
|
|
{
|
|
fsm.gameObject.AddComponent<DelayedInvoker>().Init(castDelay, SpawnFireballNow);
|
|
_castScheduled = true;
|
|
}
|
|
else
|
|
{
|
|
SpawnFireballNow();
|
|
}
|
|
}
|
|
|
|
private void OnExit()
|
|
{
|
|
StopOverlayImmediate();
|
|
_castScheduled = false;
|
|
}
|
|
|
|
private void SpawnFireballNow()
|
|
{
|
|
if (_summoner == null) return;
|
|
_summoner.CastFireball();
|
|
if (enableDebug) Debug.Log("[SA_CastFireball] Fireball cast");
|
|
}
|
|
|
|
// ------------------ Overlay helpers ------------------
|
|
|
|
private void PlayOverlayOnce(Transform owner)
|
|
{
|
|
if (overlayClip == null || owner == null) return;
|
|
|
|
Animator anim = owner.GetComponent<Animator>();
|
|
if (anim == null) return;
|
|
|
|
_overlayGraph = PlayableGraph.Create("ActionOverlay(CastFireball)");
|
|
_overlayGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
|
|
|
|
_overlayPlayable = AnimationClipPlayable.Create(_overlayGraph, overlayClip);
|
|
_overlayPlayable.SetSpeed(Mathf.Max(0.0001f, overlaySpeed));
|
|
_overlayPlayable.SetApplyFootIK(false);
|
|
_overlayPlayable.SetApplyPlayableIK(false);
|
|
|
|
_overlayOutput = AnimationPlayableOutput.Create(_overlayGraph, "AnimOut", anim);
|
|
_overlayOutput.SetSourcePlayable(_overlayPlayable);
|
|
_overlayOutput.SetWeight(1f);
|
|
|
|
_overlayGraph.Play();
|
|
|
|
float duration = (float)overlayClip.length / Mathf.Max(0.0001f, overlaySpeed);
|
|
_overlayStopAtTime = Time.time + duration;
|
|
_overlayPlaying = true;
|
|
}
|
|
|
|
private void StopOverlayWithFade()
|
|
{
|
|
StopOverlayImmediate();
|
|
}
|
|
|
|
private void StopOverlayImmediate()
|
|
{
|
|
if (!_overlayGraph.IsValid()) return;
|
|
_overlayGraph.Stop();
|
|
_overlayGraph.Destroy();
|
|
_overlayPlaying = false;
|
|
}
|
|
}
|
|
}
|