private void BuildPathForNode(BattlefieldTile pathNode) { BattlefieldTile currentNode = pathNode; while (currentNode != null) { Debug.Assert(_path.IndexOf(currentNode) == -1); //Debug.Assert(currentNode.ReservedForMove == null); Debug.Assert((_path.Count == 0) || currentNode.IsNeighbourTile(_path.Last())); _path.Add(currentNode); currentNode = currentNode.PriorTile; } _path.Reverse(); _path.RemoveAt(0); }
// Поиск пути public bool Pathfind(BattlefieldTile fromTile, BattlefieldTile toTile, BattleParticipant throughPlayer) { Debug.Assert(fromTile != null); Debug.Assert(toTile != null); Debug.Assert(fromTile != toTile); _path = new List <BattlefieldTile>();// Наиболее легкий найденный путь // Если это соседняя ячейка, то не надо искать путь if (fromTile.IsNeighbourTile(toTile)) { // Если клетка зарезервирована или на ней есть юнит, идти на нее нельзя if ((toTile.ReservedForMove != null) || (toTile.Unit != null)) { return(false); } _path.Add(toTile); return(true); } // Если режим прохода сквозь юнита, то проверяем, есть ли вокруг ячейки для прохода // Если нет, выходиим if (throughPlayer != null) { bool foundedFree = false; foreach (BattlefieldTile t in fromTile.TilesAround) { if ((t.Unit == null) && (t.ReservedForMove == null)) { foundedFree = true; break; } } if (!foundedFree) { return(false); } } // Очистка данных foreach (BattlefieldTile t in closedSet) { t.ClearPathData(); } closedSet.Clear(); foreach (BattlefieldTile t in openSet) { t.ClearPathData(); } openSet.Clear(); // Ищем путь FindPath(fromTile, toTile, throughPlayer); Debug.Assert((_path.Count() == 0) || fromTile.IsNeighbourTile(_path.First())); Debug.Assert((_path.Count() == 0) || (_path.Last() == toTile)); return(_path.Count() > 0); }
//internal int MoveStepPaa // Делает шаг битвы internal void DoStepBattle(Battle b) { Debug.Assert(IsLive == true); Debug.Assert(CurrentTile != null); priorState = State; if (inRollbackAfterAction == false) { switch (State) { case StateHeroInBattle.None: Debug.Assert(Target == null); Debug.Assert(countAction == 0); Debug.Assert(CurrentHealth > 0); Debug.Assert(IsLive == true); // Если сейчас ничего не выполняем, ищем, что можно сделать // Сначала пробуем атаковать стрелковым оружием if (((PlayerHero.RangeWeapon != null) && (QuantityArrows > 0)) || (PlayerHero.TypeCreature.ID == "Cleric") || (PlayerHero.TypeCreature.ID == "Mage")) { bool underMeleeAttack = false; // Если юнит не атакован врукопашную, можно атаковать стрелковой атакой foreach (HeroInBattle h in b.ActiveHeroes) { if ((h != this) && (h.Target == this) && (h.State == StateHeroInBattle.MeleeAttack)) { underMeleeAttack = true; break; } } if (!underMeleeAttack) { SearchTargetForShoot(); } } if (Target == null) { if (!SearchTargetForMelee()) { // Если целей нет, идем к ней if (Target == null) { if (SearchTargetForMove() == true) { State = StateHeroInBattle.Move; countAction = (int)(TimeMove() * 1.00 * ((TileForMove.X != 0) && (TileForMove.Y != 0) ? 1.4 : 1)); timeAction = countAction; inRollbackAfterAction = false; //State = StateHeroInBattle.PrepareMove; } } } } break; case StateHeroInBattle.MeleeAttack: countAction--; if (Target.State != StateHeroInBattle.Tumbstone) { if (countAction == 0) { // Делаем удар по противнику Target.GetDamage(CalcDamageMelee(Target), CalcDamageShoot(Target), CalcDamageMagic(Target)); LastTarget = Target.Coord; Target = null; // После удара делаем паузу длиной во время атаки countAction = TimeAttack(); inRollbackAfterAction = true; } } else { // Противника уже убили, пропускаем ход LastTarget = Target.Coord; Target = null; State = StateHeroInBattle.None; countAction = timeAction - countAction; timeAction = countAction; inRollbackAfterAction = true; } break; case StateHeroInBattle.RangeAttack: case StateHeroInBattle.Cast: countAction--; if (Target.State != StateHeroInBattle.Tumbstone) { if (countAction == 0) { // Делаем удар по противнику LastTarget = Target.Coord; Target = null; // После удара делаем паузу длиной во время атаки countAction = TimeAttack(); inRollbackAfterAction = true; } } else { // Противника уже убили, пропускаем ход LastTarget = Target.Coord; Target = null; State = StateHeroInBattle.None; countAction = timeAction - countAction; timeAction = countAction; inRollbackAfterAction = true; } break; case StateHeroInBattle.Tumbstone: Debug.Assert(Target == null); countAction--; if (countAction == 0) { IsLive = false; State = StateHeroInBattle.Dead; currentTile.Unit = null; currentTile = null; } else { // Если осталось шагов меньше, чем шагов на исчезновение, то надо перерисовать иконку if (countAction <= FormMain.Config.UnitStepsTimeToDisappearance) { inDisappearance = true; needRedraw = true; } } break; case StateHeroInBattle.Move: Debug.Assert(TileForMove != null); Debug.Assert(TileForMove.Unit == null); countAction--; if (countAction == 0) { Debug.Assert(TileForMove.ReservedForMove == this); // Пришли на тайл Target = null; CurrentTile = TileForMove; TileForMove.ReservedForMove = null; TileForMove = null; if (PathToDestination.Count() > 1) { // Заново осматриваемся State = StateHeroInBattle.None; /*TileForMove = PathToDestination.First(); * PathToDestination.RemoveAt(0); * countAction = TimeMove(); * timeAction = countAction;*/ } else { // Пришли на конечный тайл State = StateHeroInBattle.None; } PathToDestination = null; DestinationForMove = null; } break; default: break; } } else { countAction--; if (countAction == 0) { LastTarget = default; State = StateHeroInBattle.None; inRollbackAfterAction = false; } } if (priorState != State) { needRedraw = true; } bool SearchTargetForMelee() { // Ищем, кого атаковать List <HeroInBattle> targets = new List <HeroInBattle>(); foreach (HeroInBattle h in b.ActiveHeroes) { // Собираем список вражеских героев вокруг себя if (h.IsLive == true) { if (h.Player != Player) { if (h.CurrentHealth > 0) { if (IsNeighbour(h) == true) { targets.Add(h); } } } } } if (targets.Count > 0) { Debug.Assert(this != targets[0]); State = StateHeroInBattle.MeleeAttack; Target = targets[0]; countAction = TimeAttack(); timeAction = countAction; return(true); } else { return(false); } } bool SearchTargetForShoot() { //Debug.Assert(PlayerHero.RangeWeapon != null); // Если герой, по которому стреляли, жив, атакуем его снова if ((lastAttackedHero != null) && (lastAttackedHero.CurrentHealth > 0)) { Target = lastAttackedHero; } else { // Ищем, кого атаковать List <HeroInBattle> targets = new List <HeroInBattle>(); foreach (HeroInBattle h in b.ActiveHeroes) { // Собираем список вражеских героев if (h.Player != Player) { if (h.CurrentHealth > 0) { targets.Add(h); } } } if (targets.Count > 0) { Debug.Assert(this != targets[0]); Target = targets[0];// targets[Battle.Rnd.Next(0, targets.Count - 1)]; } } if (Target != null) { State = StateHeroInBattle.RangeAttack; countAction = TimeAttack(); timeAction = countAction; lastAttackedHero = Target; // Создаем выстрел if (PlayerHero.RangeWeapon != null) { Debug.Assert(QuantityArrows > 0); Battle.Missiles.Add(new Arrow(this, Target.CurrentTile)); QuantityArrows--; } else { Battle.Missiles.Add(new MagicStrike(this, Target.CurrentTile)); } return(true); } else { return(false); } } bool IsNeighbour(HeroInBattle hb) { Debug.Assert(this != hb); return(currentTile.IsNeighbourTile(hb.currentTile)); } }