using Godot; namespace SupaLidlGame.State.Character; public partial class PlayerMaxLevelState : PlayerState { [Export] public float CastDistance { get; set; } [Export] public double CastTime { get; set; } [Export] public int LevelCost { get; set; } private double _castTimeLeft = 0; private static PackedScene _lightningScene; private GpuParticles2D _particles; static PlayerMaxLevelState() { _lightningScene = GD.Load("res://Entities/Lightning.tscn"); } public override void _Ready() { base._Ready(); _particles = GetNode("%Effects/CastParticles"); } public override IState Enter(IState prevState) { _player.AttackAnimation.Play("cast"); _player.Inventory.Visible = false; _player.Stats.Level.Value -= LevelCost; _castTimeLeft = CastTime; return base.Enter(prevState); } public override void Exit(IState nextState) { _player.Inventory.Visible = true; base.Exit(nextState); } public override CharacterState Process(double delta) { // return to idle when finished if ((_castTimeLeft -= delta) <= 0) { return IdleState; } return base.Process(delta); } public override CharacterState Input(InputEvent @event) { return null; } public void Cast() { Scenes.Map map = Utils.World.Instance.CurrentMap; bool hasSpawned = false; foreach (var node in map.Entities.GetChildren()) { if (node is Characters.Character ch) { if (ch.Faction == Character.Faction) { continue; } if (!ch.IsAlive) { continue; } // check if distance good and spawn lightning var dist = Character.GlobalPosition .DistanceTo(ch.GlobalPosition); if (dist <= CastDistance) { // delay up to 150 milliseconds double delay = GD.Randf() * 0.150; GetTree().CreateTimer(delay).Timeout += () => { SpawnLightning(ch); }; hasSpawned = true; } } } if (hasSpawned) { _player.Camera.Shake(2.0f, 0.5f); // delay to time out // this is a workaround where particles of amount 1 won't render GetTree().CreateTimer(0.1f).Timeout += () => { _particles.Emitting = false; }; _particles.Emitting = true; //_particles.SetDeferred("emitting", false); } } private void SpawnLightning(Characters.Character target) { if (target is null || !IsInstanceValid(target) || !target.IsAlive) { return; } var map = Utils.World.Instance.CurrentMap; var instance = map.SpawnEntity(_lightningScene); instance.Hitbox.Faction = Character.Faction; instance.Hitbox.Inflictor = Character; instance.Weapon = null; instance.GlobalPosition = target.GlobalPosition; } }