Пример #1
0
        private async Task <SpellCastingResults> MoveToCastSpellOnEmptyCell(Spell spell, SpellLevels spellLevel)
        {
            // We'll move to cast the spell (if we can) with the least number of MP possible
            KeyValuePair <short, MoveNode>?node = null;
            int pmUsed = 99;

            foreach (var kvp in FightsPathfinder.GetReachableZone(_account.Game.Fight, _account.Game.Map.Data, _account.Game.Fight.PlayedFighter.CellId))
            {
                if (!kvp.Value.Reachable)
                {
                    continue;
                }

                // Only choose the safe paths
                // TODO: Maybe in the futur try to cast the spell even with tackle cost, in a LanguageManager.Translate("66") way of course
                if (kvp.Value.Path.Ap > 0 || kvp.Value.Path.Mp > 0)
                {
                    continue;
                }

                //if (spell.HandToHand && MapPoint.FromCellId(kvp.Key).DistanceToCell(MapPoint.FromCellId())
                //    continue;

                var range = _account.Game.Fight.GetSpellRange(kvp.Key, spellLevel);
                for (int i = 0; i < range.Count; i++)
                {
                    if (_account.Game.Fight.CanLaunchSpell(spell.SpellId, kvp.Key, range[i]) != SpellInabilityReasons.NONE)
                    {
                        continue;
                    }

                    if (kvp.Value.Path.Reachable.Count < pmUsed)
                    {
                        node   = kvp;
                        pmUsed = kvp.Value.Path.Reachable.Count;
                    }
                }
            }

            if (node != null)
            {
                _account.Logger.LogDebug(LanguageManager.Translate("52"), LanguageManager.Translate("63", node.Value.Key, spell.SpellName));
                await _account.Game.Managers.Movements.MoveToCellInFight(node);

                return(SpellCastingResults.MOVED);
            }

            return(SpellCastingResults.NOT_CASTED);
        }
Пример #2
0
        private async Task <SpellCastingResults> MoveToCastSimpleSpell(Spell spell, FighterEntry target)
        {
            // We'll move to cast the spell (if we can) with the least number of MP possible
            KeyValuePair <short, MoveNode>?node = null;
            int pmUsed = 99;

            foreach (var kvp in FightsPathfinder.GetReachableZone(_account.Game.Fight, _account.Game.Map.Data, _account.Game.Fight.PlayedFighter.CellId))
            {
                if (!kvp.Value.Reachable)
                {
                    continue;
                }

                // Only choose the safe paths
                // TODO: Maybe in the futur try to cast the spell even with tackle cost, in a LanguageManager.Translate("66") way of course
                if (kvp.Value.Path.Ap > 0 || kvp.Value.Path.Mp > 0)
                {
                    continue;
                }

                if (spell.HandToHand && !_account.Game.Fight.IsHandToHandWithAnEnnemy(kvp.Key))
                {
                    continue;
                }

                if (_account.Game.Fight.CanLaunchSpell(spell.SpellId, kvp.Key, target.CellId) != SpellInabilityReasons.NONE)
                {
                    continue;
                }

                if (kvp.Value.Path.Reachable.Count <= pmUsed)
                {
                    node   = kvp;
                    pmUsed = kvp.Value.Path.Reachable.Count;
                }
            }

            if (node != null)
            {
                _account.Logger.LogDebug(LanguageManager.Translate("52"), LanguageManager.Translate("63", node.Value.Key, spell.SpellName));
                await _account.Game.Managers.Movements.MoveToCellInFight(node);

                return(SpellCastingResults.MOVED);
            }

            return(SpellCastingResults.NOT_CASTED);
        }
Пример #3
0
        public KeyValuePair <short, MoveNode>?GetNearestOrFarthestEndMoveNode(bool nearest, bool basedOnAllMonsters = true)
        {
            KeyValuePair <short, MoveNode>?node = null;
            int totalDistances = -1;
            int distance       = -1;

            // Include our current cell
            totalDistances = basedOnAllMonsters ?
                             GetTotalDistancesFromEnnemies(_account.Game.Fight.PlayedFighter.CellId) :
                             MapPoint.FromCellId(_account.Game.Fight.PlayedFighter.CellId).DistanceToCell(MapPoint.FromCellId(_account.Game.Fight.GetNearestEnnemy().CellId));

            foreach (var kvp in FightsPathfinder.GetReachableZone(_account.Game.Fight, _account.Game.Map.Data, _account.Game.Fight.PlayedFighter.CellId))
            {
                if (!kvp.Value.Reachable)
                {
                    continue;
                }

                int tempTotalDistances = basedOnAllMonsters ?
                                         GetTotalDistancesFromEnnemies(kvp.Key) :
                                         MapPoint.FromCellId(kvp.Key).DistanceToCell(MapPoint.FromCellId(_account.Game.Fight.GetNearestEnnemy().CellId));

                if ((nearest && tempTotalDistances <= totalDistances) || (!nearest && tempTotalDistances >= totalDistances))
                {
                    if (nearest)
                    {
                        node           = kvp;
                        totalDistances = tempTotalDistances;
                    }
                    // If we need to give the farthest cell, we might aswell give the one that uses the most available MP
                    else if (kvp.Value.Path.Reachable.Count >= distance)
                    {
                        node           = kvp;
                        totalDistances = tempTotalDistances;
                        distance       = kvp.Value.Path.Reachable.Count;
                    }
                }
            }

            return(node);
        }
