105 lines
3.2 KiB
C#
105 lines
3.2 KiB
C#
using Invector.vCharacterController.AI.FSMBehaviour;
|
||
using Lean.Pool;
|
||
using UnityEngine;
|
||
|
||
namespace DemonBoss.Magic
|
||
{
|
||
/// <summary>
|
||
/// Spawns a meteor behind the BOSS and launches it toward the player's position
|
||
/// Similar mechanics to FireballProjectile but coming from above
|
||
/// </summary>
|
||
[CreateAssetMenu(menuName = "Invector/FSM/Actions/DemonBoss/Call Meteor")]
|
||
public class SA_CallMeteor : vStateAction
|
||
{
|
||
public override string categoryName => "DemonBoss/Magic";
|
||
public override string defaultName => "Call Meteor";
|
||
|
||
[Header("Meteor Setup")]
|
||
[Tooltip("Prefab with MeteorProjectile component")]
|
||
public GameObject meteorPrefab;
|
||
|
||
[Tooltip("Distance behind the BOSS to spawn meteor (meters)")]
|
||
public float behindBossDistance = 3f;
|
||
|
||
[Tooltip("Height above the BOSS to spawn meteor (meters)")]
|
||
public float aboveBossHeight = 8f;
|
||
|
||
[Tooltip("Delay before meteor spawns (wind-up)")]
|
||
public float castDelay = 0.4f;
|
||
|
||
[Header("Targeting")]
|
||
[Tooltip("Tag used to find the target (usually Player)")]
|
||
public string targetTag = "Player";
|
||
|
||
[Header("Debug")]
|
||
public bool enableDebug = false;
|
||
|
||
private Transform _boss;
|
||
private Transform _target;
|
||
|
||
public override void DoAction(vIFSMBehaviourController fsm, vFSMComponentExecutionType execType = vFSMComponentExecutionType.OnStateUpdate)
|
||
{
|
||
if (execType == vFSMComponentExecutionType.OnStateEnter)
|
||
{
|
||
OnEnter(fsm);
|
||
}
|
||
}
|
||
|
||
private void OnEnter(vIFSMBehaviourController fsm)
|
||
{
|
||
_boss = fsm.transform;
|
||
_target = GameObject.FindGameObjectWithTag(targetTag)?.transform;
|
||
|
||
if (_target == null)
|
||
{
|
||
if (enableDebug) Debug.LogWarning("[SA_CallMeteor] No target found – abort");
|
||
return;
|
||
}
|
||
|
||
if (enableDebug) Debug.Log($"[SA_CallMeteor] Boss: {_boss.name}, Target: {_target.name}");
|
||
|
||
SpawnMeteor();
|
||
}
|
||
|
||
private void SpawnMeteor()
|
||
{
|
||
if (meteorPrefab == null)
|
||
{
|
||
if (enableDebug) Debug.LogError("[SA_CallMeteor] Missing meteorPrefab");
|
||
return;
|
||
}
|
||
|
||
if (_boss == null || _target == null)
|
||
{
|
||
if (enableDebug) Debug.LogError("[SA_CallMeteor] Missing boss or target reference");
|
||
return;
|
||
}
|
||
|
||
// Calculate spawn position: behind the BOSS + height
|
||
Vector3 bossForward = _boss.forward.normalized;
|
||
Vector3 behindBoss = _boss.position - (bossForward * behindBossDistance);
|
||
Vector3 spawnPos = behindBoss + Vector3.up * aboveBossHeight;
|
||
|
||
if (enableDebug) Debug.Log($"[SA_CallMeteor] Spawning meteor at: {spawnPos}");
|
||
|
||
// Spawn the meteor
|
||
var meteorGO = LeanPool.Spawn(meteorPrefab, spawnPos, Quaternion.identity);
|
||
|
||
// Configure the projectile to target the player
|
||
var meteorScript = meteorGO.GetComponent<MeteorProjectile>();
|
||
if (meteorScript != null)
|
||
{
|
||
// Set it to target the player's current position
|
||
meteorScript.useOverrideImpactPoint = true;
|
||
meteorScript.overrideImpactPoint = _target.position;
|
||
meteorScript.snapImpactToGround = true;
|
||
|
||
if (enableDebug) Debug.Log($"[SA_CallMeteor] Meteor configured to target: {_target.position}");
|
||
}
|
||
else
|
||
{
|
||
if (enableDebug) Debug.LogError("[SA_CallMeteor] Meteor prefab missing MeteorProjectile component!");
|
||
}
|
||
}
|
||
}
|
||
} |