Beispiel #1
0
        private void PlaceToWeakestEnemy()
        {
            var enemy = m_character.GetOpposedTeam().Fighters.OrderBy(x => x.Level).FirstOrDefault();

            if (enemy == null)
            {
                logger.Warn("PlaceToWeakestEnemy : enemy is null");
                return;
            }

            var cell = Bot.Character.Fighter.Team.PlacementCells.OrderBy(x => x.ManhattanDistanceTo(enemy.Cell)).FirstOrDefault();

            Bot.Character.Fighter.ChangePrePlacement(cell);
        }
Beispiel #2
0
        public DamageType GetTotalDamageOnAllEnemies(PlayedFighter caster)
        {
            DamageType damages = 0;

            foreach (Fighter enemy in caster.Team == null ? caster.Fight.AliveActors : caster.GetOpposedTeam().FightersAlive)
            {
                SpellImpact impact = null;
                foreach (var effect in LevelTemplate.effects)
                {
                    damages += CumulEffects(effect, ref impact, caster, enemy /*, Spell.SpellCategory.Damages*/, this);
                }
            }
            return(damages);
        }
Beispiel #3
0
        /// <summary>
        /// Reset old PathFinding path from the cells.
        /// </summary>
        public void ClearLogic(short[] startingCells, short[] exitCells)
        {
            // Reset some information about the cells.
            foreach (CellInfo cell in _cells)
            {
                if (cell != null)
                {
                    cell.DistanceSteps = CellInfo.DEFAULT_DISTANCE;
                    cell.IsInPath      = cell.IsCloseToEnemy = false;
                    cell.IsOpen        = null;
                }
            }
            PathResult   = new List <short>();
            StartingCell = CellInfo.CELL_ERROR;
            ExitCell     = CellInfo.CELL_ERROR;
            if (_isCautious || _isInFight)
            {
                // Find cells of all enemies on the map
                IEnumerable <Cell> enemyCells;
                if (_isInFight)
                {
                    PlayedFighter player = _map.Actors.OfType <PlayedFighter>().FirstOrDefault();
                    if (player != null)
                    {
                        enemyCells = player.GetOpposedTeam().FightersAlive.Select(fighter => fighter.Cell);
                    }
                    else
                    {
                        enemyCells = null;
                    }
                }
                else
                {
                    enemyCells = _map.Actors.OfType <GroupMonster>().Select(fighter => fighter.Cell);
                }

                // Remove (/starting and) exit cells from those
                if (enemyCells != null && startingCells != null)
                {
                    //if (startingCells.Length > 0)
                    //    enemyCells = enemyCells.Except(startingCells.Select(cellid => _cells[cellid].Cell));
                    if (exitCells != null && exitCells.Length > 0)
                    {
                        enemyCells = enemyCells.Except(exitCells.Select(cellid => _cells[cellid].Cell));
                    }

                    // Then for each remainding cell, set all surrouding cells as "isCloseToEnemy"
                    PlayedFighter playedFighter = null;
                    if (_map is Fight)
                    {
                        playedFighter = (_map as Fight).CurrentPlayer as PlayedFighter;
                        //if (playedFighter != null)
                        //    playedFighter.Character.ResetCellsHighlight();
                    }
                    foreach (var cellid in enemyCells.Where(cell => cell != null).SelectMany(cell => cell.GetAdjacentCells()).Select(cell => cell.Id))
                    {
                        if (_cells[cellid] != null)
                        {
                            //if (playedFighter != null)
                            //    playedFighter.Character.HighlightCell(cellid, System.Drawing.Color.Black);
                            _cells[cellid].IsCloseToEnemy = true;
                        }
                    }
                }
            }
        }
