|  |  |  | using System; | 
					
						
							|  |  |  | using System.Collections.Generic; | 
					
						
							|  |  |  | using UnityEngine; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Game | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     public class SkillHitInfo | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         public AttackBehaviour SkillParam; | 
					
						
							|  |  |  |         public Vector3 HitDir; | 
					
						
							|  |  |  |         public int OwnerEntity; | 
					
						
							|  |  |  |         public int HitEntity; //0为非实体对象 | 
					
						
							|  |  |  |         public float AttackRate; | 
					
						
							|  |  |  |         public float StunkRate; | 
					
						
							|  |  |  |         public string SkillId; //是否技能造成的伤害 | 
					
						
							|  |  |  |         public bool IsBreak; | 
					
						
							|  |  |  |         public int hitIndex; | 
					
						
							|  |  |  |         public int hitCount; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public class ClipAttack : TimelineClipBase | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         private AttackClip _mRealAsset; | 
					
						
							|  |  |  |         private List<GameEntity> _tempTargetList = new List<GameEntity>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public override void OnEnter() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             _mRealAsset = Asset as AttackClip; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public override void OnStay() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             var param = _mRealAsset.template; | 
					
						
							|  |  |  |             var skill = Owner.skill; | 
					
						
							|  |  |  |             var castShape = param.Shape; | 
					
						
							|  |  |  |             var castDir = skill.CastDir; | 
					
						
							|  |  |  |             castDir = new Vector3(castDir.x, 0, castDir.z); //忽略y | 
					
						
							|  |  |  |             var rot = Quaternion.FromToRotation(Vector3.right, castDir); | 
					
						
							|  |  |  |             var castPos = rot * castShape.Offset + Owner.Pos(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             Util.DrawShape(castShape, castPos, castDir, Color.red); | 
					
						
							|  |  |  |             _tempTargetList.Clear(); | 
					
						
							|  |  |  |             Util.ForeachEnemies(Owner.Team(), target => | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 var isHit = UtilShape.IsOverlap(castShape, castPos, castDir, target.hp.HitBoxShape, target.Pos()); | 
					
						
							|  |  |  |                 if (!isHit) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 var hitKey = new Tuple<int, int>(target.ID(), param.hitId); | 
					
						
							|  |  |  |                 if (skill.HitSet.Contains(hitKey)) return; | 
					
						
							|  |  |  |                 skill.HitSet.Add(hitKey); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 _tempTargetList.Add(target); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |             _tempTargetList.Sort((l, r) => | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 var lRank = GetRank(param.hitOrderType, l, castPos, castDir); | 
					
						
							|  |  |  |                 var rRank = GetRank(param.hitOrderType, r, castPos, castDir); | 
					
						
							|  |  |  |                 return lRank.CompareTo(rRank); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |             var hitNum = _tempTargetList.Count; | 
					
						
							|  |  |  |             for (var i = 0; i < hitNum; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 var target = _tempTargetList[i]; | 
					
						
							|  |  |  |                 var targetID = target.ID(); | 
					
						
							|  |  |  |                 var skillHitInfo = new SkillHitInfo | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     SkillParam = param, | 
					
						
							|  |  |  |                     AttackRate = 1, | 
					
						
							|  |  |  |                     StunkRate = 1, | 
					
						
							|  |  |  |                     OwnerEntity = Owner.ID(), | 
					
						
							|  |  |  |                     HitEntity = targetID, | 
					
						
							|  |  |  |                     HitDir = GetHitDir(param.hitDirType, target, castPos, castDir), | 
					
						
							|  |  |  |                     SkillId = skill.SkillId.Value, | 
					
						
							|  |  |  |                     IsBreak = true, | 
					
						
							|  |  |  |                     hitIndex = i, | 
					
						
							|  |  |  |                     hitCount = hitNum | 
					
						
							|  |  |  |                 }; | 
					
						
							|  |  |  |                 if (!string.IsNullOrEmpty(skillHitInfo.SkillId)) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     var skillCfg = Util.GetSkillMasterConfigData(skillHitInfo.SkillId); | 
					
						
							|  |  |  |                     if (skillCfg != null) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         var featureSkill = skillCfg.GetFeatureSkill(); | 
					
						
							|  |  |  |                         skillHitInfo.AttackRate = featureSkill.AttackRate; | 
					
						
							|  |  |  |                         skillHitInfo.StunkRate = featureSkill.StunRate; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 skill.HitInfo.Enqueue(skillHitInfo); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private Vector3 GetHitDir(EHitDirType hitOrderType, GameEntity target, Vector3 castPos, Vector3 castDir) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             var targetPos = target.Pos(); | 
					
						
							|  |  |  |             var targetDir = targetPos - castPos; | 
					
						
							|  |  |  |             targetDir.y = 0; | 
					
						
							|  |  |  |             switch (hitOrderType) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 case EHitDirType.Center: | 
					
						
							|  |  |  |                     //从中心到外围 | 
					
						
							|  |  |  |                     return targetDir; | 
					
						
							|  |  |  |                 case EHitDirType.Backward: | 
					
						
							|  |  |  |                     //从前往后 | 
					
						
							|  |  |  |                     return -castDir; | 
					
						
							|  |  |  |                 case EHitDirType.Forward: | 
					
						
							|  |  |  |                     //从后往前 | 
					
						
							|  |  |  |                     return castDir; | 
					
						
							|  |  |  |                 case EHitDirType.Clockwise: | 
					
						
							|  |  |  |                     //顺时针 | 
					
						
							|  |  |  |                     return GetDirRot(targetDir, true); | 
					
						
							|  |  |  |                 case EHitDirType.CounterClockwise: | 
					
						
							|  |  |  |                     //逆时针 | 
					
						
							|  |  |  |                     return GetDirRot(targetDir, false); | 
					
						
							|  |  |  |                 case EHitDirType.CenterForward: | 
					
						
							|  |  |  |                     //中心向前 | 
					
						
							|  |  |  |                     return targetDir + castDir; | 
					
						
							|  |  |  |                 case EHitDirType.ClockwiseForward: | 
					
						
							|  |  |  |                     //顺时针向前 | 
					
						
							|  |  |  |                     return GetDirRot(targetDir, true) + castDir; | 
					
						
							|  |  |  |                 case EHitDirType.CounterClockwiseForward: | 
					
						
							|  |  |  |                     //逆时针向前 | 
					
						
							|  |  |  |                     return GetDirRot(targetDir, false) + castDir; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return targetDir; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private Vector3 GetDirRot(Vector3 targetDir, bool isClockwise) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             var sub = (Owner.move.IsRight ? -1 : 1) * (isClockwise ? 1 : -1); | 
					
						
							|  |  |  |             return Vector3.Cross(targetDir, Vector3.up * sub).normalized; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private float GetRank(EHitOrderType hitOrderType, GameEntity target, Vector3 castPos, Vector3 castDir) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             //小在前 | 
					
						
							|  |  |  |             var targetPos = target.Pos(); | 
					
						
							|  |  |  |             var targetDir = targetPos - castPos; | 
					
						
							|  |  |  |             switch (hitOrderType) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 case EHitOrderType.Center: | 
					
						
							|  |  |  |                     //按距离 | 
					
						
							|  |  |  |                     return Vector3.Distance(targetPos, castPos); | 
					
						
							|  |  |  |                 case EHitOrderType.Backward: | 
					
						
							|  |  |  |                     //从前往后 | 
					
						
							|  |  |  |                     return -Vector3.Dot(targetDir, castDir); | 
					
						
							|  |  |  |                 case EHitOrderType.Forward: | 
					
						
							|  |  |  |                     //从后往前 | 
					
						
							|  |  |  |                     return Vector3.Dot(targetDir, castDir); | 
					
						
							|  |  |  |                 case EHitOrderType.Clockwise: | 
					
						
							|  |  |  |                     //顺时针 | 
					
						
							|  |  |  |                     return -GetRankRot(castDir, targetDir); | 
					
						
							|  |  |  |                 case EHitOrderType.CounterClockwise: | 
					
						
							|  |  |  |                     //逆时针 | 
					
						
							|  |  |  |                     return GetRankRot(castDir, targetDir); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private float GetRankRot(Vector3 castDir, Vector3 targetDir) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             var rot = Quaternion.FromToRotation(-castDir, Vector3.right); | 
					
						
							|  |  |  |             return Util.Vec3ToRot(rot * targetDir) * (Owner.move.IsRight ? 1 : -1); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |