1
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using BITKit;
|
||||
using BITKit.SubSystems;
|
||||
@@ -9,14 +10,16 @@ namespace BITKit.Entities
|
||||
{
|
||||
|
||||
public interface IDamageType { }
|
||||
|
||||
public interface IDamageService
|
||||
{
|
||||
public event Action<DamageMessage> OnEntityDamaged;
|
||||
public event Action<DamageMessage> OnEntityKilled;
|
||||
void Execute(DamageMessage damageMessage);
|
||||
}
|
||||
public struct MeleeDamageMessage:IDamageType{}
|
||||
public struct MeleeDamageMessage : IDamageType
|
||||
{
|
||||
public bool Bleeding;
|
||||
}
|
||||
public struct BulletDamageMessage:IDamageType{}
|
||||
[Serializable]
|
||||
public class DamageServiceSingleton:IDamageService
|
||||
@@ -71,6 +74,34 @@ namespace BITKit.Entities
|
||||
public Vector3 Position;
|
||||
public Quaternion Rotation;
|
||||
public IDamageType DamageType;
|
||||
public RaycastHit? RaycastHit;
|
||||
}
|
||||
|
||||
public sealed class DamageMessageNetMessageWriter : NetMessageReader<DamageMessage>
|
||||
{
|
||||
public override DamageMessage ReadBinary(BinaryReader reader)
|
||||
{
|
||||
UnityEntitiesService.TryGetEntity(reader.ReadUInt64(),out var initiator);
|
||||
UnityEntitiesService.TryGetEntity(reader.ReadUInt64(),out var target);
|
||||
return new DamageMessage()
|
||||
{
|
||||
Initiator = initiator as Entity,
|
||||
Target = target as Entity,
|
||||
RawDamage = reader.ReadBoolean(),
|
||||
Damage = reader.ReadInt32(),
|
||||
Position = reader.ReadFloat3(),
|
||||
Rotation = reader.ReadQuaternion(),
|
||||
};
|
||||
}
|
||||
public override void WriteBinary(BinaryWriter writer, DamageMessage value)
|
||||
{
|
||||
writer.Write(value.Initiator?.Id ?? 0);
|
||||
writer.Write(value.Target?.Id ?? 0);
|
||||
writer.Write(value.RawDamage);
|
||||
writer.Write(value.Damage);
|
||||
writer.WriteFloat3(value.Position);
|
||||
writer.WriteQuaternion(value.Rotation);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IDamageCallback
|
||||
@@ -79,35 +110,65 @@ namespace BITKit.Entities
|
||||
}
|
||||
public interface IDamagable
|
||||
{
|
||||
IHealth Health { get; }
|
||||
IUnityEntity UnityEntity { get; }
|
||||
Rigidbody Rigidbody { get; }
|
||||
void GiveDamage(DamageMessage message);
|
||||
}
|
||||
public class DamageService:MonoBehaviour,IDamageService
|
||||
{
|
||||
internal static IDamageService Singleton { get; set; }
|
||||
public static IDamageService Singleton { get;private set; }
|
||||
private readonly Queue<DamageMessage> Messages = new();
|
||||
|
||||
[SerializeReference,SubclassSelector] private INetClient netClient;
|
||||
[SerializeReference,SubclassSelector] private INetServer netServer;
|
||||
|
||||
private INetProvider netClientProvider => netClient.Source as INetProvider;
|
||||
private INetProvider netServerProvider => netServer.Source as INetProvider;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Singleton = this;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
netClientProvider.AddCommandListener<DamageMessage>(ExecuteInternal);
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (!netServer.IsRunningServer && netClient.IsConnected) return;
|
||||
while (Messages.TryDequeue(out var damageMessage))
|
||||
{
|
||||
var unityEntity = (Entity)damageMessage.Target;
|
||||
if (!unityEntity || !unityEntity.TryGetComponent<IHealth>(out var heal) || !heal.IsAlive) continue;
|
||||
|
||||
damageMessage.Initiator?.Invoke(damageMessage);
|
||||
damageMessage.Target?.Invoke(damageMessage);
|
||||
|
||||
ExecuteInternal(damageMessage);
|
||||
|
||||
netServerProvider?.AllClientCommand(damageMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteInternal(DamageMessage damageMessage)
|
||||
{
|
||||
IHealth heal = null;
|
||||
if (damageMessage.Target?.TryGetComponent<IHealth>(out heal) is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
damageMessage.Initiator?.Invoke(damageMessage);
|
||||
damageMessage.Target?.Invoke(damageMessage);
|
||||
|
||||
if (heal!.IsAlive)
|
||||
{
|
||||
OnEntityDamaged?.Invoke(damageMessage);
|
||||
if (heal.IsAlive is false)
|
||||
{
|
||||
OnEntityKilled?.Invoke(damageMessage);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
OnEntityKilled?.Invoke(damageMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Remoting.Contexts;
|
||||
using UnityEngine;
|
||||
@@ -20,21 +21,34 @@ namespace BITKit.Entities
|
||||
/// <summary>
|
||||
/// 当受到伤害时的回调
|
||||
/// </summary>
|
||||
public event Func<DamageMessage,int,int> OnDamageFactory;
|
||||
public event Func<DamageMessage,int,int> OnDamageFactory;
|
||||
/// <summary>
|
||||
/// 收到伤害时的回调
|
||||
/// </summary>
|
||||
public event Action<DamageMessage> OnDamageRelease;
|
||||
/// <summary>
|
||||
/// 当伤害被阻止时的回调
|
||||
/// </summary>
|
||||
public event Action<DamageMessage> OnDamageVoid;
|
||||
|
||||
int HealthPoint { get; set; }
|
||||
int MaxHealthPoint { get; set; }
|
||||
bool IsAlive { get; }
|
||||
}
|
||||
[CustomType(typeof(IHealth))]
|
||||
public class EntityHealth : EntityBehavior, 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<int> OnSetHealthPoint;
|
||||
public event Action<bool> OnSetAlive;
|
||||
public event Func<DamageMessage,int, int> OnDamageFactory;
|
||||
public event Action<DamageMessage> OnDamageRelease;
|
||||
public event Action<DamageMessage> OnDamageVoid;
|
||||
|
||||
public int HealthPoint
|
||||
{
|
||||
@@ -61,7 +75,7 @@ namespace BITKit.Entities
|
||||
|
||||
private void OnHealthPointChangedInternal(int old, int newHP)
|
||||
{
|
||||
healthPoint = newHP;
|
||||
healthPoint =Mathf.Clamp(newHP,-1,maxHealthPoint) ;
|
||||
var _isAlive = newHP >= 0;
|
||||
if (_isAlive != IsAlive)
|
||||
{
|
||||
@@ -84,15 +98,28 @@ namespace BITKit.Entities
|
||||
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())
|
||||
if (IsAlive is false)
|
||||
{
|
||||
damage = x.Invoke(damageMessage, damage);
|
||||
if (damage <= 0) break;
|
||||
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<bool>("god") is false)
|
||||
AddHP(-damage);
|
||||
|
||||
damageMessage.Damage = damage;
|
||||
OnDamageRelease?.Invoke(damageMessage);
|
||||
}
|
||||
if (Data.Get<bool>("god") is false)
|
||||
AddHP(-damage);
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
[BIT]
|
||||
@@ -109,6 +136,17 @@ namespace BITKit.Entities
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user