using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; using System; using System.Threading.Tasks; using Zennysoft.Game.Abstractions; namespace Zennysoft.Game.Ma; [Meta(typeof(IAutoNode))] public partial class NavigationAgentClient : Node3D, INavigationAgentClient { public override void _Notification(int what) => this.Notify(what); [Node] private NavigationAgent3D NavAgent { get; set; } = default!; [Node] private Timer _patrolTimer { get; set; } = default!; private Vector3 _currentTarget = Vector3.Zero; private Timer _thinkTimer; private bool _canMove = false; public void Setup() { NavAgent.VelocityComputed += NavAgent_VelocityComputed; NavAgent.TargetReached += NavAgent_TargetReached; var rng = new RandomNumberGenerator(); rng.Randomize(); _patrolTimer.Timeout += OnPatrolTimeout; _patrolTimer.WaitTime = rng.RandfRange(7.0f, 15.0f); _thinkTimer = new Timer { WaitTime = 0.4f }; AddChild(_thinkTimer); _thinkTimer.Timeout += NavAgent_TargetReached; _thinkTimer.Start(); } public void Stop() { _patrolTimer.Stop(); _thinkTimer.Stop(); } private void NavAgent_VelocityComputed(Vector3 safeVelocity) { if (!_canMove) return; var enemy = GetOwner() as IEnemy; enemy.Move(safeVelocity); } public void CalculateVelocity(Vector3 currentPosition, bool canMove) { _canMove = canMove; var nextPathPosition = NavAgent.GetNextPathPosition(); var newVelocity = currentPosition.DirectionTo(nextPathPosition) * 2f; NavAgent.Velocity = newVelocity; } public void SetTarget(Vector3 target) => Task.Delay(TimeSpan.FromSeconds(0.4)).ContinueWith(_ => _currentTarget = new Vector3(target.X, -1.75f, target.Z)); public bool IsAvoidanceEnabled => NavAgent.AvoidanceEnabled; private void NavAgent_TargetReached() { NavAgent.TargetPosition = _currentTarget; } private void OnPatrolTimeout() { var rng = new RandomNumberGenerator(); rng.Randomize(); _patrolTimer.WaitTime = rng.RandfRange(5.0f, 10.0f); var enemy = GetOwner() as ICanPatrol; enemy.Patrol(); } }