//向目标地点使用技能 public void UseSkill(List <BattleAction> actions, GridUnit target, BattleSkillAnalysis skillAnalysis) { if (target == null || skillAnalysis == null) { UtilityHelper.LogError("Use skill error, none target or skill"); return; } List <BattleHeroSkillResult> skillResults = new List <BattleHeroSkillResult>(); for (int i = 0; i < skillAnalysis.suitableUnits.Count; ++i) { //范围内的都受到伤害 if (target.Distance(skillAnalysis.suitableUnits[i].mapGrid) <= skillAnalysis.battleSkill.rangeRadius) { skillResults.Add(BattleCalculator.Instance.CalcSingle(this, skillAnalysis.suitableUnits[i], skillAnalysis.battleSkill)); } } //产生使用技能的动作 if (actions != null) { BattleHeroSkillAction action = new BattleHeroSkillAction(this, skillAnalysis.battleSkill.skillID); action.skillResult = skillResults.ToArray(); actions.Add(action); } //产生伤害 for (int i = 0; i < skillResults.Count; ++i) { skillResults[i].battleUnit.AcceptSkillResult(skillResults[i].syncAttribute, actions); } }
//点击了地块、战斗单位 -- 在当前是选择移动目标的情况下 private void OnBattleUnitAndGridTouched_StateMove(GridUnit gridTouched, BattleUnit battleUnitTouched) { //点中了战斗单位 if (battleUnitTouched != null) { //显示战斗单位的详情 UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } //点中了地图 else { //障碍物不能作为移动目标(暂时) if (gridTouched.GridType == GridType.Obstacle) { UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } else { //点击是否超出了范围 GridUnit fromGrid = manualOperatingBattleUnitRenderer.battleUnit.mapGrid; if (fromGrid.Distance(gridTouched) > manualOperatingBattleUnitRenderer.battleUnit.battleUnitAttribute.mobility) { UtilityHelper.Log("超出了移动半径!"); UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } else { //判断移动是否可以到达 bool result = MapNavigator.Instance.Navigate( fieldRenderer.battleField.battleMap, fromGrid, gridTouched, UtilityObjs.gridUnits, null, manualOperatingBattleUnitRenderer.battleUnit.battleUnitAttribute.mobility ); //判断是否可以到达(导航成功且可以可以到达) if (result && UtilityObjs.gridUnits[UtilityObjs.gridUnits.Count - 1].Equals(gridTouched)) { //可以到达 ManualMoveTo(gridTouched, UtilityObjs.gridUnits.ToArray()); UtilityObjs.gridUnits.Clear(); } else { //不可以到达 UtilityHelper.Log("点击位置不可到达!"); UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } } } } }
//自动选择目标 private void AutoSelectTarget(BattleUnitAction battleUnitAction) { int stopDistance = SkillStopDistance; //从仇恨列表中确定目标 BattleUnit hatredUnit = null; //按照仇恨列表获取目标 for (int i = 0; i < hatredRecorder.HatredCount; ++i) { hatredUnit = hatredRecorder.GetHatredByIdx(i, i == 0); if (!hatredUnit.CanAction) { //已经排序过了,找到不能行动的单位,就表示没有单位可以行动了 hatredUnit = null; break; } //判断这个单位是否可以到达 bool catched = false; //如果这个单位就在身边 if (mapGrid.Distance(hatredUnit.mapGrid) <= stopDistance) { toTargetPath.Clear(); catched = true; } else { catched = MapNavigator.Instance.Navigate( battleField.battleMap, mapGrid, hatredUnit.mapGrid, toTargetPath, null, battleUnitAttribute.mobility, stopDistance ); } //寻路不可达 if (!catched) { hatredUnit = null; continue; } //找到了 else { break; } } //没有目标 if (hatredUnit == null) { targetBattleUnit = null; return; } //判断是否切换目标 if (battleUnitAction != null && !hatredUnit.Equals(targetBattleUnit)) { battleUnitAction.changeTargetAction = BattleUnitChangeTargetAction.Get(); battleUnitAction.changeTargetAction.lastTargetUnit = targetBattleUnit; battleUnitAction.changeTargetAction.newTargetUnit = hatredUnit; targetBattleUnit = hatredUnit; } }
//搜索目标 private TargetSearchResult SearchTarget(List <BattleAction> actions) { //按照距离排序敌人 UtilityObjs.battleUnits.Clear(); //只考虑可以行动的 for (int i = 0; i < enemyTeam.battleUnits.Count; ++i) { if (enemyTeam.battleUnits[i].CanAction) { UtilityObjs.battleUnits.Add(enemyTeam.battleUnits[i]); } } //天下无敌了,还有谁?? if (UtilityObjs.battleUnits.Count == 0) { return(TargetSearchResult.Inexistence); } //结果类型 TargetSearchResult searchResult = TargetSearchResult.InRange; //按照距离排序 UtilityObjs.battleUnits.Sort(delegate(BattleUnit b1, BattleUnit b2) { return(mapGrid.Distance(b1.mapGrid) - mapGrid.Distance(b2.mapGrid)); }); //暂时不添加复杂的逻辑,只选择直线距离最近的 BattleUnit newTarget = null; GridUnit newTargetGrid = null; for (int i = 0; i < UtilityObjs.battleUnits.Count; ++i) { //如果当前目标就在范围内 if (mapGrid.Distance(UtilityObjs.battleUnits[i].mapGrid) <= 1) { //设置目标,但是不需要移动 newTarget = UtilityObjs.battleUnits[i]; toTargetPath.Clear(); targetGrid = null; searchResult = TargetSearchResult.InRange; break; } //目标不在周围需要移动 newTargetGrid = battleField.battleMap.GetEmptyGrid(mapGrid, UtilityObjs.battleUnits[i].mapGrid, toTargetPath, mobility); if (newTargetGrid == null) { //UtilityHelper.LogWarning(battleUnitID + "找不到空格子了,看看下一个吧"); continue; } else { newTarget = UtilityObjs.battleUnits[i]; searchResult = TargetSearchResult.NeedMove; break; } } if (newTarget == null) { UtilityHelper.LogWarning("确实找不到了"); targetBattleUnit = null; targetGrid = null; toTargetPath.Clear(); if (actions != null) { //创建一个warning BattleHeroWarningAction action = new BattleHeroWarningAction(this, "No target:" + battleUnitID); actions.Add(action); } return(TargetSearchResult.Inexistence); } //目标不一致,切换目标 if (targetBattleUnit != newTarget) { //切换目标 BattleHeroChangeTargetAction action = new BattleHeroChangeTargetAction(this); action.lastTargetUnit = targetBattleUnit; action.newTargetUnit = newTarget; //设置当前目标以及格子 targetBattleUnit = newTarget; actions.Add(action); } //移动的格子重新设置 targetGrid = newTargetGrid; return(searchResult); }
private void OnBattleUnitAndGridTouched(GridUnit gridTouched, BattleUnit battleUnitTouched) { //没有激活操作状态 if (manualOperationState == ManualOperationState.None) { //点中了战斗单位 if (battleUnitTouched != null) { //点中了等待手动操作的战斗单位 if (battleUnitTouched.battleUnitRenderer.Equals(manualBattleUnitRenderer)) { ShowManualActionList(); } else { UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } } //点中了地图 else { UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } } //选择移动状态 else if (manualOperationState == ManualOperationState.Move) { //点中了战斗单位 if (battleUnitTouched != null) { //点中了等待手动操作的战斗单位 if (battleUnitTouched.battleUnitRenderer.Equals(manualBattleUnitRenderer)) { //取消操作 manualOperationState = ManualOperationState.None; SetRangeHighlightActive(false, 0, 0, 0); } else { UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } } //点中了地图 else { if (gridTouched.GridType == GridType.Obstacle) { UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } else { //点击是否超出了范围 GridUnit fromGrid = manualBattleUnitRenderer.battleUnit.mapGrid; if (fromGrid.Distance(gridTouched) > manualBattleUnitRenderer.battleUnit.mobility) { Debug.Log("超出了移动半径!"); } else { bool result = MapNavigator.Instance.Navigate( battleField.battleMap, fromGrid, gridTouched, UtilityObjs.gridUnits, null, manualBattleUnitRenderer.battleUnit.mobility ); //判断是否可以到达(导航成功且可以可以到达) if (result && UtilityObjs.gridUnits[UtilityObjs.gridUnits.Count - 1].Equals(gridTouched)) { //可以到达 ManualMoveTo(gridTouched, UtilityObjs.gridUnits.ToArray()); UtilityObjs.gridUnits.Clear(); } else { //不可以到达 Debug.Log("点击位置不可到达!"); } } } } } //选择攻击目标状态 else if (manualOperationState == ManualOperationState.Skill) { //点中了战斗单位 if (battleUnitTouched != null) { //点中了等待手动操作的战斗单位 if (battleUnitTouched.battleUnitRenderer.Equals(manualBattleUnitRenderer)) { //取消操作 manualOperationState = ManualOperationState.None; SetRangeHighlightActive(false, 0, 0, 0); } else { //判断是否可以被攻击 if (manualBattleUnitRenderer.battleUnit.battleTeam.Equals(battleUnitTouched.battleTeam)) { //同一个队伍的 Debug.Log("攻击状态点中了同一个队伍的战斗单位:" + battleUnitTouched.ToString()); } else if (battleUnitTouched.mapGrid.Distance(manualBattleUnitRenderer.battleUnit.mapGrid) > 1) { Debug.Log("不在攻击范围:" + battleUnitTouched.ToString()); } else { ManualSkill(battleUnitTouched); } } } //点中了地图 else { Debug.Log("攻击状态点中了地图单位:" + gridTouched.ToString()); } } }
/// <summary> /// 导航至某个位置 /// </summary> /// <returns>The navigate.</returns> /// <param name="battleMap">地图</param> /// <param name="from">起始格子</param> /// <param name="to">目标格子</param> /// <param name="path">保存导航路径</param> /// <param name="searched">搜索过的路径</param> /// <param name="mobility">步数限制(移动区域半径)</param> /// <param name="stopDistance">距离目标的停止距离</param> /// <param name="containsTargetGrid">路径是否包含目标</param> public bool Navigate( BattleMap battleMap, GridUnit from, GridUnit to, List <GridUnit> path, List <GridUnit> searched = null, int mobility = -1, int stopDistance = 0) { //没有设置地图 if (battleMap == null) { return(false); } if (path != null) { path.Clear(); } if (searched != null) { searched.Clear(); } //这种情况基本上也就不用寻路了吧... if (to.runtimePasses == 0 && stopDistance <= 1 && from.Distance(to) > 1) { return(false); } //本来就在停止距离内 if (from.Distance(to) <= stopDistance) { return(true); } int tryTimes = battleMap.GridCount; List <NavigationData> opening = new List <NavigationData>(); opening.Add(GetEmptyNavigationData(from, null, 0, from.Distance(to))); int retry = 0; bool catched = false; //当前探索方向 int curDir = 0; //上次探索方向 int lastDir = 0; //每次检测方向的次数 int checkTimes = 0; //判断是否需要遍历open列表 NavigationData gift = null; //距离最近的格子(接下来要移动的) NavigationData next_0 = null; //距离次近的格子 NavigationData next_1 = null; int minStep = EGameConstL.Infinity; while (retry <= tryTimes && !catched) { ++retry; //从open中查找最近的节点 if (gift != null) { next_0 = gift; gift = null; } else if (next_1 != null) { next_0 = next_1; next_1 = null; } else { minStep = EGameConstL.Infinity; if (opening.Count == 0) { break; } for (int i = opening.Count - 1; i >= 0; --i) { if (!opening[i].open) { opening.RemoveAt(i); } else if (opening[i].F < minStep) { next_0 = opening[i]; minStep = next_0.F; } else if (next_1 == null && next_0 != null && opening[i].F == next_0.F) { next_1 = opening[i]; } } } //标志为已关闭 next_0.open = false; //放入已搜索中 if (searched != null) { searched.Add(next_0.thisGrid); } checkTimes = 6; curDir = lastDir; //遍历最近节点的周围6个节点,依次放入close中 int roads = next_0.thisGrid.NavigationPassable ? 63 : next_0.thisGrid.roadPasses; while (checkTimes > 0) { //沿着当前探索方向继续探索 if ((roads & (1 << curDir)) != 0) { //获取该路通向的下一个item GridUnit sibling = battleMap.GetGridByDir(next_0.thisGrid.row, next_0.thisGrid.column, curDir); if (sibling == null) { //没路 ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; continue; } //如果这个不能移动 else if (sibling.GridType == GridType.Obstacle && !sibling.NavigationPassable) { //没路 ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; continue; } //如果这个格子有战斗单位且可以战斗 else if (sibling.battleUnit != null && sibling.battleUnit.CanAction && !sibling.NavigationPassable) { //无法通过 ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; continue; } //如果这个item就是目标或者已经进入了停止距离 else if ((stopDistance > 0 && sibling.Distance(to) <= stopDistance) || sibling.Equals(to)) { catched = true; if (path != null) { path.Add(sibling); NavigationData current = next_0; while (current != null) { if (current.thisGrid != from) { path.Add(current.thisGrid); } current = current.preGrid; } //翻转一下 path.Reverse(); } break; } else { //尝试判断这个是否为closed NavigationData nd = sibling.tempRef == null ? null : (NavigationData)(sibling.tempRef); if (nd == null) { //这个格子没有探索过,新建并添加 nd = GetEmptyNavigationData(sibling, next_0, next_0.G + 1, sibling.Distance(to)); //这个格子不错哦 if (nd.F <= next_0.F && gift == null) { //保存礼物 gift = nd; //记录下次起始的更新方向 lastDir = curDir; } //比第二目标好 else if (next_1 != null && nd.F < next_1.F) { //替换第二目标 next_1 = nd; opening.Add(nd); } else { //已经设置了礼物,因此只能放入opening列表中,以后再更新了呢 opening.Add(nd); } } else { //只处理没有被探索过的格子 if (nd.open) { //已经在Open列表中了 if ((next_0.G + 1) < nd.G) { //比原来的近,应该不可能 nd.G = next_0.G + 1; nd.H = sibling.Distance(to); nd.F = nd.G + nd.H; nd.preGrid = next_0; nd.thisGrid = sibling; } //这个格子不错哦 if (nd.F <= next_0.F && gift == null) { gift = nd; //保存当前探索方向 lastDir = curDir; } else if (next_1 != null && nd.F < next_1.F) { //替换第二目标 next_1 = nd; } } } } } ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; } } opening.Clear(); //重置池子 ResetPool(); //有步数限制 if (catched && path != null && mobility > 0) { for (int i = 0; i < path.Count; ++i) { if (path[i].Distance(from) > mobility) { path.RemoveRange(i, path.Count - i); break; } } } return(catched); }
//检查是否在攻击范围 private bool CheckUnderAttackRadius() { return(mapGrid.Distance(targetBattleUnit.mapGrid) <= 1); }