using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; using Zennysoft.Ma.Adapter; namespace Zennysoft.Game.Ma; [Meta(typeof(IAutoNode))] public abstract partial class Enemy2D : Enemy { public override void _Notification(int what) => this.Notify(what); [Node] private Area3D LineOfSight { get; set; } = default!; public override IEnemyModelView EnemyModelView => _enemyModelView; [Node] private EnemyModelView2D _enemyModelView { get; set; } = default!; private Vector3 _previousPosition = Vector3.Zero; public void OnEnterTree() { LineOfSight.BodyEntered += LineOfSight_BodyEntered; } public override void _PhysicsProcess(double delta) { _enemyModelView.SetCurrentDirection(GlobalBasis, -_player.GlobalBasis.Z); } public override void _Process(double delta) { if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer || _enemyLogic.Value is EnemyLogic.State.Patrolling) { var velocity = (GlobalPosition - _previousPosition) / (float)delta; if (velocity.IsZeroApprox()) _enemyLogic.Input(new EnemyLogic.Input.Idle()); else _enemyLogic.Input(new EnemyLogic.Input.Move()); _previousPosition = GlobalPosition; } } protected void PlayerDetector_BodyEntered(Node3D node) { if (node is IPlayer) _enemyLogic.Input(new EnemyLogic.Input.ReachedPlayer()); } protected void PlayerDetector_BodyExited(Node3D node) { if (node is IPlayer) _enemyLogic.Input(new EnemyLogic.Input.Follow()); } protected void OnVelocityComputed(Vector3 safeVelocity) { Velocity = safeVelocity; LookAtTarget(safeVelocity); MoveAndSlide(); } protected void EngagePlayerBehavior_TakeAction() => PerformAction(); protected void EngagePlayerBehavior_AcquireTarget() => LookAt(new Vector3(_player.GlobalPosition.X, GlobalPosition.Y, _player.GlobalPosition.Z), Vector3.Up, true); private void LineOfSight_BodyEntered(Node3D body) { if (body is IPlayer) _enemyLogic.Input(new EnemyLogic.Input.Alert()); } }