using Cirno.Scripts.Components.Actors; using Cirno.Scripts.Enums; using Godot; namespace Cirno.Scripts.Components.FSM.Enemy; public partial class Alert : EnemyStateBase { public override EnemyState StateId => EnemyState.Alert; [Export] public EnemyStorageModule StorageModule { get; private set; } [Export] public PlayerDetectionModule PlayerDetection { get; private set; } [Export] public GenericDamageReceiver DamageReceiver { get; private set; } [Export] public NavigationMovementModule NavigationModule { get; private set; } private bool _isPlayerInRange = false; public override void EnterState() { base.EnterState(); GD.Print($"Entered {Name}"); NavigationModule.Init(MainObject); PlayerDetection.SetRange(StorageModule.Root.EnemyResource.PlayerDetectionRange); //_isPlayerInRange = PlayerDetection.IsPlayerInRange(StorageModule.Root.EnemyResource.ViewRange); //GD.Print($"Player In Range: {_isPlayerInRange}"); PlayerDetection.PlayerInRange += PlayerDetectionOnPlayerInRange; PlayerDetection.PlayerOutOfRange += PlayerDetectionOnPlayerOutOfRange; DamageReceiver.ChangeState(true); DamageReceiver.HealthProvider.ResourceDepleted += HealthProviderOnResourceDepleted; } private void HealthProviderOnResourceDepleted() { ChangeState(EnemyState.Dead); } private void PlayerDetectionOnPlayerOutOfRange() { _isPlayerInRange = false; GD.Print("Player out of range"); } public override void ExitState() { base.ExitState(); GD.Print($"Exited {Name}"); PlayerDetection.PlayerInRange -= PlayerDetectionOnPlayerInRange; PlayerDetection.PlayerOutOfRange -= PlayerDetectionOnPlayerOutOfRange; DamageReceiver.HealthProvider.ResourceDepleted -= HealthProviderOnResourceDepleted; DamageReceiver.ChangeState(false); NavigationModule.SetTarget(null); } private void PlayerDetectionOnPlayerInRange() { //_isPlayerInRange = true; GD.Print("Player In Range"); } public override void PhysicsProcessState(double delta) { base.PhysicsProcessState(delta); if (PlayerDetection.IsPlayerInRange(StorageModule.Root.EnemyResource.ViewRange) && PlayerDetection.IsPlayerInSight()) { GD.Print("Player is in sight, shooting"); StateMachine.SetState(EnemyState.Shooting); return; } // if player is outside disengage range, change to idle (later on, search) if (this.GlobalPosition.DistanceTo(GameManager.Instance.PlayerPosition.Value) >= StorageModule.Root.EnemyResource.PlayerDisengageRange) { GD.Print("Player is out of sight, idling"); StateMachine.SetState(EnemyState.Idle); return; } // Move towards last known position if (PlayerDetection.LastKnownPlayerPosition.HasValue) { MoveTowardsPosition(PlayerDetection.LastKnownPlayerPosition.Value); } NavigationModule.Move(); StorageModule.FacingDirection = MainObject.Velocity.SnapToCardinal().Normalized(); } private void MoveTowardsPosition(Vector2 position) { NavigationModule.SetTarget(position); } public override void ProcessState(double delta) { base.ProcessState(delta); } }