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