using System.Collections.Generic; using System.Linq; using Cirno.Scripts.Actors; using Cirno.Scripts.Components.Actors; using Cirno.Scripts.Controllers; using Godot; namespace Cirno.Scripts.Components.FSM.Player; public partial class FreezeModule : ModuleBase { [Export] public float ResourceCost { get; private set; } = 15f; [Export] public float FreezeRadius { get; private set; } = 64f; [Export] public double Cooldown { get; private set; } = 0.5f; [Export] public double IceLife { get; private set; } = 4f; [Export] public PackedScene IceScene { get; private set; } [ExportGroup("Providers")] [Export] public ActorResourceProvider Shield { get; private set; } [Export] public InputProvider InputProvider { get; private set; } public bool Enabled { get; set; } = false; private double _cooldownTimer = 0; private IStateMachine _machine; public override void EnterState(PlayerState state) { Enabled = true; } public override void ExitState(PlayerState state) { Enabled = false; } public override void Init(IStateMachine machine) { _machine = machine; } public override void Process(double delta) { if (!Enabled) return; // TODO: Handle cooldown } public override void PhysicsProcess(double delta) { if (!Enabled) return; if (InputProvider.GetFreezeJustPressed()) { if (Shield.CurrentResource >= ResourceCost) { Shield.CurrentResource -= ResourceCost; FreezeBullets(); } } } private void FreezeBullets() { var bullets = GetNearbyBullets(); foreach (var bullet in bullets) { bullet.Freeze(); var ice = bullet.CreateSibling(IceScene); ice.Life = IceLife; ice.FreezeModule = this; } } private List GetNearbyBullets() { return (from child in PoolingManager.Instance.GetAllActiveBullets() where child is not null where child.Enabled // Could be redundant but better check in case of errors where child.BulletOwner is not BulletOwner.Player where !child.IsFrozen where child.BulletInfo.Freezable let distance = _machine.MainObject.GlobalPosition.DistanceTo(child.GlobalPosition) where distance <= FreezeRadius select child).ToList(); } }