BITKit/Packages/Runtime~/Unity/Scripts/Entity/Components/Health/DamageService.cs

120 lines
3.8 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BITKit;
using BITKit.SubSystems;
using BITKit.Entities;
namespace BITKit.Entities
{
public interface IDamageType { }
public interface IDamageService
{
public event Action<DamageMessage> OnEntityDamaged;
public event Action<DamageMessage> OnEntityKilled;
void Execute(DamageMessage damageMessage);
}
[Serializable]
public class DamageServiceSingleton:IDamageService
{
private IDamageService _damageServiceImplementation => DamageService.Singleton;
public event Action<DamageMessage> OnEntityDamaged
{
add => _damageServiceImplementation.OnEntityDamaged += value;
remove => _damageServiceImplementation.OnEntityDamaged -= value;
}
public event Action<DamageMessage> OnEntityKilled
{
add => _damageServiceImplementation.OnEntityKilled += value;
remove => _damageServiceImplementation.OnEntityKilled -= value;
}
public void Execute(DamageMessage damageMessage)
{
_damageServiceImplementation.Execute(damageMessage);
}
}
[Serializable]
public class DamageServiceMonoProxy:IDamageService
{
[SerializeField] private MonoBehaviour monoBehaviour;
private IDamageService _damageServiceImplementation=>monoBehaviour as IDamageService;
public event Action<DamageMessage> OnEntityDamaged
{
add => _damageServiceImplementation.OnEntityDamaged += value;
remove => _damageServiceImplementation.OnEntityDamaged -= value;
}
public event Action<DamageMessage> OnEntityKilled
{
add => _damageServiceImplementation.OnEntityKilled += value;
remove => _damageServiceImplementation.OnEntityKilled -= value;
}
public void Execute(DamageMessage damageMessage)
{
_damageServiceImplementation.Execute(damageMessage);
}
}
public record DamageMessage
{
public IEntity initiator;
public IEntity target;
public int damage;
public IDamagable hit;
public Location location;
public IDamageType damageType;
}
public interface IDamageCallback
{
void OnGetDamage(DamageMessage message);
}
public interface IDamagable
{
IEntity Entity { get; }
Rigidbody Rigidbody { get; }
void GiveDamage(DamageMessage message);
}
public class DamageService:MonoBehaviour,IDamageService
{
internal static IDamageService Singleton { get; set; }
private readonly Queue<DamageMessage> Messages = new();
private void Awake()
{
Singleton = this;
}
private void FixedUpdate()
{
while (Messages.TryDequeue(out var damageMessage))
{
var unityEntity = (Entity)damageMessage.target;
if (unityEntity is null || !unityEntity.TryGetComponent<IHealth>(out var heal) || !heal.IsAlive) continue;
damageMessage.initiator?.Invoke(damageMessage);
damageMessage.target?.Invoke(damageMessage);
foreach (var x in damageMessage.target?.GetCallbacks<IDamageCallback>()!)
{
x.OnGetDamage(damageMessage);
}
OnEntityDamaged?.Invoke(damageMessage);
if (heal.IsAlive is false)
{
OnEntityKilled?.Invoke(damageMessage);
}
}
}
public event Action<DamageMessage> OnEntityDamaged;
public event Action<DamageMessage> OnEntityKilled;
public void Execute(DamageMessage damageMessage)=>Messages.Enqueue(damageMessage);
}
}