using FL.Nodes.GameMain; using UnityEngine; using XGame.Database; using XGame.Framework.Components; namespace FL.Battle.Components { public interface ICombatContext { IEntity Entity { get; } ITargetSelector Selector { get; } Vector3 Position { get; } StatesComponent States { get; } BuffsComponent Buffs { get; } SkillComponent Skill { get; } /// /// 铭文组件 /// 可能为空 /// EpigraphicsComponent Epigraphics { get; } } public class CombatComponent : Component, ICombatCalculation { protected override void OnDispose() { } /// /// 计算血量 /// 正数表示加血 /// 负数表示扣血 /// /// /// private int CalculateHP(int damage) { var remainDamage = Context.Buffs.CalculateShieldAbsorb(damage); if (remainDamage == 0) { // 全部被护盾吸收 return damage; } // 吸收值 var absorption = damage - remainDamage; var attrs = Context.Entity.Attr; var lastHp = attrs.CurrentHp; var nextHp = lastHp + remainDamage; if (nextHp > attrs.HpLimit) { nextHp = attrs.HpLimit; } else if (nextHp < 0) { nextHp = 0; } attrs.CurrentHp = nextHp; if (nextHp == 0) { Context.States.AddState(EEntityState.Dead); } var result = (int)(nextHp - lastHp); // 返回扣血和护盾吸收的总和 return result + absorption; } private void AddSkillBuff(SkillTable skill, ITarget attacker, int damage) { if (skill.BuffTie.Length != 2) return; var probability = skill.BuffTie[0]; var buffId = skill.BuffTie[1]; if (TryGetTrigger(BuffTableRepo.GetTargetType(buffId), attacker, out var trigger)) { trigger?.Buffs.TryAddBuff(buffId, probability, 1, null, damage); } else { Context.Buffs.TryAddBuff(buffId, probability, 1, attacker?.Calculation, damage); } } /// /// 根据技能/Buff的目标类型确定触发目标 /// /// /// /// private ICombatCalculation GetTrigger(ESkillTargetType targetType, ICombatCalculation attacker) { if (TableUtils.IsContain((uint)targetType, ESkillTargetType.Attacker)) { return attacker; } if (TableUtils.IsContain((uint)targetType, ESkillTargetType.Player)) { return Context.Selector.GetPlayer()?.Calculation; } return this; } private bool TryGetTrigger(ESkillTargetType targetType, ITarget attacker, out ITarget trigger) { if (TableUtils.IsContain((uint)targetType, ESkillTargetType.Attacker)) { trigger = attacker; return true; } if (TableUtils.IsContain((uint)targetType, ESkillTargetType.Player)) { trigger = Context.Selector.GetPlayer(); return true; } trigger = null; return false; } #region 被动技能 //private void TickAttackerPassiveSkill(SkillTable skill, ICombatCalculation target) //{ // Context.Skill.TryTickPassiveSkills((passiveSkill) => // { // return true; // }); //} #endregion #region 接口实现 void ICombatCalculation.Damage(int damage, long attackerId, SkillTable skill) { if (Context.Entity.IsDead) { // 已经死亡 return; } ITarget attacker = null; if (damage != 0) { // damage为零时不计算 var damageAdd = 0; if (attackerId != Context.Entity.EntityId) { // 攻击者和受击者是同一个目标时不计算加成 attacker = Context.Selector.GetTarget(attackerId); if (attacker != null && !attacker.IsDead) { damageAdd += attacker.Buffs.GetDamageAdd(skill.Element, Context.Entity, Context.Buffs); } } damageAdd += Context.Buffs.GetDamageAdd(skill.Element, Context.Entity, Context.Buffs); var realDamage = Mathf.CeilToInt(damage * (1 + damageAdd.ToRealFloat())); damage = CalculateHP(realDamage); EventSingle.Instance.Notify(EventDefine.GameMainMapHpAdd, new HpAddDto() { entityId = Context.Entity.EntityId, position = Context.Position, hpValue = damage, elementType = skill.Element, }); //攻击者触发铭文 attacker?.Calculation.TickEpigraph(Context.Entity.EntityId, skill.Element, realDamage); // 受击目标的buff触发 Context.Buffs.TickBuffOrSkill(damage, skill.Element, attacker?.Calculation); } //TODO 攻击者的buff触发 AddSkillBuff(skill, attacker, damage); //TODO 受击者的被动技能 //TODO 攻击者的被动技能 //if (attacker != null && (attacker.Calculation is CombatComponent atkCalculation)) //{ // atkCalculation.TickAttackerPassiveSkill(skill, this); //} } void ICombatCalculation.Damage(int damage, EElementType elementType) { if (Context.Entity.IsDead) { // 已经死亡 return; } damage = CalculateHP(damage); if (damage == 0) return; EventSingle.Instance.Notify(EventDefine.GameMainMapHpAdd, new HpAddDto() { entityId = Context.Entity.EntityId, position = Context.Position, hpValue = damage, elementType = elementType, }); } ICombatCalculation ICombatCalculation.GetSkillTrigger(long skillId, ICombatCalculation attacker) { return GetTrigger(SkillTableRepo.GetTargetType(skillId), attacker); } ICombatCalculation ICombatCalculation.GetBuffTrigger(long buffId, ICombatCalculation attacker) { return GetTrigger(BuffTableRepo.GetTargetType(buffId), attacker); } void ICombatCalculation.TickSkill(long skillId, long targetId, int probability) { // TODO Context.Skill.TryTickSkill((int)skillId, targetId, probability); } void ICombatCalculation.TickBuff(long buffId, int probability, int addLayer, int damage) { Context.Buffs.TryAddBuff(buffId, probability, addLayer, null, damage); } void ICombatCalculation.TickEpigraph(long targetId, EElementType skillElementType, int damage) { Context.Epigraphics?.TryTickIceToPoison(targetId, skillElementType, damage); } #endregion } }