using System.Linq; using Cirno.Scripts.Resources; using Godot; using Godot.Collections; namespace Cirno.Scripts.Components.Actors; public partial class GenericDamageReceiver : Area2D, IHittable { [Export] public ActorResourceProvider HealthProvider { get; private set; } [Export] public bool Invulnerable { get; private set; } = false; [Export] public BulletOwner BulletGroup { get; set; } = BulletOwner.None; [Export] public PackedScene Debris { get; set; } [Export] public Array DamageResistances { get; set; } = []; private Node2D _parent; public bool Enabled { get; private set; } = true; public override void _Ready() { _parent = GetParent(); HealthProvider.FillResource(); HealthProvider.ResourceDepleted += OnDeath; } public void ChangeState(bool enabled) { Enabled = enabled; } private void _on_damage_hitbox_area_entered(Area2D area) { if (!Enabled) return; if (Invulnerable) return; if (area is not Bullet bullet) return; if (BulletGroup is BulletOwner.None) { this.Hit(bullet.Damage, bullet.DamageType); bullet.RequestCollisionDestruction(); return; } if (bullet.BulletInfo.Owner == BulletGroup) return; this.Hit(bullet.Damage, bullet.DamageType); bullet.RequestCollisionDestruction(); } public void Hit(float damage, DamageType damageType = DamageType.Neutral) { if (!Enabled) return; if (Invulnerable) return; var dmg = DamageResistances.Aggregate(damage, (current, resistance) => current * resistance.CalculateDamage(current, damageType)); HealthProvider.CurrentResource -= dmg; } private void OnDeath() { if (Debris is not null) { _parent.CreateSibling(Debris); } _parent.QueueFree(); } }