using Cirno.Scripts.Actors; using Cirno.Scripts.AttackPatterns; using Cirno.Scripts.Resources.BulletScripts; using Godot; using Godot.Collections; namespace Cirno.Scripts.Resources; [GlobalClass] [Tool] public partial class BossPhase : Resource { [Export] public string PhaseName = string.Empty; [Export] public int Threshold; [Export] public bool PlayAnimation; [Export] public BulletScript3D BulletScript3D; // Legacy path kept for backwards compatibility with existing phase compositions. // TODO: Migrate compositions to BulletScript3D-first workflows where possible. [Export] public Array Patterns; private int currentPatternIndex = 0; private double patternTimer; private bool _useBulletScript3D; private IPatternMachine _patternMachine; private BulletScript3D.BulletScriptMachine _bulletScriptMachine; public void Start(Node boss) { _useBulletScript3D = BulletScript3D is not null; patternTimer = 0; if (_useBulletScript3D) { _bulletScriptMachine = BulletScript3D.Make(boss); _bulletScriptMachine.Start(); _patternMachine = null; return; } if (Patterns is null || Patterns.Count == 0) { GD.PushWarning($"BossPhase '{PhaseName}' has no legacy Patterns and no BulletScript3D assigned."); _patternMachine = null; return; } currentPatternIndex = 0; _patternMachine = Patterns[currentPatternIndex].MakeMachine(boss); _patternMachine.Start(); } public void UpdatePhase(double delta) { if (_useBulletScript3D) { _bulletScriptMachine?.UpdatePhase(delta); return; } if (_patternMachine is null || Patterns is null || Patterns.Count == 0) { return; } patternTimer += delta; var currentPattern = Patterns[currentPatternIndex]; _patternMachine.UpdatePattern(delta); if (!currentPattern.WaitForCompletion || _patternMachine.IsComplete()) { currentPatternIndex = (currentPatternIndex + 1) % Patterns.Count; var oldParent = _patternMachine.Parent; _patternMachine = Patterns[currentPatternIndex].MakeMachine(oldParent); _patternMachine.Start(); } } }