Beispiel #1
0
        public int MaxConsecutiveSpellCast(Spell spell, int ap)
        {
            // can be casted indefinitly
            if (spell.CurrentSpellLevel.ApCost == 0 && spell.CurrentSpellLevel.MinCastInterval == 0)
            {
                return(0);
            }

            if (spell.CurrentSpellLevel.GlobalCooldown > 0)
            {
                return(1);
            }

            var max      = (int)(ap / spell.CurrentSpellLevel.ApCost);
            var category = SpellIdentifier.GetSpellCategories(spell);

            if ((category & SpellCategory.Summoning) != 0)
            {
                return(1);
            }

            if (spell.CurrentSpellLevel.MaxCastPerTarget > 0 &&
                max > spell.CurrentSpellLevel.MaxCastPerTarget)
            {
                max = (int)spell.CurrentSpellLevel.MaxCastPerTarget;
            }

            if (spell.CurrentSpellLevel.MaxCastPerTurn > 0 &&
                max > spell.CurrentSpellLevel.MaxCastPerTurn)
            {
                max = (int)spell.CurrentSpellLevel.MaxCastPerTurn;
            }

            return(max);
        }
Beispiel #2
0
        public bool GetRangeAttack(out int min, out int max)
        {
            bool hasRangeAttack = false;

            min = 0;
            max = 0;
            foreach (var spell in Fighter.Spells.Values)
            {
                var category = SpellIdentifier.GetSpellCategories(spell);
                if ((category & SpellCategory.Damages) != 0)
                {
                    if (min < spell.CurrentSpellLevel.MinRange)
                    {
                        min = (int)spell.CurrentSpellLevel.MinRange;
                    }

                    if (spell.CurrentSpellLevel.Range > max)
                    {
                        max = (int)spell.CurrentSpellLevel.Range;
                    }

                    hasRangeAttack = true;
                }
            }

            return(hasRangeAttack);
        }
Beispiel #3
0
        public AISpellCastPossibility FindFirstSpellCast()
        {
            var casts     = new List <AISpellCastPossibility>();
            var minUsedAP = 0;
            var minUsedPM = 0;

            foreach (var priority in Priorities.OrderByDescending(x => x.Value))
            {
                // find best spell
                var impactComparer = new SpellImpactComparer(this, priority.Key);
                foreach (var possibleCast in Possibilities.OrderByDescending(x => x, new SpellCastComparer(this, priority.Key)))
                {
                    var category = SpellIdentifier.GetSpellCategories(possibleCast.Spell);

                    var dummy = possibleCast;
                    if ((category & priority.Key) == 0 || casts.Any(x => x.Spell == dummy.Spell))   // spell already used
                    {
                        continue;
                    }

                    if (Fighter.AP - minUsedAP < possibleCast.Spell.CurrentSpellLevel.ApCost)
                    {
                        continue;
                    }

                    if (possibleCast.IsSummoningSpell)
                    {
                        var target = new SpellTarget()
                        {
                            Target = new TargetCell(possibleCast.SummonCell), CastCell = Fighter.Cell, AffectedCells = new [] { possibleCast.SummonCell }
                        };
                        casts.Add(new AISpellCastPossibility(possibleCast.Spell, target));
                        minUsedAP += (int)possibleCast.Spell.CurrentSpellLevel.ApCost;
                        continue;
                    }

                    // find best target
                    foreach (var impact in possibleCast.Impacts.OrderByDescending(x => x, impactComparer))
                    {
                        if (impactComparer.GetScore(impact) <= 0)
                        {
                            continue;
                        }

                        Cell castSpell = impact.CastCell;

                        var cast = new AISpellCastPossibility(possibleCast.Spell, impact);
                        if (castSpell == Fighter.Cell)
                        {
                            casts.Add(cast);
                            minUsedAP += (int)possibleCast.Spell.CurrentSpellLevel.ApCost;
                            continue;
                        }

                        var pathfinder = new Pathfinder(m_environment.CellInformationProvider);
                        var path       = pathfinder.FindPath(Fighter.Position.Cell.Id, castSpell.Id, false);

                        if (path.IsEmpty() || path.MPCost > Fighter.MP)
                        {
                            continue;
                        }

                        cast.MoveBefore = path;

                        casts.Add(cast);
                        minUsedAP += (int)possibleCast.Spell.CurrentSpellLevel.ApCost;
                        minUsedPM += path.MPCost;
                        break;
                    }
                }
            }

            if (casts.Count > 1)
            {
                // check if the second spell can be casted before
                var max = MaxConsecutiveSpellCast(casts[0].Spell, Fighter.AP);
                if (casts[1].Spell.CurrentSpellLevel.ApCost <= Fighter.AP - max * casts[0].Spell.CurrentSpellLevel.ApCost &&
                    casts[0].MoveBefore != null)
                {
                    if (casts[1].MoveBefore == null)
                    {
                        return(casts[1]);
                    }

                    var pathfinder = new Pathfinder(m_environment.CellInformationProvider);
                    var path       = pathfinder.FindPath(casts[1].MoveBefore.EndCell.Id, casts[0].MoveBefore != null ? casts[0].MoveBefore.EndCell.Id : Fighter.Cell.Id, false);

                    if (!path.IsEmpty() && path.MPCost + casts[1].MPCost <= Fighter.MP)
                    {
                        return(casts[1]);
                    }
                }
            }

            return(casts.FirstOrDefault());
        }
