using Godot; using System; using System.Linq; using Movementtests.interfaces; [GlobalClass] public partial class FirstEnemy : CharacterBody3D, IDamageable, IDamageMaker, IHealthable, IKillable { [Export] public Node3D Target { get; set; } [Export] public EnemyInitInputs Inputs; [Export] public RDamage GetDamageDealt { get; set; } [Export] public CHealth CHealth { get; set; } [Export] public CDamageable CDamage { get; set; } [Export] public RDeathEffect[] DeathEffects { get; set; } private RayCast3D _wallInFrontRayCast; private Area3D _damageBox; public override void _Ready() { _wallInFrontRayCast = GetNode("WallInFrontRayCast"); _damageBox = GetNode("DamageBox"); _damageBox.BodyEntered += OnDamageBoxTriggered; CDamage.DamageTaken += ReduceHealth; CHealth.Dead += Kill; } public override void _PhysicsProcess(double delta) { var target = Target.GlobalPosition; var direction = (target - GlobalPosition).Normalized(); var targetPlane = new Vector3(target.X, GlobalPosition.Y, target.Z); LookAt(targetPlane); var velocity = Velocity; velocity.X = direction.X * Inputs.Speed; velocity.Z = direction.Z * Inputs.Speed; if (_wallInFrontRayCast.IsColliding()) velocity.Y = Inputs.Speed; else if (!IsOnFloor()) velocity += GetGravity() * (float)delta; Velocity = velocity; MoveAndSlide(); } public void OnDamageBoxTriggered(Node3D body) { if(body is IDamageable damageable) damageable.TakeDamage(GetDamageDealt); } public float TakeDamage(RDamage damage) { return CDamage.TakeDamage(damage); } public float CurrentHealth { get => CHealth.CurrentHealth; set => CHealth.CurrentHealth = value; } public void ReduceHealth(float amount) { CHealth.ReduceHealth(amount); } public void Kill() { foreach (var killable in DeathEffects.ToIKillables()) { killable.Kill(); } QueueFree(); } }