BITKit/Src/Unity/Scripts/Entity/Components/Health/EntityHealth.cs

159 lines
4.6 KiB
C#
Raw Normal View History

2023-08-11 23:57:37 +08:00
using System;
2023-06-05 19:57:17 +08:00
using System.Collections;
using System.Collections.Generic;
2024-03-31 23:31:00 +08:00
using System.IO;
2023-10-24 23:38:22 +08:00
using System.Linq;
2023-06-29 14:57:11 +08:00
using System.Runtime.Remoting.Contexts;
2023-06-05 19:57:17 +08:00
using UnityEngine;
using UnityEngine.Events;
namespace BITKit.Entities
{
2023-06-29 14:57:11 +08:00
public interface IHealth
2023-06-05 19:57:17 +08:00
{
2023-10-06 23:43:19 +08:00
/// <summary>
/// 当设置HP时的回调
/// </summary>
2023-08-11 23:57:37 +08:00
public event Action<int> OnSetHealthPoint;
2023-10-06 23:43:19 +08:00
/// <summary>
/// 当设置生存状态时的回调
/// </summary>
2023-08-11 23:57:37 +08:00
public event Action<bool> OnSetAlive;
2023-10-06 23:43:19 +08:00
/// <summary>
/// 当受到伤害时的回调
/// </summary>
2024-03-31 23:31:00 +08:00
public event Func<DamageMessage,int,int> OnDamageFactory;
/// <summary>
/// 收到伤害时的回调
/// </summary>
public event Action<DamageMessage> OnDamageRelease;
/// <summary>
/// 当伤害被阻止时的回调
/// </summary>
public event Action<DamageMessage> OnDamageVoid;
2023-06-29 14:57:11 +08:00
int HealthPoint { get; set; }
2023-08-11 23:57:37 +08:00
int MaxHealthPoint { get; set; }
2023-06-29 14:57:11 +08:00
bool IsAlive { get; }
}
2023-09-01 14:35:05 +08:00
[CustomType(typeof(IHealth))]
2024-03-31 23:31:00 +08:00
public class EntityHealth : EntityBehavior, IHealth,IEntityBinaryComponent
2023-06-29 14:57:11 +08:00
{
2023-08-11 23:57:37 +08:00
[Header(Constant.Header.Settings)]
[SerializeField] private int healthPoint = 100;
[SerializeField] private int maxHealthPoint = 100;
2023-06-29 14:57:11 +08:00
2024-03-31 23:31:00 +08:00
public int Id { get; } = 84946486;
2023-08-11 23:57:37 +08:00
public event Action<int> OnSetHealthPoint;
public event Action<bool> OnSetAlive;
2023-10-24 23:38:22 +08:00
public event Func<DamageMessage,int, int> OnDamageFactory;
2024-03-31 23:31:00 +08:00
public event Action<DamageMessage> OnDamageRelease;
public event Action<DamageMessage> OnDamageVoid;
2023-06-29 14:57:11 +08:00
public int HealthPoint
{
get => healthPoint;
2023-08-11 23:57:37 +08:00
set => OnHealthPointChangedInternal(healthPoint, value);
2023-06-29 14:57:11 +08:00
}
2023-08-11 23:57:37 +08:00
public int MaxHealthPoint
{
get => maxHealthPoint;
set => maxHealthPoint = value;
}
public bool IsAlive { get; private set; }
2023-06-05 19:57:17 +08:00
public override void OnAwake()
{
2023-11-06 01:17:23 +08:00
UnityEntity.AddListener<DamageMessage>(OnGetDamage);
2023-06-05 19:57:17 +08:00
}
2023-06-29 14:57:11 +08:00
2023-06-05 19:57:17 +08:00
public override void OnStart()
{
2023-08-11 23:57:37 +08:00
IsAlive = healthPoint >= 0;
OnSetAliveInternal(IsAlive);
OnHealthPointChangedInternal(0, healthPoint);
2023-06-05 19:57:17 +08:00
}
2023-06-29 14:57:11 +08:00
2023-08-11 23:57:37 +08:00
private void OnHealthPointChangedInternal(int old, int newHP)
2023-06-05 19:57:17 +08:00
{
2024-03-31 23:31:00 +08:00
healthPoint =Mathf.Clamp(newHP,-1,maxHealthPoint) ;
2023-06-05 19:57:17 +08:00
var _isAlive = newHP >= 0;
2023-08-11 23:57:37 +08:00
if (_isAlive != IsAlive)
2023-06-05 19:57:17 +08:00
{
2023-08-11 23:57:37 +08:00
OnSetAliveInternal(IsAlive = _isAlive);
2023-06-05 19:57:17 +08:00
}
2023-08-11 23:57:37 +08:00
OnSetHealthPoint?.Invoke(newHP);
2023-06-05 19:57:17 +08:00
}
2023-06-29 14:57:11 +08:00
2023-08-11 23:57:37 +08:00
private void OnSetAliveInternal(bool alive)
2023-06-05 19:57:17 +08:00
{
2023-09-01 14:35:05 +08:00
IsAlive = alive;
2023-08-11 23:57:37 +08:00
OnSetAlive?.Invoke(alive);
2023-06-05 19:57:17 +08:00
}
2023-06-29 14:57:11 +08:00
2023-10-06 23:43:19 +08:00
private void OnGetDamage(DamageMessage damageMessage)
2023-06-05 19:57:17 +08:00
{
2023-11-06 01:17:23 +08:00
if (damageMessage.Target != UnityEntity) return;
2024-03-31 23:31:00 +08:00
if (IsAlive is false)
{
OnDamageVoid?.Invoke(damageMessage);
}
else
2023-10-06 23:43:19 +08:00
{
2024-03-31 23:31:00 +08:00
var damage = damageMessage.Damage;
foreach (var x in OnDamageFactory.CastAsFunc())
{
damage = x.Invoke(damageMessage, damage);
if (damage <= 0)
{
OnDamageVoid?.Invoke(damageMessage);
break;
}
}
2024-05-31 01:23:15 +08:00
2024-03-31 23:31:00 +08:00
damageMessage.Damage = damage;
2024-05-31 01:23:15 +08:00
if (Data.Get<bool>("god") is false)
{
healthPoint-=damage;
}
IsAlive = healthPoint >= 0;
OnSetHealthPoint?.Invoke(healthPoint);
2024-03-31 23:31:00 +08:00
OnDamageRelease?.Invoke(damageMessage);
2024-05-31 01:23:15 +08:00
if (!IsAlive)
{
OnSetAliveInternal(false);
}
2023-10-06 23:43:19 +08:00
}
2023-06-05 19:57:17 +08:00
}
#if UNITY_EDITOR
[BIT]
public void SetAlive()
{
BITAppForUnity.ThrowIfNotPlaying();
2023-08-11 23:57:37 +08:00
OnHealthPointChangedInternal(-1, 100);
2023-06-05 19:57:17 +08:00
}
2023-06-29 14:57:11 +08:00
2023-06-05 19:57:17 +08:00
[BIT]
public void SetDead()
{
BITAppForUnity.ThrowIfNotPlaying();
2023-08-11 23:57:37 +08:00
OnHealthPointChangedInternal(100, -1);
2023-06-05 19:57:17 +08:00
}
#endif
2024-03-31 23:31:00 +08:00
public void Serialize(BinaryWriter writer)
{
writer.Write(HealthPoint);
}
2023-06-29 14:57:11 +08:00
2024-03-31 23:31:00 +08:00
public void Deserialize(BinaryReader reader)
{
var newHealthPoint = reader.ReadInt32();
if (HealthPoint != newHealthPoint)
HealthPoint = newHealthPoint;
}
2023-06-05 19:57:17 +08:00
}
}