Beispiel #4
0
        public void AnalysePossibilities()
        {
            Possibilities = new List <SpellCastImpact>();
            foreach (var spell in Fighter.Spells.Values)
            {
                var category   = SpellIdentifier.GetSpellCategories(spell);
                var spellLevel = spell.CurrentSpellLevel;
                var cast       = new SpellCastImpact(spell);

                if (Fighter.AP < spellLevel.ApCost)
                {
                    continue;
                }

                if (spellLevel.StatesForbidden.Any(Fighter.HasState))
                {
                    continue;
                }

                if (spellLevel.StatesRequired.Any(state => !Fighter.HasState(state)))
                {
                    continue;
                }

                if (!Fighter.SpellHistory.CanCastSpell(spell.CurrentSpellLevel))
                {
                    continue;
                }

                // summoning is the priority
                if ((category & SpellCategory.Summoning) != 0 &&
                    ((category & SpellCategory.Healing) == 0 || Fighter.Team.Fighters.Any(x => x.IsDead())) &&                      // revive effect and an ally is dead
                    (Fighter.CanSummon() || (category & SpellCategory.Healing) != 0 && Fighter.Team.Fighters.Any(x => x.IsDead()))) // can summon or is revive spell
                {
                    var adjacentCell = Fighter.GetCastZoneSet(spell.CurrentSpellLevel, Fighter.Position.Point).EnumerateValidPoints().
                                       OrderBy(x => x.ManhattanDistanceTo(Fighter.Position.Point)).
                                       FirstOrDefault(x => m_environment.CellInformationProvider.IsCellWalkable(x.CellId));

                    if (adjacentCell == null)
                    {
                        continue;
                    }

                    cast.IsSummoningSpell = true;
                    cast.SummonCell       = Fighter.Map.Cells[adjacentCell.CellId];
                }
                else
                {
                    var cells =
                        ExpandCellsZone(Fighter.Fight.Fighters.Where(fighter => fighter.IsAlive() && fighter.IsVisibleFor(Fighter))
                                        .Select(x => x.Cell).ToArray(), spell);

                    foreach (var target in cells)
                    {
                        if (!CanReach(target, spell, out var cell))
                        {
                            continue;
                        }

                        if (Fighter.CanCastSpell(new SpellCastInformations(Fighter, spell, target.Cell)
                        {
                            CastCell = cell
                        }) != SpellCastResult.OK)
                        {
                            continue;
                        }

                        var impact = ComputeSpellImpact(spell, target.Cell, cell);

                        if (impact == null)
                        {
                            continue;
                        }

                        impact.CastCell = cell;
                        impact.Target   = target;

                        if (impact.Damage < 0)
                        {
                            continue; // hurts more allies than boost them
                        }
                        cast.Impacts.Add(impact);
                    }
                }

                if (cast.Impacts.Count > 0 || cast.IsSummoningSpell)
                {
                    Possibilities.Add(cast);
                }
            }

            AnalysePossibilitiesFinished?.Invoke(Fighter);
        }
