using Godot; using System; using Movementtests.interfaces; [GlobalClass] public partial class FlyingEnemy : CharacterBody3D, IDamageable, IKillable, IKnockbackable, IDamageMaker { [Export] public Node3D Target { get; set; } [Export] public FlyingEnemyInputs Inputs { get; set; } [Export] public RDamage GetDamageDealt { get; set; } [Export] public RDamageModifier[] DamageModifiers { get; set; } private RayCast3D _groundDistanceRaycast; private Area3D _damageBox; private bool _movingToDesiredHeight = true; private Vector3 _randomDirection; public override void _Ready() { _groundDistanceRaycast = GetNode("GroundDistance"); _groundDistanceRaycast.TargetPosition = new Vector3(0, 0, 0); _damageBox = GetNode("DamageBox"); _damageBox.BodyEntered += OnDamageBoxTriggered; _randomDirection = new Vector3(GD.RandRange(-1, 1), 1, GD.RandRange(-1, 1)).Normalized(); } public override void _PhysicsProcess(double delta) { var spaceState = GetWorld3D().DirectSpaceState; var target = Target.GlobalPosition; var direction = (target - GlobalPosition).Normalized(); Vector3 velocity = Velocity; LookAt(target); // Check if we have a direct line of sight to the player if (!_movingToDesiredHeight) { velocity = direction * Inputs.Speed; var query = PhysicsRayQueryParameters3D.Create(GlobalPosition, target, _groundDistanceRaycast.CollisionMask); var result = spaceState.IntersectRay(query); if (result.Count > 0) { _movingToDesiredHeight = true; _randomDirection = new Vector3(GD.RandRange(-1, 1), 1, GD.RandRange(-1, 1)).Normalized(); } } else { velocity = _randomDirection * Inputs.Speed; var groundQuery = PhysicsRayQueryParameters3D.Create(GlobalPosition, GlobalPosition+Vector3.Down*Inputs.TargetHeight, _groundDistanceRaycast.CollisionMask); var groundResult = spaceState.IntersectRay(groundQuery); if (groundResult.Count == 0) { velocity.Y = 0; var query = PhysicsRayQueryParameters3D.Create(GlobalPosition, target, _groundDistanceRaycast.CollisionMask); var result = spaceState.IntersectRay(query); if (result.Count == 0) { _movingToDesiredHeight = false; } } } Velocity = velocity; MoveAndSlide(); } public void OnDamageBoxTriggered(Node3D body) { if(body is IDamageable damageable) damageable.TakeDamage(GetDamageDealt); } public void TakeDamage(RDamage damage) { foreach (var damageable in DamageModifiers.ToIDamageables()) damageable.TakeDamage(damage); } }