newlon/scripts/components/zombies/RuntimeZombieData.cs
2024-10-07 18:18:59 +05:00

116 lines
2.8 KiB
C#

using System.Collections.Generic;
using Godot;
using Newlon.Systems.Effects;
namespace Newlon.Components.Zombies;
public partial class RuntimeZombieData : Node2D, IEntity, ILocalTimescale, IEffectHandler
{
[Signal]
public delegate void OnHPChangedEventHandler(int deltaHP, Node origin);
[Signal]
public delegate void OnLocalTimescaleChangedEventHandler(int currentTimescale);
private int _hp;
[Export]
private int _maxHP;
[Export]
private int _line;
private float _localTimescale = 1.0f;
public int Hp => _hp;
public int MaxHp => _maxHP;
public int Line => _line;
public bool AbleToEat = true;
public float LocalTimescale
{
get => _localTimescale;
set
{
_localTimescale = value;
EmitSignal(SignalName.OnLocalTimescaleChanged,_localTimescale);
}
}
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);};
}
}
public void Heal(int amount,Node origin)
{
_hp += amount;
EmitSignal(SignalName.OnHPChanged,amount,origin);
if (MaxHp > 0)
{
_hp = MaxHp;
}
}
public void TakeDamage(int amount, Node origin, Utility.DamageTypes damageType = Utility.DamageTypes.PHYSICAL)
{
_hp -= amount;
EmitSignal(SignalName.OnHPChanged,-amount, origin);
if (_hp <= 0)
{
QueueFree();
}
}
#region Effects system
private readonly Effect[] _activeEffectSlots = new Effect[Utility.EffectSlotCount];
private readonly Timer[] _effectSlotTimers = new Timer[Utility.EffectSlotCount];
// Effect handling
public void GiveEffect(Effect what)
{
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
}