|  |  | using Entitas;
 | 
						
						
						
							|  |  | using System.Collections.Generic;
 | 
						
						
						
							|  |  | using UnityEngine;
 | 
						
						
						
							|  |  | using Game;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | public class SettleSystem : IExecuteSystem, IInitializeSystem
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  |     private IGroup<GameEntity> _entities;
 | 
						
						
						
							|  |  |     private readonly List<SkillHitInfo> _tempHitInfo = new List<SkillHitInfo>();
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     public void Initialize()
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         _entities = Util.GetGroup(GameMatcher.Skill);
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     public void Execute()
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         foreach (var entity in _entities)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             SettleSkill(entity.skill);
 | 
						
						
						
							|  |  |             SettleHit(entity.skill);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleSkill(SkillComponent skill)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         foreach (var hitInfo in skill.SkillHitInfo.Values)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             if (hitInfo.IsDealed)
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 continue;
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             hitInfo.IsDealed = true;
 | 
						
						
						
							|  |  |             var isEntity = hitInfo.HitEntity != 0;
 | 
						
						
						
							|  |  |             if (isEntity)
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 var target = Util.GetEntity(hitInfo.HitEntity);
 | 
						
						
						
							|  |  |                 target.skill.HitInfo.Add(hitInfo);
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private void SettleHit(SkillComponent skill)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         while (true)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             _tempHitInfo.Clear();
 | 
						
						
						
							|  |  |             _tempHitInfo.AddRange(skill.HitInfo);
 | 
						
						
						
							|  |  |             skill.HitInfo.Clear();
 | 
						
						
						
							|  |  |             foreach (var hitInfo in _tempHitInfo)
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 var isEntity = hitInfo.HitEntity != 0;
 | 
						
						
						
							|  |  |                 if (!isEntity)
 | 
						
						
						
							|  |  |                 {
 | 
						
						
						
							|  |  |                     continue;
 | 
						
						
						
							|  |  |                 }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |                 var entity = Util.GetEntity(hitInfo.OwnerEntity);
 | 
						
						
						
							|  |  |                 var target = Util.GetEntity(hitInfo.HitEntity);
 | 
						
						
						
							|  |  |                 if (entity == null || target == null)
 | 
						
						
						
							|  |  |                 {
 | 
						
						
						
							|  |  |                     continue;
 | 
						
						
						
							|  |  |                 }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |                 var damageResult = SettleDamage(hitInfo, entity, target); //伤害结算
 | 
						
						
						
							|  |  |                 var hitLevel = SettleHitLevel(hitInfo, damageResult, entity, target); //命中效果等级
 | 
						
						
						
							|  |  |                 var flowSpeed = SettleFlowSpeed(hitInfo, hitLevel, entity, target); //强制位移(击退、击飞、击落等)
 | 
						
						
						
							|  |  |                 SettleSelfMoveForceScale(hitLevel, entity, target); //攻击者移动速度调整
 | 
						
						
						
							|  |  |                 SettleBreak(flowSpeed, hitLevel, damageResult, entity, target); //打断技能/动画
 | 
						
						
						
							|  |  |                 SettleBuff(hitLevel, entity, target); //添加硬直/击晕buff
 | 
						
						
						
							|  |  |                 SettlePause(hitInfo, hitLevel, entity, target); //卡帧
 | 
						
						
						
							|  |  |                 SettleTrigger(hitInfo, entity, target); //命中触发器
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |                 //纯表现
 | 
						
						
						
							|  |  |                 SettleHitText(hitLevel, damageResult, entity, target); //跳字
 | 
						
						
						
							|  |  |                 SettleHitEffect(flowSpeed, hitLevel, entity, target); //命中特效
 | 
						
						
						
							|  |  |                 SettleFlash(hitLevel, entity, target); //闪白
 | 
						
						
						
							|  |  |                 SettleShake(hitLevel, entity, target); //抖动
 | 
						
						
						
							|  |  |                 SettleScale(flowSpeed, entity, target); //抖动
 | 
						
						
						
							|  |  |                 SettleGlobalEffect(hitInfo, hitLevel, damageResult, entity, target); //全局特效
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             if (skill.HitInfo.Count > 0)
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 //结算过程中可能引入新的受击 直接继续结算
 | 
						
						
						
							|  |  |                 continue;
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             break;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     public struct SettleDamageResult
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         public float Damage; //伤害
 | 
						
						
						
							|  |  |         public bool HasShield; //是否结算前有护盾
 | 
						
						
						
							|  |  |         public bool IsSkill; //是否技能造成伤害
 | 
						
						
						
							|  |  |         public bool IsDead; //当次伤害造成死亡
 | 
						
						
						
							|  |  |         public bool IsShieldBreak; //当次伤害破盾
 | 
						
						
						
							|  |  |         public bool IsStun; //当次伤害眩晕
 | 
						
						
						
							|  |  |         public bool IsFlowing; //是否浮空
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static SettleDamageResult SettleDamage(SkillHitInfo hitInfo, GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         var param = hitInfo.SkillParam;
 | 
						
						
						
							|  |  |         var targetHp = target.hp;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         var ret = new SettleDamageResult();
 | 
						
						
						
							|  |  |         ret.IsSkill = !string.IsNullOrEmpty(hitInfo.SkillId);
 | 
						
						
						
							|  |  |         //伤害计算
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             var basicAttack = Util.GetProperty(entity, EProperty.BasicAttack);
 | 
						
						
						
							|  |  |             ret.Damage = basicAttack * param.damageRate * hitInfo.AttackRate;
 | 
						
						
						
							|  |  |             ret.HasShield = targetHp.Shield.Value > 0;
 | 
						
						
						
							|  |  |             if (ret.HasShield)
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 ret.Damage = Mathf.Min(ret.Damage, targetHp.Shield.Value);
 | 
						
						
						
							|  |  |                 targetHp.Shield.Value -= ret.Damage;
 | 
						
						
						
							|  |  |                 ret.IsShieldBreak = targetHp.Shield.Value == 0;
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  |             else
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 ret.Damage = Mathf.Min(ret.Damage, targetHp.Hp.Value);
 | 
						
						
						
							|  |  |                 targetHp.Hp.Value -= ret.Damage;
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             targetHp.IsDamaged.Value = true;
 | 
						
						
						
							|  |  |             //刷新护盾恢复cd
 | 
						
						
						
							|  |  |             target.hp.ShieldRecoverTime = target.hp.ShieldRecoverTimeMax;
 | 
						
						
						
							|  |  |             //刷新眩晕恢复cd
 | 
						
						
						
							|  |  |             target.hp.StunRecoverTime = target.hp.StunRecoverTimeMax;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         //异常值积累
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             if (targetHp.StunMax.Value > targetHp.Stun.Value)
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 //眩晕
 | 
						
						
						
							|  |  |                 var basicStun = Util.GetProperty(entity, EProperty.BasicStun);
 | 
						
						
						
							|  |  |                 var damageStun = basicStun * param.stunRate * hitInfo.StunkRate;
 | 
						
						
						
							|  |  |                 damageStun = Mathf.Min(damageStun, targetHp.StunMax.Value - targetHp.Stun.Value);
 | 
						
						
						
							|  |  |                 targetHp.Stun.Value += damageStun;
 | 
						
						
						
							|  |  |                 if (targetHp.Stun.Value >= targetHp.StunMax.Value)
 | 
						
						
						
							|  |  |                 {
 | 
						
						
						
							|  |  |                     ret.IsStun = true;
 | 
						
						
						
							|  |  |                     targetHp.Stun.Value = 0;
 | 
						
						
						
							|  |  |                     Util.AddStunBuff(target.ID());
 | 
						
						
						
							|  |  |                 }
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         //浮空判定 目标不在地面 或者可以从地面浮空
 | 
						
						
						
							|  |  |         if (!target.move.IsGround || param.isFlow)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             ret.IsFlowing = true;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         //实体死亡
 | 
						
						
						
							|  |  |         if (targetHp.IsAlive && targetHp.Hp.Value == 0)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             ret.IsDead = true;
 | 
						
						
						
							|  |  |             Util.EntityDie(target);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         return ret;
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static EHitLevel SettleHitLevel(SkillHitInfo hitInfo, SettleDamageResult dmgResult, GameEntity entity,
 | 
						
						
						
							|  |  |         GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         if (!dmgResult.IsSkill)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             return EHitLevel.None;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if (dmgResult.IsDead)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             return EHitLevel.Kill;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if (dmgResult.IsShieldBreak)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             return EHitLevel.ShieldBreak;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if (dmgResult.IsStun)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             return EHitLevel.Stun;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         var staggerDef = Util.GetProperty(target, EProperty.StaggerDefLevel);
 | 
						
						
						
							|  |  |         if (dmgResult.HasShield)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             staggerDef += Util.GetProperty(target, EProperty.ShieldStaggerDefLevel);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         var sub = hitInfo.StaggerLevel - staggerDef;
 | 
						
						
						
							|  |  |         sub = Mathf.Clamp(sub, 0, 3);
 | 
						
						
						
							|  |  |         var ret = EHitLevel.None;
 | 
						
						
						
							|  |  |         switch (sub)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             case 0:
 | 
						
						
						
							|  |  |                 ret = EHitLevel.Block;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case 1:
 | 
						
						
						
							|  |  |                 ret = EHitLevel.Stagger1;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case 2:
 | 
						
						
						
							|  |  |                 ret = EHitLevel.Stagger2;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case 3:
 | 
						
						
						
							|  |  |                 ret = EHitLevel.Stagger3;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if (ret > EHitLevel.Block)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             if (dmgResult.IsFlowing)
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 return EHitLevel.Flowing;
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             if (target.hp.LastDamageLevel == EHitLevel.Stagger3)
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 //后仰升级为浮空
 | 
						
						
						
							|  |  |                 return EHitLevel.Flowing;
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         return ret;
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static Vector3 SettleFlowSpeed(SkillHitInfo hitInfo, EHitLevel hitLevel, GameEntity entity,
 | 
						
						
						
							|  |  |         GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         var param = hitInfo.SkillParam;
 | 
						
						
						
							|  |  |         //浮空数值
 | 
						
						
						
							|  |  |         var flowSpeed = new Vector3(param.flowSpeed.x, param.flowSpeed.y,
 | 
						
						
						
							|  |  |             param.flowSpeed.z * GameRandom.RollSymbol(0.5f));
 | 
						
						
						
							|  |  |         var rot = Quaternion.FromToRotation(Vector3.right, hitInfo.HitDir);
 | 
						
						
						
							|  |  |         flowSpeed = rot * flowSpeed;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if (hitInfo.IsBreak)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             //近距离推开
 | 
						
						
						
							|  |  |             //根据实体xz距离调整xz浮空速度,距离为0时系数为1.5,距离大于0.5时系数为1
 | 
						
						
						
							|  |  |             var flowSpeedXZ = new Vector3(flowSpeed.x, 0, flowSpeed.z);
 | 
						
						
						
							|  |  |             var dist = Util.EntityDistanceXZ(entity, target);
 | 
						
						
						
							|  |  |             flowSpeedXZ *= Mathf.Clamp(1.5f - dist, 1, 2);
 | 
						
						
						
							|  |  |             flowSpeed = new Vector3(flowSpeedXZ.x, flowSpeed.y, flowSpeedXZ.z);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if (hitLevel >= EHitLevel.Flowing)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             target.move.IsFlowing = true;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |         else
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             flowSpeed = new Vector3(flowSpeed.x, 0, flowSpeed.z);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         //根据命中等级调整系数
 | 
						
						
						
							|  |  |         switch (hitLevel)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             case EHitLevel.Block:
 | 
						
						
						
							|  |  |                 flowSpeed *= 0.2f;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Stagger1:
 | 
						
						
						
							|  |  |                 flowSpeed *= 0.7f;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Stagger2:
 | 
						
						
						
							|  |  |                 flowSpeed *= 1f;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Stagger3:
 | 
						
						
						
							|  |  |                 flowSpeed *= 1.2f;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         //记录受击方向 添加强制移动buff
 | 
						
						
						
							|  |  |         if (flowSpeed != Vector3.zero)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             target.hp.LastDamageDir = flowSpeed;
 | 
						
						
						
							|  |  |             if (flowSpeed.y < 0)
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 //击落
 | 
						
						
						
							|  |  |                 Util.AddHitDownBuff(target.ID());
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             //击退
 | 
						
						
						
							|  |  |             Util.AddSetSpeedBuff(target.ID(), param.flowTime);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         target.hp.LastDamageLevel = hitLevel;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         //命中瞬间、在pause之前生效部分位移
 | 
						
						
						
							|  |  |         var move = target.move;
 | 
						
						
						
							|  |  |         move.Transform.position += flowSpeed * Time.deltaTime * 2;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         return flowSpeed;
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettlePause(SkillHitInfo hitInfo, EHitLevel hitLevel, GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         if (target.IsMaster())
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             //主角受击不卡帧
 | 
						
						
						
							|  |  |             return;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         var param = hitInfo.SkillParam;
 | 
						
						
						
							|  |  |         var pauseTime = param.pauseTime;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if (hitLevel >= EHitLevel.ShieldBreak)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             pauseTime = Mathf.Max(pauseTime, 0.05f);
 | 
						
						
						
							|  |  |             //受击方向
 | 
						
						
						
							|  |  |             var dir = target.hp.LastDamageDir;
 | 
						
						
						
							|  |  |             //受击方向与实体方向夹角
 | 
						
						
						
							|  |  |             var angle = Vector3.Angle(dir, target.move.Transform.forward);
 | 
						
						
						
							|  |  |             //夹角越大,卡帧越长
 | 
						
						
						
							|  |  |             pauseTime *= Mathf.Clamp(1.5f - angle / 180, 0.5f, 1);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         //根据命中等级调整系数
 | 
						
						
						
							|  |  |         switch (hitLevel)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             case EHitLevel.ShieldBreak:
 | 
						
						
						
							|  |  |                 pauseTime *= 1.5f;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Block:
 | 
						
						
						
							|  |  |                 pauseTime *= 1.2f;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Kill:
 | 
						
						
						
							|  |  |                 pauseTime *= 1.5f;
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         Util.EntityPause(entity, pauseTime);
 | 
						
						
						
							|  |  |         Util.EntityPause(target, pauseTime);
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleSelfMoveForceScale(EHitLevel hitLevel, GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         switch (hitLevel)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             case EHitLevel.Stagger1:
 | 
						
						
						
							|  |  |             case EHitLevel.Stagger2:
 | 
						
						
						
							|  |  |             case EHitLevel.Stagger3:
 | 
						
						
						
							|  |  |                 Util.EntitySetTempMoveForceScale(entity.ID(), -0.8f);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Block:
 | 
						
						
						
							|  |  |                 Util.EntitySetTempMoveForceScale(entity.ID(), -1.2f);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleBreak(Vector3 flowSpeed, EHitLevel hitLevel, SettleDamageResult dmgResult,
 | 
						
						
						
							|  |  |         GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         //打断技能
 | 
						
						
						
							|  |  |         if (hitLevel > EHitLevel.Block)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             Util.EndSkillTimeline(target);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         //强制转向
 | 
						
						
						
							|  |  |         if (hitLevel > EHitLevel.Stagger2)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             Util.EntityTurn(target, flowSpeed.x < 0);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         //受击动画
 | 
						
						
						
							|  |  |         if (dmgResult.IsFlowing)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             if (hitLevel > EHitLevel.Block)
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 target.animation.AirHitMsg = true;
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |         else
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             if (Util.HasStunBuff(target.ID()))
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 if (hitLevel > EHitLevel.Stun)
 | 
						
						
						
							|  |  |                     target.animation.AirHitMsg = true;
 | 
						
						
						
							|  |  |                 else if (hitLevel > EHitLevel.Block)
 | 
						
						
						
							|  |  |                     target.animation.StunHitMsg = true;
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  |             else
 | 
						
						
						
							|  |  |             {
 | 
						
						
						
							|  |  |                 switch (hitLevel)
 | 
						
						
						
							|  |  |                 {
 | 
						
						
						
							|  |  |                     case EHitLevel.Stagger1:
 | 
						
						
						
							|  |  |                         target.animation.HitMsg = true;
 | 
						
						
						
							|  |  |                         break;
 | 
						
						
						
							|  |  |                     case EHitLevel.Stagger2:
 | 
						
						
						
							|  |  |                         target.animation.MHitMsg = true;
 | 
						
						
						
							|  |  |                         break;
 | 
						
						
						
							|  |  |                     case EHitLevel.Stagger3:
 | 
						
						
						
							|  |  |                         target.animation.LHitMsg = true;
 | 
						
						
						
							|  |  |                         break;
 | 
						
						
						
							|  |  |                     case EHitLevel.ShieldBreak:
 | 
						
						
						
							|  |  |                     case EHitLevel.Stun:
 | 
						
						
						
							|  |  |                         target.animation.StunHitMsg = true;
 | 
						
						
						
							|  |  |                         break;
 | 
						
						
						
							|  |  |                     case EHitLevel.Flowing:
 | 
						
						
						
							|  |  |                     case EHitLevel.Kill:
 | 
						
						
						
							|  |  |                         target.animation.AirHitMsg = true;
 | 
						
						
						
							|  |  |                         break;
 | 
						
						
						
							|  |  |                 }
 | 
						
						
						
							|  |  |             }
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleBuff(EHitLevel hitLevel, GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         switch (hitLevel)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             case EHitLevel.Stagger1:
 | 
						
						
						
							|  |  |                 Util.AddStaggerBuff(target.ID(), 0.2f);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Stagger2:
 | 
						
						
						
							|  |  |                 Util.AddStaggerBuff(target.ID(), 0.5f);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Stagger3:
 | 
						
						
						
							|  |  |                 Util.AddStaggerBuff(target.ID(), 1f);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Flowing:
 | 
						
						
						
							|  |  |                 Util.AddStaggerBuff(target.ID(), -1f);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.ShieldBreak:
 | 
						
						
						
							|  |  |             case EHitLevel.Stun:
 | 
						
						
						
							|  |  |                 Util.AddStunBuff(target.ID());
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleTrigger(SkillHitInfo hitInfo, GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         //触发buffTrigger
 | 
						
						
						
							|  |  |         UtilBuff.BuffEffectAll(target.ID(), EBuffEffectTimingType.BeAttack);
 | 
						
						
						
							|  |  |         if (((hitInfo.Performance & (1 << ((int)ESKillPerformance.Heavy - 1))) != 0) ||
 | 
						
						
						
							|  |  |             (hitInfo.Performance & (1 << ((int)ESKillPerformance.Floating - 1))) != 0)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             UtilBuff.BuffEffectAll(target.ID(), EBuffEffectTimingType.BeAttackHeavy);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         //触发SkillTrigger
 | 
						
						
						
							|  |  |         UtilSkillTrigger.Trigger(entity.ID(), target.ID(), hitInfo.SkillId, ESkillTriggerTimingType.Hit);
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleHitText(EHitLevel hitLevel, SettleDamageResult dmgResult, GameEntity entity,
 | 
						
						
						
							|  |  |         GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         //受击事件广播
 | 
						
						
						
							|  |  |         var hitMsg = new PEntityHit()
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             Entity = entity.ID(),
 | 
						
						
						
							|  |  |             Target = target.ID(),
 | 
						
						
						
							|  |  |             Dmg = (int)dmgResult.Damage,
 | 
						
						
						
							|  |  |             IsSkill = dmgResult.IsSkill,
 | 
						
						
						
							|  |  |         };
 | 
						
						
						
							|  |  |         EventManager.Instance.SendEvent<PEntityHit>(EEvent.EntityHit, hitMsg);
 | 
						
						
						
							|  |  |         switch (hitLevel)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             case EHitLevel.ShieldBreak:
 | 
						
						
						
							|  |  |                 //破盾事件广播
 | 
						
						
						
							|  |  |                 var breakmsg = new PEntityHitText()
 | 
						
						
						
							|  |  |                 {
 | 
						
						
						
							|  |  |                     Target = target.ID(),
 | 
						
						
						
							|  |  |                     Text = "Break",
 | 
						
						
						
							|  |  |                 };
 | 
						
						
						
							|  |  |                 EventManager.Instance.SendEvent<PEntityHitText>(EEvent.EntityHitText, breakmsg);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             // case EHitLevel.Block:
 | 
						
						
						
							|  |  |             //     //格挡事件广播
 | 
						
						
						
							|  |  |             //     var blockmsg = new PEntityHitText()
 | 
						
						
						
							|  |  |             //     {
 | 
						
						
						
							|  |  |             //         target = target.ID(),
 | 
						
						
						
							|  |  |             //         text = "Block",
 | 
						
						
						
							|  |  |             //     };
 | 
						
						
						
							|  |  |             //     EventManager.instance.SendEvent<PEntityHitText>(EEvent.EntityHitText, blockmsg);
 | 
						
						
						
							|  |  |             //     break;
 | 
						
						
						
							|  |  |             // default:
 | 
						
						
						
							|  |  |             //     //测试
 | 
						
						
						
							|  |  |             //     var msg = new PEntityHitText()
 | 
						
						
						
							|  |  |             //     {
 | 
						
						
						
							|  |  |             //         target = target.ID(),
 | 
						
						
						
							|  |  |             //         text = hitLevel.ToString(),
 | 
						
						
						
							|  |  |             //     };
 | 
						
						
						
							|  |  |             //     EventManager.instance.SendEvent<PEntityHitText>(EEvent.EntityHitText, msg);
 | 
						
						
						
							|  |  |             //     break;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleHitEffect(Vector3 flowSpeed, EHitLevel hitLevel, GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         //受击特效
 | 
						
						
						
							|  |  |         var effectRot = GameRandom.RandomRot(Util.Vec3ToRot(new Vector3(flowSpeed.x, 0, flowSpeed.y)), 45);
 | 
						
						
						
							|  |  |         switch (hitLevel)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             case EHitLevel.Kill:
 | 
						
						
						
							|  |  |                 Util.CastHitEffect(GameConst.EffectHitKill, target.ID(), effectRot);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.ShieldBreak:
 | 
						
						
						
							|  |  |                 Util.CastHitEffect(GameConst.EffectHitShieldBreak, target.ID(), effectRot);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Block:
 | 
						
						
						
							|  |  |                 Util.CastHitEffect(GameConst.EffectHitShield, target.ID(), effectRot);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             default:
 | 
						
						
						
							|  |  |                 Util.CastHitEffect(GameConst.EffectHit, target.ID(), effectRot);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleFlash(EHitLevel hitLevel, GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         switch (hitLevel)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             case EHitLevel.ShieldBreak:
 | 
						
						
						
							|  |  |                 Util.EntityFlash(target, Color.red);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             case EHitLevel.Block:
 | 
						
						
						
							|  |  |                 Util.EntityFlash(target, Color.yellow);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |             default:
 | 
						
						
						
							|  |  |                 Util.EntityFlash(target);
 | 
						
						
						
							|  |  |                 break;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleShake(EHitLevel hitLevel, GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         Util.EntityShake(target, 3);
 | 
						
						
						
							|  |  |         Util.EntityShake(entity, 2);
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleScale(Vector3 flowSpeed, GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         var dir = new Vector3(flowSpeed.x * (target.move.IsRight ? 1 : -1), flowSpeed.y, 0);
 | 
						
						
						
							|  |  |         Util.EntityScale(target, dir);
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private static void SettleGlobalEffect(SkillHitInfo hitInfo, EHitLevel hitLevel, SettleDamageResult dmgResult,
 | 
						
						
						
							|  |  |         GameEntity entity, GameEntity target)
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         if (target.IsMaster())
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             //主角受击
 | 
						
						
						
							|  |  |             Util.SetTimeScaleEffect(0.2f, 1, 0.5f);
 | 
						
						
						
							|  |  |             Util.SetAberrationEffect(1, 0, 0.5f);
 | 
						
						
						
							|  |  |             Util.SetFovEffect(0.9f, 1, 0.5f);
 | 
						
						
						
							|  |  |             return;
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         var pauseTime = hitInfo.SkillParam.pauseTime;
 | 
						
						
						
							|  |  |         if (pauseTime >= 0.1f)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             Util.Shake();
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             var (aberrationFrom, aberrationTo) = (0.5f, 0);
 | 
						
						
						
							|  |  |             var (timeScaleFrom, timeScaleTo) = (0.2f, 1);
 | 
						
						
						
							|  |  |             var (fovFrom, fovTo) = (0.85f, 1);
 | 
						
						
						
							|  |  |             var effectTime = pauseTime + 0.2f;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             Util.SetAberrationEffect(aberrationFrom, aberrationFrom, pauseTime);
 | 
						
						
						
							|  |  |             Util.AppendAberrationEffect(aberrationFrom, aberrationTo, 0.3f);
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             // Util.SetTimeScaleEffect(timeScaleFrom, timeScaleFrom, pauseTime);
 | 
						
						
						
							|  |  |             // Util.AppendTimeScaleEffect(timeScaleFrom, timeScaleTo, 0.5f);
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             Util.SetFovEffect(fovFrom, fovFrom, pauseTime);
 | 
						
						
						
							|  |  |             Util.AppendFovEffect(fovFrom, fovTo, 0.5f);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |         else if (pauseTime > 0)
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             Util.SetAberrationEffect(0.2f, 0, 0.2f);
 | 
						
						
						
							|  |  |             Util.SetFovEffect(0.99f, 1, 0.2f);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |         else
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |             Util.SetAberrationEffect(0.2f, 0, 0.2f);
 | 
						
						
						
							|  |  |             Util.SetFovEffect(0.99f, 1, 0.2f);
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  | } |