Beispiel #5
0
        public IEnumerable <SpellCast> EnumerateSpellsCast()
        {
            Func <MapPoint, uint> keySelector = null;

            foreach (KeyValuePair <SpellCategory, int> iteratorVariable0 in from x in this.Priorities
                     orderby x.Value descending
                     select x)
            {
                SpellImpactComparer comparer = new SpellImpactComparer(this, iteratorVariable0.Key);
                foreach (SpellCastInformations iteratorVariable2 in this.Possibilities.OrderBy <SpellCastInformations, SpellCastInformations>(x => x, new SpellCastComparer(this, iteratorVariable0.Key)))
                {
                    SpellCategory spellCategories = SpellIdentifier.GetSpellCategories(iteratorVariable2.Spell);
                    if ((spellCategories & ((SpellCategory)iteratorVariable0.Key)) != SpellCategory.None)
                    {
                        if (this.Fighter.AP == 0)
                        {
                            break;
                        }
                        if (iteratorVariable2.MPToUse <= this.Fighter.MP)
                        {
                            if (iteratorVariable2.IsSummoningSpell)
                            {
                                yield return(new SpellCast(iteratorVariable2.Spell, iteratorVariable2.SummonCell));
                            }
                            else
                            {
                                foreach (SpellTarget iteratorVariable4 in iteratorVariable2.Impacts.OrderByDescending <SpellTarget, SpellTarget>(x => x, comparer))
                                {
                                    int iteratorVariable5;
                                    if (this.CanReach(iteratorVariable4.Target, iteratorVariable2.Spell, out iteratorVariable5))
                                    {
                                        SpellCast iteratorVariable6 = new SpellCast(iteratorVariable2.Spell, iteratorVariable4.Target.Cell);
                                        if (iteratorVariable5 == 0)
                                        {
                                            yield return(iteratorVariable6);
                                        }
                                        else if (iteratorVariable5 <= this.Fighter.MP)
                                        {
                                            if (keySelector == null)
                                            {
                                                keySelector = entry => entry.DistanceToCell(this.Fighter.Position.Point);
                                            }
                                            MapPoint point = iteratorVariable4.Target.Position.Point.GetAdjacentCells(new Func <short, bool>(this.m_environment.CellInformationProvider.IsCellWalkable)).OrderBy <MapPoint, uint>(keySelector).FirstOrDefault <MapPoint>();
                                            if (point == null)
                                            {
                                                point = iteratorVariable4.Target.Position.Point;
                                            }
                                            Path iteratorVariable9 = new Pathfinder(this.m_environment.CellInformationProvider).FindPath(this.Fighter.Position.Cell.Id, point.CellId, false, this.Fighter.MP);
                                            if (!iteratorVariable9.IsEmpty() && (iteratorVariable9.MPCost <= this.Fighter.MP))
                                            {
                                                iteratorVariable6.MoveBefore = iteratorVariable9;
                                                yield return(iteratorVariable6);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #6
0
 public void AnalysePossibilities()
 {
     this.Possibilities = new System.Collections.Generic.List <SpellCastInformations>();
     foreach (Spell current in this.Fighter.Spells.Values)
     {
         SpellCategory         spellCategories       = SpellIdentifier.GetSpellCategories(current);
         SpellLevelTemplate    currentSpellLevel     = current.CurrentSpellLevel;
         SpellCastInformations spellCastInformations = new SpellCastInformations(current);
         if ((long)this.Fighter.AP >= (long)((ulong)currentSpellLevel.ApCost) && !currentSpellLevel.StatesForbidden.Any(new Func <int, bool>(this.Fighter.HasState)))
         {
             if (!currentSpellLevel.StatesRequired.Any((int state) => !this.Fighter.HasState(state)) && this.Fighter.SpellHistory.CanCastSpell(current.CurrentSpellLevel))
             {
                 if ((spellCategories & SpellCategory.Summoning) != SpellCategory.None && this.Fighter.CanSummon())
                 {
                     Cell freeAdjacentCell = this.m_environment.GetFreeAdjacentCell();
                     if (freeAdjacentCell == null)
                     {
                         continue;
                     }
                     spellCastInformations.IsSummoningSpell = true;
                     spellCastInformations.SummonCell       = freeAdjacentCell;
                 }
                 else
                 {
                     foreach (FightActor current2 in
                              from fighter in this.Fighter.Fight.Fighters
                              where fighter.IsAlive() && fighter.IsVisibleFor(this.Fighter)
                              select fighter)
                     {
                         int mPToUse;
                         if (this.CanReach(current2, current, out mPToUse) && this.Fighter.SpellHistory.CanCastSpell(current.CurrentSpellLevel, current2.Cell))
                         {
                             spellCastInformations.MPToUse = mPToUse;
                             SpellTarget spellTarget = this.ComputeSpellImpact(current, current2);
                             if (spellTarget != null)
                             {
                                 spellTarget.Target = current2;
                                 if (spellTarget.Damage >= 0.0)
                                 {
                                     spellCastInformations.Impacts.Add(spellTarget);
                                 }
                             }
                         }
                     }
                 }
                 this.Possibilities.Add(spellCastInformations);
             }
         }
     }
     if (Brain.Brain.DebugMode)
     {
         Debug.WriteLine(this.Fighter.Name);
         using (System.Collections.Generic.Dictionary <int, Spell> .ValueCollection.Enumerator enumerator = this.Fighter.Spells.Values.GetEnumerator())
         {
             while (enumerator.MoveNext())
             {
                 Spell spell = enumerator.Current;
                 Debug.WriteLine("Spell {0} ({1}) :: {2}", new object[]
                 {
                     spell.Template.Name,
                     spell.Id,
                     SpellIdentifier.GetSpellCategories(spell)
                 });
                 System.Collections.Generic.IEnumerable <SpellCastInformations> arg_2C4_0 = this.Possibilities;
                 Func <SpellCastInformations, bool> predicate = (SpellCastInformations x) => x.Spell == spell;
                 SpellCastInformations spellCastInformations2 = arg_2C4_0.FirstOrDefault(predicate);
                 if (spellCastInformations2 != null)
                 {
                     if (spellCastInformations2.IsSummoningSpell)
                     {
                         Debug.WriteLine("\tSummon Spell");
                     }
                     else
                     {
                         ObjectDumper objectDumper = new ObjectDumper(8);
                         objectDumper.MemberPredicate = ((System.Reflection.MemberInfo member) => !member.Name.Contains("Target"));
                         ObjectDumper objectDumper2 = objectDumper;
                         Debug.WriteLine("\t{0} Targets", new object[]
                         {
                             spellCastInformations2.Impacts.Count
                         });
                         foreach (SpellTarget spellTarget in spellCastInformations2.Impacts)
                         {
                             Debug.Write(objectDumper2.DumpElement(spellTarget));
                             if (spellTarget.Target != null)
                             {
                                 Debug.WriteLine("\t\tTarget = " + spellTarget.Target + spellTarget.Target.Id.ToString());
                             }
                         }
                     }
                 }
             }
         }
         Debug.WriteLine("");
     }
 }