using Cirno.Scripts.Utils; using Godot; namespace Cirno.Scripts.Components.FSM.Enemy._3D; public partial class NavigationProvider3D : Node { private Vector3? _lastTargetPosition; private CharacterBody3D _characterBody; //private NavigationAgent3D _navigationAgent; [ExportCategory("References")] [Export] public NavigationAgent3D NavigationAgent { get; private set; } [Export] public EnemyStorage3D StorageModule { get; private set; } [ExportCategory("Properties")] [Export] public float ProcessingRate { get; private set; } = 0.1f; private Vector3? _nextPathPosition; public void Init(CharacterBody3D characterBody) { _characterBody = characterBody; if (NavigationAgent is not null) return; // var timer = new Timer(); // this.AddChild(timer); // // timer.Timeout += TimerOnTimeout; // // timer.Start(ProcessingRate); } private void TimerOnTimeout() { if (!_lastTargetPosition.HasValue) { return; } if (NavigationAgent.IsNavigationFinished()) { return; } _nextPathPosition = NavigationAgent.GetNextPathPosition(); } public void SetTarget(Vector3? target) { _lastTargetPosition = target; } public void Move(float movementSpeed) { if (!_lastTargetPosition.HasValue) { return; } NavigationAgent.SetTargetPosition(_lastTargetPosition.Value); var currentAgentPosition = _characterBody.GlobalPosition; if (NavigationAgent.IsNavigationFinished()) { return; } _nextPathPosition = NavigationAgent.GetNextPathPosition(); var newVelocity = !_nextPathPosition.HasValue ? Vector3.Zero : currentAgentPosition.DirectionTo(_nextPathPosition.Value) * movementSpeed; newVelocity += StorageModule.KnockbackVelocity; if (NavigationAgent.AvoidanceEnabled) { NavigationAgent.SetVelocity(newVelocity); } else { _on_navigation_agent_3d_velocity_computed(newVelocity); } } public void _on_navigation_agent_3d_velocity_computed(Vector3 safeVelocity) { if (_characterBody is null) return; _characterBody.Velocity = safeVelocity; if (_characterBody.Velocity.Length() > 0) { StorageModule.FacingDirection = _characterBody.Velocity.Normalized().ToVector2(); } } public bool IsNavigable(Vector3 newPos) { NavigationAgent.SetTargetPosition(newPos); return NavigationAgent.IsTargetReachable(); } public bool IsNavigationFinished() { return NavigationAgent.IsNavigationFinished(); } }