From 172d8ffbf5fe3bdd60b3d71a3a60feeed1cb1762 Mon Sep 17 00:00:00 2001 From: chenxin <chenxin6991@163.com> Date: Mon, 09 Nov 2020 16:37:47 +0800 Subject: [PATCH] Merge commit '894e974d944190fb2e10e14827f0d878626bd048' into master --- Assets/Scripts/Core/Health/Damageable.cs | 532 ++++++++++++++++++++++++++++++++++------------------------ 1 files changed, 314 insertions(+), 218 deletions(-) diff --git a/Assets/Scripts/Core/Health/Damageable.cs b/Assets/Scripts/Core/Health/Damageable.cs index 40a963d..59f64da 100644 --- a/Assets/Scripts/Core/Health/Damageable.cs +++ b/Assets/Scripts/Core/Health/Damageable.cs @@ -3,251 +3,347 @@ namespace Core.Health { - /// <summary> - /// Damageable class for handling health using events - /// Could be used on Players or enemies or even destructable world objects - /// </summary> - [Serializable] - public class Damageable - { - /// <summary> - /// The max health of this instance - /// </summary> - public float maxHealth; - - public float startingHealth; + /// <summary> + /// Damageable class for handling health using events + /// Could be used on Players or enemies or even destructable world objects + /// </summary> + [Serializable] + public class Damageable + { + /// <summary> + /// The max health of this instance + /// </summary> + public float maxHealth; - /// <summary> - /// The alignment of the damager - /// </summary> - public SerializableIAlignmentProvider alignment; + public float startingHealth; - // events - public event Action reachedMaxHealth; + /// <summary> + /// The alignment of the damager + /// </summary> + public SerializableIAlignmentProvider alignment; - // 当前的Entity用于响应各种血量相关的事件。 - public event Action<HealthChangeInfo> damaged, healed, died, healthChanged; + // events + public event Action reachedMaxHealth; + + // 当前的Entity用于响应各种血量相关的事件。 + public event Action<HealthChangeInfo> damaged, healed, died, healthChanged; + + /// <summary> + /// 魔法护盾值改变 + /// </summary> + public event Action<HealthChangeInfo> ShieldWallHealthChanged; + + /// <summary> + /// Gets the current health. + /// </summary> + public float currentHealth { protected set; get; } + + /// <summary> + /// 设置无敌状态. + /// </summary> + public bool bInvincible { get; set; } + + /// <summary> + /// 是否存在魔法护盾 + /// </summary> + public bool IsExistShieldWall { get; set; } + + /// <summary> + /// 0 -> 和agent的生命周期一致,直到死亡, > 0 (单位s)*时间内生效 + /// </summary> + public float ShieldWallEffectiveTime { get; set; } + + /// <summary> + /// 魔法护盾生效剩余时间,这个只针对 ShieldWallEffectTime > 0 才生效 + /// </summary> + public float ShieldWallRemainTime { get; set; } + + /// <summary> + /// 魔法护盾最大生命值,即初始生命值 + /// </summary> + public float ShieldWallMaxHealth { get; set; } + + /// <summary> + /// 魔法护盾当前生命值,当 <= 0时直接移除护盾效果 + /// </summary> + public float ShieldWallCurrentHealth { get; set; } + + /// <summary> + /// Gets the normalised health. + /// </summary> + public float normalisedHealth + { + get + { + if (Math.Abs(maxHealth) <= Mathf.Epsilon) + { + Debug.LogError("Max Health is 0"); + maxHealth = 1f; + } + return currentHealth / maxHealth; + } + } + + /// <summary> + /// 清理魔法护盾 + /// </summary> + public void ClearShieldWall() + { + IsExistShieldWall = false; + ShieldWallMaxHealth = 0; + ShieldWallCurrentHealth = 0; + ShieldWallRemainTime = 0; + ShieldWallEffectiveTime = 0; + } + + /// <summary> + /// Gets the <see cref="IAlignmentProvider"/> of this instance + /// </summary> + public IAlignmentProvider alignmentProvider + { + get + { + return alignment != null ? alignment.GetInterface() : null; + } + } + + /// <summary> + /// Gets whether this instance is dead. + /// </summary> + public bool isDead + { + get { return currentHealth < 1.0f; } + } + + /// <summary> + /// Gets whether this instance is at max health. + /// </summary> + public bool isAtMaxHealth + { + get { return Mathf.Approximately(currentHealth, maxHealth); } + } - /// <summary> - /// Gets the current health. - /// </summary> - public float currentHealth { protected set; get; } + /// <summary> + /// Init this instance + /// </summary> + public virtual void Init() + { + currentHealth = startingHealth; + } - /// <summary> - /// 设置无敌状态. - /// </summary> - public bool bInvincible { get; set; } + /// <summary> + /// Sets the max health and starting health to the same value + /// </summary> + public void SetMaxHealth(float health) + { + if (health <= 0) + { + return; + } + maxHealth = startingHealth = health; + } - /// <summary> - /// Gets the normalised health. - /// </summary> - public float normalisedHealth - { - get - { - if (Math.Abs(maxHealth) <= Mathf.Epsilon) - { - Debug.LogError("Max Health is 0"); - maxHealth = 1f; - } - return currentHealth / maxHealth; - } - } + /// <summary> + /// Sets the max health and starting health separately + /// </summary> + public void SetMaxHealth(float health, float startingHealth) + { + if (health <= 0) + { + return; + } + maxHealth = health; + this.startingHealth = startingHealth; + } - /// <summary> - /// Gets the <see cref="IAlignmentProvider"/> of this instance - /// </summary> - public IAlignmentProvider alignmentProvider - { - get - { - return alignment != null ? alignment.GetInterface() : null; - } - } + /// <summary> + /// Sets this instance's health directly. + /// </summary> + /// <param name="health"> + /// The value to set <see cref="currentHealth"/> to + /// </param> + public void SetHealth(float health) + { + var info = new HealthChangeInfo + { + damageable = this, + newHealth = health, + oldHealth = currentHealth + }; - /// <summary> - /// Gets whether this instance is dead. - /// </summary> - public bool isDead - { - get { return currentHealth < 1.0f; } - } + currentHealth = health; + info.oldHealth = health; - /// <summary> - /// Gets whether this instance is at max health. - /// </summary> - public bool isAtMaxHealth - { - get { return Mathf.Approximately(currentHealth, maxHealth); } - } + if (healthChanged != null) + { + healthChanged(info); + } + } + /// <summary> + /// 获得一个魔法护盾 + /// </summary> + /// <param name="maxHealth">护盾的最大生命值</param> + /// <param name="effectiveTime">生效时间 0 -> 和Agent生命周期一致,> 0 *(单位ms)时间内生效</param> + public void AddShieldWall(float maxHealth, float effectiveTime) + { + // 如果重复获得护盾,直接全部重置数据,移除之前的护盾效果,重新获得一个护盾 + IsExistShieldWall = true; + ShieldWallEffectiveTime = effectiveTime; - /// <summary> - /// Init this instance - /// </summary> - public virtual void Init() - { - currentHealth = startingHealth; - } + if (effectiveTime > 0) + ShieldWallRemainTime = effectiveTime / 1000f; - /// <summary> - /// Sets the max health and starting health to the same value - /// </summary> - public void SetMaxHealth(float health) - { - if (health <= 0) - { - return; - } - maxHealth = startingHealth = health; - } + ShieldWallMaxHealth = ShieldWallCurrentHealth = maxHealth; - /// <summary> - /// Sets the max health and starting health separately - /// </summary> - public void SetMaxHealth(float health, float startingHealth) - { - if (health <= 0) - { - return; - } - maxHealth = health; - this.startingHealth = startingHealth; - } + HealthChangeInfo info = new HealthChangeInfo + { + damageable = this, + ShieldWallMaxHealth = maxHealth, + ShieldWallCurrentHealth = maxHealth, + IsExistShieldWall = true + }; - /// <summary> - /// Sets this instance's health directly. - /// </summary> - /// <param name="health"> - /// The value to set <see cref="currentHealth"/> to - /// </param> - public void SetHealth(float health) - { - var info = new HealthChangeInfo - { - damageable = this, - newHealth = health, - oldHealth = currentHealth - }; - - currentHealth = health; - info.oldHealth = health; + if (ShieldWallHealthChanged != null) + { + ShieldWallHealthChanged(info); + } + } - if (healthChanged != null) - { - healthChanged(info); - } - } + /// <summary> + /// Use the alignment to see if taking damage is a valid action + /// </summary> + /// <param name="damage"> + /// The damage to take + /// </param> + /// <param name="damageAlignment"> + /// The alignment of the other combatant + /// </param> + /// <param name="output"> + /// The output data if there is damage taken + /// </param> + /// <returns> + /// <value>true if this instance took damage</value> + /// <value>false if this instance was already dead, or the alignment did not allow the damage</value> + /// </returns> + public bool TakeDamage(float damage, IAlignmentProvider damageAlignment, ref HealthChangeInfo output) + { - /// <summary> - /// Use the alignment to see if taking damage is a valid action - /// </summary> - /// <param name="damage"> - /// The damage to take - /// </param> - /// <param name="damageAlignment"> - /// The alignment of the other combatant - /// </param> - /// <param name="output"> - /// The output data if there is damage taken - /// </param> - /// <returns> - /// <value>true if this instance took damage</value> - /// <value>false if this instance was already dead, or the alignment did not allow the damage</value> - /// </returns> - public bool TakeDamage(float damage, IAlignmentProvider damageAlignment, ref HealthChangeInfo output) - { - - /*output = new HealthChangeInfo + /*output = new HealthChangeInfo { damageAlignment = damageAlignment, damageable = this, newHealth = currentHealth, oldHealth = currentHealth };*/ - output.damageAlignment = damageAlignment; - output.damageable = this; - output.newHealth = currentHealth; - output.oldHealth = currentHealth; + output.damageAlignment = damageAlignment; + output.damageable = this; + output.newHealth = currentHealth; + output.oldHealth = currentHealth; - // 无敌状态下,不可伤害. - if (this.bInvincible) - return false; + // 无敌状态下,不可伤害. + if (this.bInvincible) + return false; - bool canDamage = damageAlignment == null || alignmentProvider == null || - damageAlignment.CanHarm(alignmentProvider); - - if (isDead || !canDamage) - { - return false; - } + bool canDamage = damageAlignment == null || alignmentProvider == null || + damageAlignment.CanHarm(alignmentProvider); - ChangeHealth(-damage, ref output); - SafelyDoAction(damaged, output); - if (isDead) - { - SafelyDoAction(died, output); - } - return true; - } + if (isDead || !canDamage) + { + return false; + } - /// <summary> - /// Logic for increasing the health. - /// </summary> - /// <param name="health">Health.</param> - public HealthChangeInfo IncreaseHealth(float health) - { - var info = new HealthChangeInfo {damageable = this}; - ChangeHealth(health, ref info); - SafelyDoAction(healed, info); - if (isAtMaxHealth) - { - SafelyDoAction(reachedMaxHealth); - } + ChangeHealth(-damage, ref output); + SafelyDoAction(damaged, output); + if (isDead) + { + SafelyDoAction(died, output); + } + return true; + } - return info; - } + /// <summary> + /// Logic for increasing the health. + /// </summary> + /// <param name="health">Health.</param> + public HealthChangeInfo IncreaseHealth(float health) + { + var info = new HealthChangeInfo { damageable = this }; + ChangeHealth(health, ref info); + SafelyDoAction(healed, info); + if (isAtMaxHealth) + { + SafelyDoAction(reachedMaxHealth); + } - /// <summary> - /// Changes the health. - /// </summary> - /// <param name="healthIncrement">Health increment.</param> - /// <param name="info">HealthChangeInfo for this change</param> - protected void ChangeHealth(float healthIncrement, ref HealthChangeInfo info) - { - info.oldHealth = currentHealth; - currentHealth += healthIncrement; - currentHealth = Mathf.Clamp(currentHealth, 0f, maxHealth); - info.newHealth = currentHealth; - - if (healthChanged != null) - { - healthChanged(info); - } - } + return info; + } - /// <summary> - /// A helper method for null checking actions - /// </summary> - /// <param name="action">Action to be done</param> - protected void SafelyDoAction(Action action) - { - if (action != null) - { - action(); - } - } + /// <summary> + /// Changes the health. + /// </summary> + /// <param name="healthIncrement">Health increment.</param> + /// <param name="info">HealthChangeInfo for this change</param> + protected void ChangeHealth(float healthIncrement, ref HealthChangeInfo info) + { + bool changeHealth = false; + float increment = healthIncrement; - /// <summary> - /// A helper method for null checking actions - /// </summary> - /// <param name="action">Action to be done</param> - /// <param name="info">The HealthChangeInfo to be passed to the Action</param> - protected void SafelyDoAction(Action<HealthChangeInfo> action, HealthChangeInfo info) - { - if (action != null) - { - action(info); - } - } - } + if (IsExistShieldWall) + { + info.ShieldWallOldHealth = ShieldWallCurrentHealth; + ShieldWallCurrentHealth += healthIncrement; + + if (ShieldWallCurrentHealth == 0) + info.IsExistShieldWall = IsExistShieldWall = false; + else if (ShieldWallCurrentHealth < 0) + { + changeHealth = true; + info.IsExistShieldWall = IsExistShieldWall = false; + // 护盾血量不够减 + increment = ShieldWallCurrentHealth; + info.ShieldWallCurrentHealth = ShieldWallCurrentHealth = 0; + } + } + else + changeHealth = true; + + if (changeHealth) + { + info.oldHealth = currentHealth; + currentHealth += increment; + currentHealth = Mathf.Clamp(currentHealth, 0f, maxHealth); + info.newHealth = currentHealth; + + if (healthChanged != null) + { + healthChanged(info); + } + } + } + + /// <summary> + /// A helper method for null checking actions + /// </summary> + /// <param name="action">Action to be done</param> + protected void SafelyDoAction(Action action) + { + if (action != null) + { + action(); + } + } + + /// <summary> + /// A helper method for null checking actions + /// </summary> + /// <param name="action">Action to be done</param> + /// <param name="info">The HealthChangeInfo to be passed to the Action</param> + protected void SafelyDoAction(Action<HealthChangeInfo> action, HealthChangeInfo info) + { + if (action != null) + { + action(info); + } + } + } } \ No newline at end of file -- Gitblit v1.9.1