162 lines
4.2 KiB
C#
162 lines
4.2 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 OnDamagedEventHandler();
|
|
|
|
[Signal]
|
|
public delegate void OnLocalTimescaleChangedEventHandler(int currentTimescale);
|
|
|
|
[Export]
|
|
private int _hp;
|
|
[Export]
|
|
private int _maxHP;
|
|
[Export]
|
|
private Armor _armor;
|
|
|
|
[Export]
|
|
private AudioStream garlicSound;
|
|
[Export]
|
|
private AudioStream freezeSound;
|
|
|
|
|
|
private float _localTimescale = 1.0f;
|
|
public int Hp => _hp;
|
|
|
|
public int MaxHp => _maxHP;
|
|
|
|
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)
|
|
{
|
|
if(_armor != null)
|
|
{
|
|
_hp += _armor.Heal(amount);
|
|
}
|
|
else
|
|
_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)
|
|
{
|
|
if (_armor != null)
|
|
{
|
|
_hp -= _armor.RecieveDamage(amount);
|
|
}
|
|
else
|
|
_hp -= amount;
|
|
EmitSignal(SignalName.OnHPChanged,-amount, origin);
|
|
EmitSignal(SignalName.OnDamaged);
|
|
|
|
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)
|
|
{
|
|
switch (what.Slot)
|
|
{
|
|
case Utility.EffectSlots.FREEZE:
|
|
AudioSequencer.Play("zombie_freeze", freezeSound);
|
|
var settings = new ChannelSettings();
|
|
settings.restartTreshold = -1;
|
|
AudioSequencer.ChangeSettings("zombie_freeze",settings);
|
|
break;
|
|
case Utility.EffectSlots.GARLIC:
|
|
AudioSequencer.Play("zombie_garlic", garlicSound);
|
|
|
|
break;
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
|
|
public void DisableBrain()
|
|
{
|
|
GetNode<AnimationPlayer>("AnimationPlayer").ProcessMode = ProcessModeEnum.Pausable;
|
|
ProcessMode = ProcessModeEnum.Disabled;
|
|
}
|
|
|
|
public void EnableBrain()
|
|
{
|
|
GetNode<AnimationPlayer>("AnimationPlayer").ProcessMode = ProcessModeEnum.Inherit;
|
|
ProcessMode = ProcessModeEnum.Inherit;
|
|
}
|
|
#endregion
|
|
}
|