using System.Collections.Generic; using Sirenix.OdinInspector; using UnityEngine; using VOID.Generic.Objects.Unit; using VOID.Generic.Objects.Unit.Events; using VOID.Generic.Projectile; using VOID.ScriptableObjects; namespace VOID.Generic.Status.Effect.Positional { [TypeRegistryItem("Jump")] public class JumpEffect : BasicEffect { private enum JumpEffectState { Pre, Waiting, Jump, End } private JumpEffectState _state; private ProjectileObject _projectile; private UnitObject _forUnit; public override void OnApply() { if (forObject is not UnitObject forUnit) return; _forUnit = forUnit; if (_state == JumpEffectState.Pre) { // "PRE" is firing from ability, but this will fire instant effect // Here we will create new status+effect for jump that will handle whole jump var newJumpEffect = new JumpEffect(); newJumpEffect._state = JumpEffectState.Waiting; var newJumpStatus = ScriptableObject.CreateInstance(); newJumpStatus.effects = new List { newJumpEffect }; newJumpStatus.hidden = true; newJumpStatus.permanent = true; _forUnit.statusManager.AddStatus(newJumpStatus, _forUnit, false); } else if (_state == JumpEffectState.Waiting) { // "WAITING" this state is waiting for projectile to fire, after that unit can attach to projectile _forUnit.unitEvents.onAbilityProjectileStart.AddListener(OnProjectileStart); _forUnit.unitEvents.onAbilityProjectileEnd.AddListener(OnProjectileEnd); } } public override void OnEnd() { if (!_forUnit) return; // Just to be sure - remove all listeners after jump is finished _forUnit.basicEvents.onFixedUpdate.RemoveListener(MoveWithProjectile); _forUnit.unitEvents.onAbilityProjectileStart.RemoveListener(OnProjectileStart); _forUnit.unitEvents.onAbilityProjectileEnd.RemoveListener(OnProjectileEnd); } public override void OnTurnSelfEnd() {} public override void OnTurnSelfStart() {} public override void OnCancel() => OnEnd(); public sealed override string GetSimpleDescription() => "Unit jump like a projectile"; private void OnProjectileStart(AbilityProjectileEvent projectileEvent) { // just to be sure that unit stick only to first projectile, if somehow there is more if (projectileEvent.projectileIndex != 0) return; _projectile = projectileEvent.projectile; _state = JumpEffectState.Jump; _forUnit.basicEvents.onFixedUpdate.AddListener(MoveWithProjectile); _forUnit.unitEvents.onAbilityProjectileStart.RemoveListener(OnProjectileStart); } private void OnProjectileEnd(AbilityProjectileEvent projectileEvent) { // just to be sure that unit stick only to first projectile, if somehow there is more if (projectileEvent.projectileIndex != 0) return; _state = JumpEffectState.End; _forUnit.basicEvents.onFixedUpdate.RemoveListener(MoveWithProjectile); _forUnit.unitEvents.onAbilityProjectileEnd.RemoveListener(OnProjectileEnd); // End whole jump status when projectile along with unit end their "jump" forStatus.End(); } private void MoveWithProjectile() { _forUnit.transform.position = _projectile.transform.position; } } }