using Godot; using Godot.Collections; using Newlon.Systems.Effects; namespace Newlon.Components; public partial class Entity : Node2D { #region Health points [Export] public float MaxHP { get; private set; } public float HP { get; private set; } [Signal] public delegate void OnHPChangedEventHandler(int deltaHP, Node origin); [Signal] public delegate void OnDamagedEventHandler(); public virtual void TakeDamage(float amount, Node origin) { HP -= amount; if (HP <= 0) { } } public virtual void Heal(float amount, Node origin) { HP += amount; } public virtual void Kill() { QueueFree(); } #endregion #region Brain public virtual void DisableBrain() { GetNode("AnimationPlayer").ProcessMode = ProcessModeEnum.Pausable; ProcessMode = ProcessModeEnum.Disabled; } public virtual void EnableBrain() { GetNode("AnimationPlayer").ProcessMode = ProcessModeEnum.Inherit; ProcessMode = ProcessModeEnum.Inherit; } #endregion #region Effects [Export] private Array _effectImmunities; private readonly Effect[] _activeEffectSlots = new Effect[Utility.EffectSlotCount]; private readonly Timer[] _effectSlotTimers = new Timer[Utility.EffectSlotCount]; public virtual void GiveEffect(Effect what) { if (_effectImmunities.Contains(what)) { return; } int slot = (int)what.Slot; if (_activeEffectSlots[slot] != null) { _effectSlotTimers[slot].Stop(); _activeEffectSlots[slot].Exit(this); } _effectSlotTimers[slot].WaitTime = what.Duration; _effectSlotTimers[slot].Start(); what.Enter(this); _activeEffectSlots[slot] = what; } public void EndEffect(Effect what) { what.Exit(this); _activeEffectSlots[(int)what.Slot] = null; } public void ProcessEffects() { for (int i = 0; i < Utility.EffectSlotCount; i++) _activeEffectSlots[i]?.Process(this); } private void EndEffectAtSlot(int slot) { _activeEffectSlots[slot].Exit(this); _activeEffectSlots[slot] = null; } #endregion #region LocalTimescale private float _localTimescale = 1.0f; [Signal] public delegate void OnLocalTimescaleChangedEventHandler(float scale); public float LocalTimescale { get => _localTimescale; set { _localTimescale = value; EmitSignal(SignalName.OnLocalTimescaleChanged, _localTimescale); } } #endregion #region Godot overrides public override void _Ready() { HP = MaxHP; // Effect timers setup for(int i = 0; i < Utility.EffectSlotCount; i++) { var timer = new Timer() {Autostart = false, OneShot = true}; _effectSlotTimers[i] = timer; AddChild(timer); int current_index = i; timer.Timeout += () => {EndEffectAtSlot(current_index);}; } } #endregion }