using Cirno.Scripts.Components.Actors; using Cirno.Scripts.Enums; using Godot; namespace Cirno.Scripts.Components.FSM.Enemy; public partial class Controlled : EnemyStateBase { public override EnemyState StateId => EnemyState.Controlled; private EnemyStorageModule StorageModule { get; set; } private GenericDamageReceiver DamageReceiver { get; set; } [Export] private InputProvider _inputProvider; private PlayerCrosshairProvider CrosshairProvider { get; set; } [Export] public Weapon EquippedWeapon { get; private set; } [Export] public StringName ControlEndAction { get; private set; } = "pause"; [Export] public StringName ShootAction { get; private set; } = "shoot"; private bool _isStrafing = false; public override void Init(IStateMachine machine) { base.Init(machine); StorageModule ??= StateMachine.GetModule(); DamageReceiver ??= StateMachine.GetModule(); CrosshairProvider ??= StateMachine.GetModule(); } public override void EnterState() { base.EnterState(); GD.Print($"{StorageModule.Root.Name} Controlled"); DamageReceiver.ChangeState(true); DamageReceiver.HealthProvider.ResourceDepleted += HealthProviderOnResourceDepleted; GameManager.Instance.CameraTargetObject(MainObject); GameManager.Instance.Player.SetState(PlayerState.Controlling); DamageReceiver.BulletGroup = BulletOwner.Player; _isStrafing = false; CrosshairProvider.Visible = true; // Show possession sprite } private void HealthProviderOnResourceDepleted() { ChangeState(EnemyState.Dead); } public override void ExitState() { base.ExitState(); DamageReceiver.HealthProvider.ResourceDepleted -= HealthProviderOnResourceDepleted; DamageReceiver.ChangeState(false); GameManager.Instance.CameraTargetPlayer(); GameManager.Instance.Player.SetState(PlayerState.Active); DamageReceiver.BulletGroup = BulletOwner.Enemy; CrosshairProvider.Visible = false; // Hide possession sprite } public override void PhysicsProcessState(double delta) { base.PhysicsProcessState(delta); if (_inputProvider.GetShootPressed()) { Shoot(); } if (Input.IsActionJustPressed(ControlEndAction)) { StateMachine.SetState(EnemyState.Idle); } HandlePhysics(delta); StorageModule.FacingDirection = MainObject.Velocity.SnapToCardinal().Normalized(); } private void HandlePhysics(double delta) { StorageModule.MovementDirection = _inputProvider.GetMovementInput().Normalized(); _isStrafing = _inputProvider.GetStrafePressed(); var rightStickInput = _inputProvider.GetAimInput().Normalized(); if (rightStickInput.Length() > 0.1f) // If the right stick is moved { StorageModule.AimingDirection = rightStickInput; } else if (StorageModule.MovementDirection != Vector2.Zero) // Fall back to movement direction { StorageModule.AimingDirection = StorageModule.MovementDirection; } // Update crosshair CrosshairProvider.UpdatePosition(StorageModule.AimingDirection); MainObject.Velocity = StorageModule.MovementDirection * StorageModule.MovementSpeed; MainObject.MoveAndSlide(); } private void Shoot() { if (EquippedWeapon == null) return; var direction = StorageModule.AimingDirection; // Shoot at the player's last known position EquippedWeapon.ShootDirection = direction; //StorageModule.FacingDirection = direction.SnapToCardinal().Normalized(); EquippedWeapon.Shoot(BulletOwner.Player); } public override void ProcessState(double delta) { base.ProcessState(delta); } }