战斗系统

战斗系统涉及两个关键的用来标记的接口: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