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 _tempTargetList = new List(); 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(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.hitDirType, l, castPos, castDir); var rRank = GetRank(param.hitDirType, 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 hitDirType, GameEntity target, Vector3 castPos, Vector3 castDir) { var targetPos = target.Pos(); var targetDir = targetPos - castPos; switch (hitDirType) { case EHitDirType.Center: //从中心到外围 return targetDir; case EHitDirType.Backward: //从前往后 return -castDir; case EHitDirType.Forward: //从后往前 return castDir; case EHitDirType.Clockwise: //顺时针 return Vector3.Cross(targetDir, Vector3.down * (Owner.move.IsRight ? 1 : -1)); case EHitDirType.CounterClockwise: //逆时针 return Vector3.Cross(targetDir, Vector3.up * (Owner.move.IsRight ? 1 : -1)); } return targetDir; } private float GetRank(EHitDirType hitDirType, GameEntity target, Vector3 castPos, Vector3 castDir) { //小在前 var targetPos = target.Pos(); var targetDir = targetPos - castPos; switch (hitDirType) { case EHitDirType.Center: //按距离 return Vector3.Distance(targetPos, castPos); case EHitDirType.Backward: //从前往后 return -Vector3.Dot(targetDir, castDir); case EHitDirType.Forward: //从后往前 return Vector3.Dot(targetDir, castDir); case EHitDirType.Clockwise: //顺时针 return -GetRankRot(castDir, targetDir); case EHitDirType.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); } } }