using System; using System.Collections.Generic; using System.Linq; using Cirno.Scripts.Actors; using Cirno.Scripts.Components; using Cirno.Scripts.Resources; using Godot; using Godot.Collections; using Array = System.Array; namespace Cirno.Scripts.AttackPatterns; [GlobalClass] public partial class SpiralPattern : AttackPattern { [Export] public BulletResource BulletResource { get; set; } //Export] public PackedScene BulletScene; //[Export] private float _bulletLifeTime = 20f; // Switch to res //[Export] private bool _destroyOnCollision = false; // Switch to res //[Export] private float bulletSpeed = 5f; // Switch to res [Export] public int bulletCount = 16; [Export] public float rotationSpeed = 0f; [Export] public float _rotationOffset = 0f; [Export] public float duration = 5f; [Export] public float spread = 360f; [Export] public float burstInterval = 0.5f; [ExportCategory("Burst")] [Export] public int ShotsPerBurst { get; private set; } = 100; [Export] public float BurstRate { get; private set; } = 0f; //[Export] private BulletOwner owner = BulletOwner.Enemy; // Switch to res //[Export] private DamageType _damageType = DamageType.Neutral; // Switch to res //[Export] private float _bulletDamage = 1f; // Switch to res // [ExportGroup("Modifiers")] [Export] private BulletCreationModifier _modifier; // [ExportGroup("Modifiers")] [Export] private Array _timeModifiers; [ExportCategory("Other")] [Export] public bool _targetPlayer = false; protected virtual BulletInfo MakeBullet(Vector2 position, Vector2 direction, float angleOffset) { var bl = BulletResource.MakeBullet(position, bulletCount, angleOffset); bl.Direction = direction; return bl; // return new BulletInfo() // { // Position = position, // Direction = direction, // LifeTime = _bulletLifeTime, // DestroyOnCollision = _destroyOnCollision, // Speed = bulletSpeed, // Owner = owner, // DamageType = _damageType, // Damage = _bulletDamage, // BulletCount = bulletCount, // Spread = spread, // BulletScene = BulletScene, // RotationOffset = angleOffset, // Modifier = _modifier, // TimeModifiers = _timeModifiers.ToList()// _timeModifiers.Select(x => x.MakeClone()).ToList() // // TimeModifiers = _timeModifiers?.Where(mod => mod != null).ToList() ?? new List() // }; } public override IPatternMachine MakeMachine(Node2D parent) { return new SpiralPatternMachine(this, parent); } public class SpiralPatternMachine(SpiralPattern pattern, Node2D parent) : IPatternMachine { public Node2D Parent => parent; private double timer; private double burstTimer; //private double _burstRateTimer; private BulletSpawner spawner; private ShootStatus _state = ShootStatus.Idle; private int _burstBullets; public void Start() { timer = 0; _burstBullets = pattern.ShotsPerBurst; burstTimer = pattern.burstInterval; // start immediately //_burstRateTimer = pattern.burstInterval; spawner = parent.GetNode("BulletSpawner"); _state = ShootStatus.Shooting; } private void WaitingBurstUpdate(double delta) { timer += delta; burstTimer += delta; if (burstTimer >= pattern.burstInterval) { _state = ShootStatus.Shooting; } } private void WaitingReloadUpdate(double delta) { timer += delta; burstTimer += delta; if (burstTimer >= pattern.BurstRate) { _burstBullets = pattern.ShotsPerBurst; _state = ShootStatus.Shooting; } } private void ShootingUpdate(double delta) { timer += delta; burstTimer = 0; Shoot(); _burstBullets--; if (_burstBullets <= 0) { _state = ShootStatus.WaitingReload; } else { _state = ShootStatus.WaitingBurst; } } public void UpdatePattern(double delta) { switch (_state) { case ShootStatus.Idle: case ShootStatus.Done: return; case ShootStatus.Shooting: ShootingUpdate(delta); break; case ShootStatus.WaitingBurst: WaitingBurstUpdate(delta); break; case ShootStatus.WaitingReload: WaitingReloadUpdate(delta); break; } if (timer >= pattern.duration) { _state = ShootStatus.Done; } // timer += delta; // burstTimer += delta; // //_burstRateTimer += delta; // // if (timer > pattern.duration) // { // return; // } // // if (burstTimer < pattern.burstInterval) return; // // Shoot(); // // // // burstTimer = 0; } private void Shoot() { float angleOffset = pattern._rotationOffset + (float)(pattern.rotationSpeed * timer); Vector2 direction = pattern.BulletResource.Direction; if (pattern._targetPlayer && GameManager.Instance.PlayerPosition.HasValue) { direction = (GameManager.Instance.PlayerPosition.Value - Parent.GlobalPosition).Normalized(); } var bullet = pattern.BulletResource.MakeBullet(Parent.GlobalPosition, pattern.bulletCount, pattern.spread, angleOffset); bullet.Direction = direction; //spawner.SpawnBullet(MakeBullet(Boss.GlobalPosition, direction, angleOffset)); spawner.SpawnBullet(bullet); } public bool IsComplete() { //return timer >= pattern.duration; return _state is ShootStatus.Done; } private enum ShootStatus { Idle, Shooting, WaitingBurst, WaitingReload, Done } } }