using Cirno.Scripts.Components.Actors; using Cirno.Scripts.Enums; using Cirno.Scripts.Utils; using Godot; namespace Cirno.Scripts.Components.FSM.Enemy.Turret; public partial class TurretShooting : EnemyStateBase { public override EnemyState StateId => EnemyState.Shooting; [Export] public EnemyStorageModule StorageModule { get; private set; } [Export] public PlayerDetectionModule PlayerDetection { get; private set; } [Export] public GenericDamageReceiver DamageReceiver { get; private set; } [Export] public Weapon EquippedWeapon; private bool _isPlayerInRange = false; private double _responseTimer = 0; public override void EnterState() { base.EnterState(); PlayerDetection.PlayerOutOfRange += PlayerDetectionOnPlayerOutOfRange; DamageReceiver.ChangeState(true); DamageReceiver.HealthProvider.ResourceDepleted += HealthProviderOnResourceDepleted; EquippedWeapon.WeaponData = StorageModule.Root.EnemyResource.Weapon; _responseTimer = 0; } private void HealthProviderOnResourceDepleted() { ChangeState(EnemyState.Dead); } private void PlayerDetectionOnPlayerOutOfRange() { StateMachine.SetState(EnemyState.Alert); } public override void ExitState() { base.ExitState(); PlayerDetection.PlayerOutOfRange -= PlayerDetectionOnPlayerOutOfRange; DamageReceiver.HealthProvider.ResourceDepleted -= HealthProviderOnResourceDepleted; DamageReceiver.ChangeState(false); } public override void PhysicsProcessState(double delta) { base.PhysicsProcessState(delta); if (PlayerDetection.IsPlayerInRange(StorageModule.Root.EnemyResource.ViewRange) && PlayerDetection.IsPlayerInSight()) { // SHOOT Shoot(); } else { StateMachine.SetState(EnemyState.Alert); return; } } private Vector2 GetShootDirection() { if (StorageModule.EnemyData.PredictPlayer && PlayerDetection.LastKnowPlayerVelocity.HasValue) { var predictedDirection = MathFunctions.PredictInterceptPosition(MainObject.GlobalPosition, PlayerDetection.LastKnownPlayerPosition.Value, PlayerDetection.LastKnowPlayerVelocity.Value, EquippedWeapon.WeaponData.BulletData.BulletSpeed); if (predictedDirection.HasValue) return (predictedDirection.Value - MainObject.GlobalPosition).Normalized(); } return ( PlayerDetection.LastKnownPlayerPosition.Value - MainObject.GlobalPosition).Normalized(); } private void Shoot() { if (EquippedWeapon == null) return; if (!PlayerDetection.LastKnownPlayerPosition.HasValue) return; var direction = GetShootDirection(); // Shoot at the player's last known position EquippedWeapon.ShootDirection = direction; //StorageModule.FacingDirection = direction; StorageModule.FacingDirection = direction; StorageModule.AimingDirection = direction; EquippedWeapon.Shoot(); } }