Пример #4
0
        private async Task <SpellCastingResults> CastAOESpell(Spell spell)
        {
            if (spell.Target == SpellTargets.ALLY || spell.Target == SpellTargets.EMPTY_CELL)
            {
                return(SpellCastingResults.NOT_CASTED);
            }

            if (_account.Game.Fight.CanLaunchSpell(spell.SpellId) != SpellInabilityReasons.NONE)
            {
                return(SpellCastingResults.NOT_CASTED);
            }

            var         spellEntry = _account.Game.Character.GetSpell(spell.SpellId);
            Spells      spellData  = DataManager.Get <Spells>(spell.SpellId);
            SpellLevels spellLevel = DataManager.Get <SpellLevels>(spellData.SpellLevels[spellEntry.Level - 1]);

            // Get all the possible ranges
            Stopwatch             sw      = Stopwatch.StartNew();
            List <RangeNodeEntry> entries = new List <RangeNodeEntry>();
            RangeNodeEntry        entry;

            // Include our current cell
            entry = GetRangeNodeEntry(_account.Game.Fight.PlayedFighter.CellId, null, spell, spellLevel);
            if (entry.TouchedEnnemiesByCell.Count > 0)
            {
                entries.Add(entry);
            }

            foreach (var kvp in FightsPathfinder.GetReachableZone(_account.Game.Fight, _account.Game.Map.Data, _account.Game.Fight.PlayedFighter.CellId))
            {
                if (!kvp.Value.Reachable)
                {
                    continue;
                }

                if (kvp.Value.Ap > 0 || kvp.Value.Mp > 0)
                {
                    continue;
                }

                entry = GetRangeNodeEntry(kvp.Key, kvp.Value, spell, spellLevel);
                if (entry.TouchedEnnemiesByCell.Count > 0)
                {
                    entries.Add(entry);
                }
            }

            // Get a cell where we can hit the most
            // If we need to move, try to move with the least amount of mps (with the same number of touched ennemies of course)
            short cellId     = -1;
            short fromCellId = -1;
            KeyValuePair <short, MoveNode>?node = null;
            byte touchedEnnemies = 0;
            int  usedMps         = 99;

            for (int i = 0; i < entries.Count; i++)
            {
                foreach (var kvp in entries[i].TouchedEnnemiesByCell)
                {
                    // Check for HandToHand
                    if (spell.HandToHand && !_account.Game.Fight.IsHandToHandWithAnEnnemy(entries[i].FromCellId))
                    {
                        continue;
                    }

                    // Check if we can cast the spell first
                    if (_account.Game.Fight.CanLaunchSpell(spell.SpellId, entries[i].FromCellId, kvp.Key) != SpellInabilityReasons.NONE)
                    {
                        continue;
                    }

                    // >= in case a cell uses less pm
                    if (kvp.Value >= touchedEnnemies)
                    {
                        // If its the same number of touched ennemies, check for the amount of mp we will use
                        //if (kvp.Value > touchedEnnemies || (kvp.Value == touchedEnnemies && entries[i].MpUsed < usedMps))
                        if (kvp.Value > touchedEnnemies || (kvp.Value == touchedEnnemies && entries[i].MpUsed <= usedMps))
                        {
                            touchedEnnemies = kvp.Value;
                            cellId          = kvp.Key;
                            fromCellId      = entries[i].FromCellId;
                            usedMps         = entries[i].MpUsed;
                            if (entries[i].Node != null)
                            {
                                node = new KeyValuePair <short, MoveNode>(fromCellId, entries[i].Node);
                            }
                        }
                    }
                }
            }

            if (cellId != -1)
            {
                // If node is null, it means that the chosen cellId is within range, so we don't have to move
                if (node == null)
                {
                    _account.Logger.LogDebug(LanguageManager.Translate("52"), LanguageManager.Translate("62", spell.SpellName, touchedEnnemies, cellId));
                    await _account.Game.Fight.LaunchSpell(spell.SpellId, cellId);

                    return(SpellCastingResults.CASTED);
                }
                // We need to move
                else
                {
                    _account.Logger.LogDebug(LanguageManager.Translate("52"), LanguageManager.Translate("63", fromCellId, spell.SpellName));

                    // Set the spell to cast
                    _spellIdToCast   = spell.SpellId;
                    _targetCellId    = cellId;
                    _ennemiesTouched = touchedEnnemies;

                    await _account.Game.Managers.Movements.MoveToCellInFight(node);

                    return(SpellCastingResults.MOVED);
                }
            }

            return(SpellCastingResults.NOT_CASTED);
        }