战斗系统
所有的伤害计算,必须在服务器上进行。
战斗系统涉及两个关键的用来标记的接口:IDamageable和IDamageSource。
前者用来标记一个对象可以被伤害,后者用来标记此对象可以作为伤害的来源。
伤害的传递使用结构体DamagePacket来传递:
https://github.com/VMware233/TH/blob/main/Assets/Scripts/Damage/DamagePacket.cs
namespace TH.Damage
{
public struct DamagePacket
{
/// <summary>
/// 伤害çç´æ¥æ¥æº
/// </summary>
public IDamageSource directSource;
/// <summary>
/// æ¯å¦æ¯åå¼¹æ»å»
/// </summary>
public bool isReflectedAttack;
/// <summary>
/// æ¯å¦æ¯è¿ææ»å»
/// </summary>
public bool isMelee;
/// <summary>
/// ç©ç伤害
/// </summary>
public int physicalDamage;
/// <summary>
/// 鿳伤害
/// </summary>
public int magicalDamage;
/// <summary>
/// æ»ä¼¤å®³åç
/// </summary>
public float damageMultiplier;
/// <summary>
/// æ´å»ç
/// </summary>
public float criticalRate;
/// <summary>
/// æ´å»ä¼¤å®³åç
/// </summary>
public float criticalDamageMultiplier;
public DamagePacket(IDamageSource directSource)
{
this.directSource = directSource;
this.isReflectedAttack = false;
this.isMelee = false;
this.physicalDamage = 0;
this.magicalDamage = 0;
this.damageMultiplier = 1;
this.criticalRate = 0;
this.criticalDamageMultiplier = 1;
}
}
}一个IDamageSource是可以产生DamagePacket的(通过ProduceDamagePacket方法),而一个IDamageable在收到DamagePacket后,首先会产生一个DamageResult,然后调用ProcessDamageResult去处理这个DamageResult。
使用下述的工具方法可以让IDamageSource给IDamageable发送一个伤害包(DamagePacket):
https://github.com/VMware233/TH/blob/main/Assets/Scripts/Damage/DamageSource/DamageSourceUtility.cs
using FishNet.Object;
namespace TH.Damage
{
public static class DamageSourceUtility
{
/// <summary>
/// 强å¶å¯¹ç®æ é æä¼¤å®³
/// ä»
卿å¡å¨ä¸ææ
/// </summary>
/// <param name="source"></param>
/// <param name="target"></param>
[Server]
public static void ForceTakeDamage(this IDamageSource source, IDamageable target)
{
if (target == null)
{
return;
}
source.ProduceDamagePacket(target, out var packet);
target.ReceiveDamagePacket(packet);
}
/// <summary>
/// 请æ±å¯¹ç®æ é æä¼¤å®³
/// ä»
卿å¡å¨ä¸ææ
/// </summary>
/// <param name="source"></param>
/// <param name="target"></param>
public static void RequestTakeDamage(this IDamageSource source, IDamageable target)
{
if (target == null)
{
return;
}
if (source.CanDamage(target) == false)
{
return;
}
if (target.CanBeDamaged(source) == false)
{
return;
}
source.ForceTakeDamage(target);
}
}
}Last updated