123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- 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; }
- /// <summary>
- /// 铭文组件
- /// 可能为空
- /// </summary>
- EpigraphicsComponent Epigraphics { get; }
- }
- public class CombatComponent : Component<ICombatContext>, ICombatCalculation
- {
- protected override void OnDispose()
- {
- }
- /// <summary>
- /// 计算血量
- /// 正数表示加血
- /// 负数表示扣血
- /// </summary>
- /// <param name="damage"></param>
- /// <returns></returns>
- 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);
- }
- }
- /// <summary>
- /// 根据技能/Buff的目标类型确定触发目标
- /// </summary>
- /// <param name="targetType"></param>
- /// <param name="attacker"></param>
- /// <returns></returns>
- 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
- }
- }
|