Beispiel #4
0
        // Find where the PC should come to cast the spell, and the best target there (todo : optimize if needed)
        public SpellTarget FindBestTarget(PlayedFighter pc, IEnumerable <Cell> sourceCells, IEnumerable <Fighter> actors, Spell.SpellCategory category)
        {
            if (LevelTemplate.statesForbidden != null)
            {
                if (LevelTemplate.statesForbidden.Any(state => pc.HasState(state)))
                {
                    logger.Debug("Spell {0} skipped : statesForbidden {1}", this, string.Join(",", LevelTemplate.statesForbidden));
                    pc.Character.SendWarning("Spell {0} skipped : statesForbidden {1}", this, string.Join(",", LevelTemplate.statesForbidden));
                    return(null); // Can't cast this : all the required states are not on the caster
                }
            }
            if (LevelTemplate.statesRequired != null)
            {
                if (!LevelTemplate.statesRequired.All(state => pc.HasState(state)))
                {
                    logger.Debug("Spell {0} skipped : statesRequired {1}", this, string.Join(",", LevelTemplate.statesForbidden));
                    pc.Character.SendWarning("Spell {0} skipped : statesRequired {1}", this, string.Join(",", LevelTemplate.statesForbidden));
                    return(null); // Can't cast this : at least one required state is not on the caster
                }
            }
            if (IsMaitrise(null)) // If the spell is a maitrise, then ignore it if not of the proper type for equipped weapon.
            {
                Weapon weapon = pc.Character.Inventory.GetEquippedWeapon();
                if (weapon == null)
                {
                    return(null);
                }
                if (!IsMaitrise(weapon.typeId))
                {
                    return(null);
                }
            }
            _losMap = new LOSMap(pc.Fight);
            SpellTarget bestResult = null;

            #region optimisations
            IEnumerable <Fighter> enemies = pc.GetOpposedTeam().FightersAlive;
            IEnumerable <Fighter> friends = pc.Team.FightersAlive;

            bool goodSpell = (Categories & (SpellCategory.Buff | SpellCategory.Healing)) != 0;
            bool badSpell  = (Categories & (SpellCategory.Damages | SpellCategory.Curse)) != 0;
            IEnumerable <Fighter> targets = null;
            int targetsCount = 0;
            if (goodSpell && badSpell)
            {
                goodSpell = badSpell = false;
            }
            else
            {
                targets      = goodSpell ? friends : enemies;
                targetsCount = targets.Count();
            }
            uint surface = this.GetArea(category);
            efficiencyCache = null;
            if (!areaDependsOnDirection)
            {
                efficiencyCache = new Dictionary <short, int>();
            }
            #endregion
            if (surface == 1 && LevelTemplate.range == 0) // Hack fast Cure and protect self
            {
                var res = GetSpellDamages(pc, pc);
                if (res.Damage > 0)
                {
                    bestResult = new SpellTarget(res.Damage, pc.Cell, pc.Cell, this);
                }
            }
            else
            {
                foreach (Cell source in sourceCells)
                {
                    IEnumerable <Cell> destCells = GetCellsAtSpellRange(pc, source, actors);
                    if (goodSpell || badSpell)
                    {
                        if (surface <= 1 && LevelTemplate.range > 0)
                        {
                            destCells = destCells.Intersect(targets.Select(fighter => fighter.Cell)); // for spells that have an area of effect of 1, just find enemies or friends as targets. No need to scan all the range.
                        }
                    }
                    if (surface >= 560 && destCells.Count() > 1) // For spells that cover the full map, use only the first cell
                    {
                        destCells = destCells.Take(1);
                    }
                    SpellTarget newResult = FindBestTarget(pc, source, destCells, actors, category);
                    if (newResult == null || newResult.Efficiency <= 0)
                    {
                        continue;
                    }
                    if (bestResult == null || bestResult.Efficiency < newResult.Efficiency)
                    {
                        bestResult = newResult;
                        if (surface >= 560)
                        {
                            break;                 // if spell covers all map, and we have some hit, then no need to continue (first source cells are nearest)
                        }
                        if (targetsCount == 1 && surface == 1)
                        {
                            break;                                    // only one target and 1 cell area spell => no need to loop further
                        }
                    }
                }
            }
            if (bestResult != null)
            {
                bestResult.Efficiency *= (pc.Stats.CurrentAP / LevelTemplate.apCost);
                bestResult.cast        = false;
            }

            return(bestResult);
        }