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);
        }
Ejemplo n.º 3
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));
            }
        }