using System;
using System.Collections;
using System.Collections.Generic;
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;
int HealthPoint { get; set; }
int MaxHealthPoint { get; set; }
bool IsAlive { get; }
}
[CustomType(typeof(IHealth))]
public class EntityHealth : EntityBehavior, IHealth
{
[Header(Constant.Header.Settings)]
[SerializeField] private int healthPoint = 100;
[SerializeField] private int maxHealthPoint = 100;
public event Action OnSetHealthPoint;
public event Action OnSetAlive;
public event Func OnDamageFactory;
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 = newHP;
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) return;
var damage = damageMessage.Damage;
foreach (var x in OnDamageFactory.CastAsFunc().Reverse())
{
damage = x.Invoke(damageMessage, damage);
if (damage <= 0) break;
}
if (Data.Get("god") is false)
AddHP(-damage);
}
#if UNITY_EDITOR
[BIT]
public void SetAlive()
{
BITAppForUnity.ThrowIfNotPlaying();
OnHealthPointChangedInternal(-1, 100);
}
[BIT]
public void SetDead()
{
BITAppForUnity.ThrowIfNotPlaying();
OnHealthPointChangedInternal(100, -1);
}
#endif
}
}