/// <summary> /// 检查技能释放 /// </summary> /// <param name="fsm"></param> /// <returns></returns> public static bool CheckSkillRelease(SoldierFSMSystem fsm) { var searchData = fsm.Display.ClusterData; // 攻击范围内是否有敌人 var checkPos = new Vector2(fsm.Display.ClusterData.X, fsm.Display.ClusterData.Y); // 不可释放技能 if (!searchData.AllData.MemberData.CouldReleaseSkill) { return(false); } var list = TargetSelecter.TargetFilter(searchData, ClusterManager.Single.CheckRange(checkPos, searchData.AllData.MemberData.SkillRange, searchData.AllData.MemberData.Camp, true)); Utils.DrawGraphics(new CircleGraphics(checkPos, searchData.AllData.MemberData.SkillRange), Color.yellow); if (list != null && list.Count > 0) { // 攻击目标 fsm.TargetIsLoseEfficacy = false; // 检测技能 // TODO 技能的单位列表根据单位范围进行筛选 if (CheckSkill(fsm, list)) { fsm.IsCanInPutonggongji = false; fsm.IsCanInJinenggongji = true; return(true); } } return(false); }
/// <summary> /// 单元搜寻目标 /// </summary> private void ScanTarget() { // 遍历对象, //foreach (var item in MemberList.List) //{ var item = _leader; var memberData = item.AllData.MemberData; // 根据对象的搜寻外径获取对向列表 var itemRect = new RectGraphics(new Vector2(item.X, item.Y), memberData.AttackRange, memberData.AttackRange, 0); Utils.DrawGraphics(itemRect, Color.red); // 根据策略筛选目标 var targetList = TargetSelecter.TargetFilter(item, MemberList.QuadTree); // 连线 foreach (var targetItem in targetList) { Debug.DrawLine(new Vector3(item.X, 0, item.Y), new Vector3(targetItem.X, 0, targetItem.Y)); } foreach (var memberItem in MemberList.List) { if (TargetSelecter.IsCollisionItem(memberItem, item.X, item.Y, memberData.AttackRange * 0.5f)) { Utils.DrawRect(new Vector3(memberItem.X, 0, memberItem.Y), memberData.SpaceSet + 1, memberData.SpaceSet + 1, 0, Color.red); } } Utils.DrawCircle(new Vector3(item.X, 0, item.Y), memberData.AttackRange * 0.5f, Color.red); //} }
/// <summary> /// 设置扫描单位 /// </summary> private void Scan() { if (scaner != null) { var resultList = TargetSelecter.GetCollisionItemList(itemList, scaner.X, scaner.Y, scaner.AllData.MemberData.AttackRange * 0.5f); Utils.DrawCircle(new Vector3(scaner.X, 0, scaner.Y), scaner.AllData.MemberData.AttackRange * 0.5f, Color.white); for (var i = 0; i < resultList.Count; i++) { var item = resultList[i]; Utils.DrawCircle(new Vector3(item.X, 0, item.Y), item.AllData.MemberData.SpaceSet * 0.5f, Color.white); } } }
/// <summary> /// 是否可以技能攻击 /// </summary> /// <param name="fsm"></param> /// <param name="res">目标列表</param> /// <returns></returns> public static bool CheckSkill(SoldierFSMSystem fsm, IList <PositionObject> res) { var result = false; // 判断主动技能是否可释放, 可释放则释放技能, 否则普通攻击 var skillInfoList = fsm.Display.ClusterData.AllData.SkillInfoList; if (skillInfoList.Count > 0) { // 判断技能CD的长短, 释放技能最长的 foreach (var skill in skillInfoList) { // 技能目标选择器 // 是否为主动技能 // 技能没有在CD中 if (!skill.IsActive || CDTimer.Instance().IsInCD(skill.Num, fsm.Display.ClusterData.AllData.MemberData.ObjID.ID, skill.CDGroup)) { continue; } // 判断技能是否符合释放条件(范围内有适合的单位) if (skill.WeightData != null) { res = TargetSelecter.TargetFilter(skill.WeightData, skill.ReleaseMember.ClusterData, res); } if (res != null && res.Count > 0) { fsm.Skill = skill; result = true; break; } } } if (result) { // 确定释放技能, 设置目标 //System.Random ran = new System.Random(); var target = res[0]; fsm.EnemyTarget = DisplayerManager.Single.GetElementByPositionObject(target); } return(result); }
///// <summary> ///// 检测条件 ///// </summary> ///// <param name="fsm"></param> ///// <returns></returns> //public override bool CheckTrigger(SoldierFSMSystem fsm) //{ // return Check(fsm); //} public static bool Check(SoldierFSMSystem fsm) { switch (fsm.CurrentStateID) { // 行进切追击 case SoldierStateID.Xingjin: { // 如果正在技能攻击或普通攻击则不进入追击状态 if (fsm.IsCanInJinenggongji || fsm.IsCanInPutonggongji) { return(false); } var clusterData = fsm.Display.ClusterData; //var objId = clusterData.MemberData.ObjID; // 视野范围内是否有敌人 var pos = new Vector2(clusterData.X, clusterData.Y); // 范围内符合阵营条件的单位列表 var scopeMemberList = ClusterManager.Single.CheckRange(pos, clusterData.AllData.MemberData.SightRange, clusterData.AllData.MemberData.Camp, true); // 按照权重与是否可攻击单位选择 var filtedlist = TargetSelecter.TargetFilter(clusterData, scopeMemberList); Utils.DrawGraphics(new CircleGraphics(pos, clusterData.AllData.MemberData.SightRange), Color.yellow); //fsm.Display.ClusterData.MemberData.SightRange if (filtedlist != null && filtedlist.Count > 0) { // 追击目标 // 设置状态 切追击状态 fsm.IsZhuiJi = true; return(SetTarget(fsm, filtedlist)); } return(fsm.IsZhuiJi); } } return(false); }
/// <summary> /// 检查普通攻击 /// </summary> /// <param name="fsm"></param> /// <returns></returns> public static bool CheckNormalAttack(SoldierFSMSystem fsm) { var searchData = fsm.Display.ClusterData; // 攻击范围内是否有敌人 var checkPos = new Vector2(fsm.Display.ClusterData.X, fsm.Display.ClusterData.Y); // 目标选择器选择目标列表 var list = TargetSelecter.TargetFilter(searchData, ClusterManager.Single.CheckRange(checkPos, searchData.AllData.MemberData.AttackRange, searchData.AllData.MemberData.Camp, true)); Utils.DrawGraphics(new CircleGraphics(checkPos, searchData.AllData.MemberData.AttackRange), Color.yellow); if (list != null && list.Count > 0) { // 攻击目标 fsm.TargetIsLoseEfficacy = false; // 检测普通攻击 if (SetTarget(fsm, list)) { fsm.IsCanInJinenggongji = false; fsm.IsCanInPutonggongji = true; return(true); } } return(false); }
/// <summary> /// 生成行为单元 /// </summary> /// <returns>行为单元对象</returns> public override IFormula GetFormula(FormulaParamsPacker paramsPacker) { if (paramsPacker == null) { return(null); } IFormula result = null; // 替换替换符的数据 ReplaceData(paramsPacker); // 数据本地化 var myReceivePos = ReceivePos; var myTargetCamps = TargetCamps; var clusterData = paramsPacker.ReleaseMember.ClusterData; var myFormulaType = FormulaType; var myScopeType = ScopeType; var myTargetCount = TargetCount; var myIsFollowDir = IsFollowDir; // 目标权重筛选数据 var targetSelectData = TargetSelectDataId > 0 ? new SelectWeightData(SData_armyaim_c.Single.GetDataOfID(TargetSelectDataId)) : null; result = new Formula((callback, scope) => { // 检测范围 ICollisionGraphics graphics = null; var pos = Utils.V3ToV2WithouY(GetPosByType(myReceivePos, paramsPacker, scope)); var plusAngle = 0f; if (myIsFollowDir) { plusAngle = Utils.GetAngleWithZ(clusterData.Direction); } // 获取图形对象 switch (myScopeType) { case GraphicType.Circle: // 圆形 graphics = new CircleGraphics(pos, Arg1); break; case GraphicType.Rect: // 矩形 graphics = new RectGraphics(pos, Arg1, Arg2, Arg3 + plusAngle); break; case GraphicType.Sector: // 扇形 graphics = new SectorGraphics(pos, Arg3 + plusAngle, Arg1, Arg2); break; } // 获取周围单位DisplayOwner列表 var packerList = FormulaParamsPackerFactroy.Single.GetFormulaParamsPackerList(graphics, paramsPacker.StartPos, myTargetCamps, paramsPacker.Skill, paramsPacker.TargetMaxCount); // 根据权重数据筛选目标 if (targetSelectData != null) { packerList = TargetSelecter.TargetFilter(targetSelectData, clusterData, packerList); // 对他们释放技能(技能编号) if (packerList != null) { var counter = 0; var completeCount = 0; var allCount = packerList.Count; foreach (var packer in packerList) { // 如果设置了数量上限, 并且超过数量上限则跳出 if (myTargetCount > 0 && counter >= myTargetCount) { break; } // 执行子行为链 if (SubFormulaItem != null) { var subSkill = new SkillInfo(packer.SkillNum); FormulaParamsPackerFactroy.Single.CopyPackerData(paramsPacker, packer); subSkill.DataList = packer.DataList; subSkill.AddActionFormulaItem(SubFormulaItem); //subSkill.GetFormula(packer); SkillManager.Single.DoSkillInfo(subSkill, packer, true, () => { // 执行完成, 回调 completeCount++; if (completeCount >= myTargetCount || completeCount >= allCount) { callback(); } }); } counter++; } } } }, myFormulaType); return(result); }
/// <summary> /// 获取行为节点 /// </summary> /// <param name="paramsPacker">目标数据</param> /// <returns>滑动碰撞检测行为节点</returns> public override IFormula GetFormula(FormulaParamsPacker paramsPacker) { if (Speed < Utils.ApproachZero) { throw new Exception("滑动碰撞检测的速度不能小于等于0"); } // 替换数据 ReplaceData(paramsPacker); // 数据本地化 var mySpeed = Speed; var myCheckTime = CheckTime; var myLength = Length; var myTargetCamps = TargetCamps; var myFormulaType = FormulaType; var myTargetPos = TargetPos; var myStartPos = StartPos; var clusterData = paramsPacker.ReleaseMember.ClusterData; // 上一次列表 List <FormulaParamsPacker> prvPackerList = new List <FormulaParamsPacker>(); IList <FormulaParamsPacker> tmpPackerList = null; IFormula result = new Formula((callback, scope) => { // 当前长度 var nowLength = 0f; // 目标点 var targetPos = GetPosByType(myTargetPos, paramsPacker, scope); // 起始点 var startPos = GetPosByType(myStartPos, paramsPacker, scope); // 计时器 var timer = new Timer(myCheckTime, true); // 计时器行为 Action completeCallback = () => { // 是否到达目标 if (nowLength < Length) { // 搜索位置+1 nowLength += mySpeed; // 从发射位置向目标位置一节一节搜索目标 // 速度影响单次搜索的长度 var diffPos = targetPos - startPos; var pos = (diffPos) * nowLength / myLength + startPos; // 创建图形 var diffPosNoY = new Vector3(diffPos.x, 0, diffPos.z); // 求旋转角度 var rotation = Vector3.Angle(Vector3.forward, diffPosNoY); // 求旋转方向 float dir = (Vector3.Dot(Vector3.up, Vector3.Cross(Vector3.forward, diffPosNoY)) < 0 ? 1 : -1); // 获得图形 var graphics = new RectGraphics(new Vector2(pos.x, pos.z), Width, mySpeed, rotation * dir); Utils.DrawGraphics(graphics, Color.white); // 搜索当前节范围内的单位 tmpPackerList = FormulaParamsPackerFactroy.Single.GetFormulaParamsPackerList(graphics, startPos, myTargetCamps, paramsPacker.Skill, paramsPacker.TargetMaxCount); // 执行子技能 if (tmpPackerList != null && tmpPackerList.Count > 0 && SubFormulaItem != null) { // 排除不可选择目标 for (var i = 0; i < tmpPackerList.Count; i++) { var nowPacker = tmpPackerList[i]; if (!TargetSelecter.CouldSelectTarget(clusterData, nowPacker.ReceiverMenber.ClusterData)) { tmpPackerList.RemoveAt(i); i--; } } // 排除上次被攻击过的目标 bool isExist; for (var j = 0; j < prvPackerList.Count; j++) { isExist = false; var prvPacker = prvPackerList[j]; // 判断是否存在上次被攻击的对象 // 从列表中删除重复对象 for (var i = 0; i < tmpPackerList.Count; i++) { var nowPacker = tmpPackerList[i]; if (prvPacker.ReceiverMenber.Equals(nowPacker.ReceiverMenber)) { // 删除本次攻击中上次攻击存在的单位 tmpPackerList.RemoveAt(i); i--; isExist = true; break; } } // 删除上次攻击中本次攻击不存在的单位 if (!isExist) { prvPackerList.RemoveAt(j); j--; } } prvPackerList.AddRange(tmpPackerList); foreach (var packer in tmpPackerList) { var subSkill = new SkillInfo(packer.SkillNum); FormulaParamsPackerFactroy.Single.CopyPackerData(paramsPacker, packer); subSkill.DataList = paramsPacker.DataList; subSkill.AddActionFormulaItem(SubFormulaItem); //subSkill.GetFormula(packer); SkillManager.Single.DoSkillInfo(subSkill, packer, true); } } } else { // 结束计时 timer.Kill(); // 完成回调 callback(); } }; timer.OnCompleteCallback(completeCallback); timer.Start(); }, myFormulaType); return(result); }