using Cirno.Scripts.Components.Actors; using Cirno.Scripts.Enums; using Godot; namespace Cirno.Scripts.Components.FSM.Enemy; public partial class TurretAnimationModule : ModuleBase { private IStateMachine _machine; [Export] public PlayerAnimationProvider AnimationProvider { get; set; } [Export] public EnemyStorageModule StorageModule { get; set; } [Export] public ActorResourceProvider HealthProvider { get; set; } [Export] public Vector2 TurretFacingDirection { get; set; } = Vector2.Down; [Export] public float SweepAngle = 90f; // In degrees [Export] public float SweepSpeed = 1f; // Speed of sweeping [Export] public bool Debug = false; // Enable debug lines //[Export] public NodePath SpritePath; private float _currentAngle; private float _sweepDirection = 1f; private float _raycastLength; public override void EnterState(EnemyState state) { //AnimationProvider.SetAnimation(StorageModule.AimingDirection); //AnimationProvider.SetAnimation(Vector2.Zero); if (HealthProvider is not null) { HealthProvider.ResourceDecreased += HealthProviderOnResourceDecreased; } } private void HealthProviderOnResourceDecreased(float oldValue, float newValue, float maxValue) { AnimationProvider?.Blink(); } public override void ExitState(EnemyState state) { //AnimationProvider.SetAnimation(Vector2.Zero); if (HealthProvider is not null) { HealthProvider.ResourceDecreased -= HealthProviderOnResourceDecreased; } } public override void Init(IStateMachine machine) { _machine = machine; } public override void Process(double delta) { if (StorageModule.AimingDirection == Vector2.Zero || TurretFacingDirection == Vector2.Zero) return; // Calculate the angle between the turret's facing direction and the aim direction float angleToTarget = TurretFacingDirection.AngleTo(StorageModule.AimingDirection); // radians // Clamp the angle to within the sweep cone float halfSweepRad = Mathf.DegToRad(SweepAngle / 2f); float clampedAngle = Mathf.Clamp(angleToTarget, -halfSweepRad, halfSweepRad); // Convert to degrees before passing to SweepSprite float clampedAngleDeg = Mathf.RadToDeg(clampedAngle); // Update the sprite based on this clamped angle AnimationProvider.SweepSprite(clampedAngleDeg, SweepAngle); //AnimationProvider.SetAnimation(StorageModule.AimingDirection); } public override void PhysicsProcess(double delta) { } private void Sweep(float delta) { _currentAngle += _sweepDirection * SweepSpeed * delta; // Clamp angle within the sweep range float halfAngle = SweepAngle / 2f; if (_currentAngle > halfAngle || _currentAngle < -halfAngle) { _sweepDirection *= -1f; _currentAngle = Mathf.Clamp(_currentAngle, -halfAngle, halfAngle); } } // private void DrawDebugLine(Vector2 endPoint) // { // // Request the node to redraw // QueueRedraw(); // _debugLineEndPoint = endPoint; // } private void UpdateSpriteDirection() { AnimationProvider.SweepSprite(_currentAngle, SweepAngle); } private Vector2 _debugLineEndPoint; // public override void _Draw() // { // if (Debug) // { // DrawLine(Vector2.Zero, ToLocal(_debugLineEndPoint), Colors.Red, 2); // } // } }