|  |  |  |  | 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); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | } |